|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include <QtTest/QtTest> |
|
43 |
|
44 #include "qtcontacts.h" |
|
45 #include "qcontactchangeset.h" |
|
46 #include "qcontactmanagerdataholder.h" |
|
47 |
|
48 QTM_USE_NAMESPACE |
|
49 // Eventually these will make it into qtestcase.h |
|
50 // but we might need to tweak the timeout values here. |
|
51 #ifndef QTRY_COMPARE |
|
52 #define QTRY_COMPARE(__expr, __expected) \ |
|
53 do { \ |
|
54 const int __step = 50; \ |
|
55 const int __timeout = 5000; \ |
|
56 if ((__expr) != (__expected)) { \ |
|
57 QTest::qWait(0); \ |
|
58 } \ |
|
59 for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ |
|
60 QTest::qWait(__step); \ |
|
61 } \ |
|
62 QCOMPARE(__expr, __expected); \ |
|
63 } while(0) |
|
64 #endif |
|
65 |
|
66 #ifndef QTRY_VERIFY |
|
67 #define QTRY_VERIFY(__expr) \ |
|
68 do { \ |
|
69 const int __step = 50; \ |
|
70 const int __timeout = 5000; \ |
|
71 if (!(__expr)) { \ |
|
72 QTest::qWait(0); \ |
|
73 } \ |
|
74 for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ |
|
75 QTest::qWait(__step); \ |
|
76 } \ |
|
77 QVERIFY(__expr); \ |
|
78 } while(0) |
|
79 #endif |
|
80 |
|
81 |
|
82 #define QTRY_WAIT(code, __expr) \ |
|
83 do { \ |
|
84 const int __step = 50; \ |
|
85 const int __timeout = 5000; \ |
|
86 if (!(__expr)) { \ |
|
87 QTest::qWait(0); \ |
|
88 } \ |
|
89 for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ |
|
90 do { code } while(0); \ |
|
91 QTest::qWait(__step); \ |
|
92 } \ |
|
93 } while(0) |
|
94 |
|
95 #define QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(params) params.remove(QString::fromAscii(QTCONTACTS_VERSION_NAME)); \ |
|
96 params.remove(QString::fromAscii(QTCONTACTS_IMPLEMENTATION_VERSION_NAME)) |
|
97 |
|
98 //TESTED_CLASS= |
|
99 //TESTED_FILES= |
|
100 |
|
101 // to get QFETCH to work with the template expression... |
|
102 typedef QMap<QString,QString> tst_QContactManager_QStringMap; |
|
103 Q_DECLARE_METATYPE(tst_QContactManager_QStringMap) |
|
104 Q_DECLARE_METATYPE(QList<QContactLocalId>) |
|
105 |
|
106 /* A class that no backend can support */ |
|
107 class UnsupportedMetatype { |
|
108 int foo; |
|
109 }; |
|
110 Q_DECLARE_METATYPE(UnsupportedMetatype) |
|
111 |
|
112 class tst_QContactManager : public QObject |
|
113 { |
|
114 Q_OBJECT |
|
115 |
|
116 public: |
|
117 tst_QContactManager(); |
|
118 virtual ~tst_QContactManager(); |
|
119 |
|
120 private: |
|
121 void dumpContactDifferences(const QContact& a, const QContact& b); |
|
122 void dumpContact(const QContact &c); |
|
123 void dumpContacts(QContactManager *cm); |
|
124 bool isSuperset(const QContact& ca, const QContact& cb); |
|
125 QList<QContactDetail> removeAllDefaultDetails(const QList<QContactDetail>& details); |
|
126 void addManagers(); // add standard managers to the data |
|
127 QContact createContact(QContactDetailDefinition nameDef, QString firstName, QString lastName, QString phoneNumber); |
|
128 void setContactName(QContactDetailDefinition nameDef, QContactName& contactName, const QString &name) const; |
|
129 |
|
130 QContactManagerDataHolder managerDataHolder; |
|
131 |
|
132 public slots: |
|
133 void init(); |
|
134 void cleanup(); |
|
135 private slots: |
|
136 |
|
137 void doDump(); |
|
138 void doDump_data() {addManagers();} |
|
139 |
|
140 void doDumpSchema(); |
|
141 void doDumpSchema_data() {addManagers();} |
|
142 |
|
143 /* Special test with special data */ |
|
144 void uriParsing(); |
|
145 void nameSynthesis(); |
|
146 |
|
147 /* Tests that are run on all managers */ |
|
148 void metadata(); |
|
149 void nullIdOperations(); |
|
150 void add(); |
|
151 void update(); |
|
152 void remove(); |
|
153 void batch(); |
|
154 void signalEmission(); |
|
155 void detailDefinitions(); |
|
156 void displayName(); |
|
157 void actionPreferences(); |
|
158 void selfContactId(); |
|
159 void detailOrders(); |
|
160 void relationships(); |
|
161 void contactType(); |
|
162 |
|
163 /* Tests that take no data */ |
|
164 void contactValidation(); |
|
165 void errorStayingPut(); |
|
166 void ctors(); |
|
167 void invalidManager(); |
|
168 void memoryManager(); |
|
169 void changeSet(); |
|
170 |
|
171 /* data providers (mostly all engines) */ |
|
172 void uriParsing_data(); // Special data |
|
173 void nameSynthesis_data(); // Special data |
|
174 void metadata_data() {addManagers();} |
|
175 void nullIdOperations_data() {addManagers();} |
|
176 void add_data() {addManagers();} |
|
177 void update_data() {addManagers();} |
|
178 void remove_data() {addManagers();} |
|
179 void batch_data() {addManagers();} |
|
180 void signalEmission_data() {addManagers();} |
|
181 void detailDefinitions_data() {addManagers();} |
|
182 void displayName_data() {addManagers();} |
|
183 void actionPreferences_data() {addManagers();} |
|
184 void selfContactId_data() {addManagers();} |
|
185 void detailOrders_data() {addManagers();} |
|
186 void relationships_data() {addManagers();} |
|
187 void contactType_data() {addManagers();} |
|
188 }; |
|
189 |
|
190 tst_QContactManager::tst_QContactManager() |
|
191 { |
|
192 } |
|
193 |
|
194 tst_QContactManager::~tst_QContactManager() |
|
195 { |
|
196 } |
|
197 |
|
198 void tst_QContactManager::init() |
|
199 { |
|
200 /* Make sure these other test plugins are NOT loaded by default */ |
|
201 // These are now removed from the list of managers in addManagers() |
|
202 //QVERIFY(!QContactManager::availableManagers().contains("testdummy")); |
|
203 //QVERIFY(!QContactManager::availableManagers().contains("teststaticdummy")); |
|
204 //QVERIFY(!QContactManager::availableManagers().contains("maliciousplugin")); |
|
205 } |
|
206 |
|
207 void tst_QContactManager::cleanup() |
|
208 { |
|
209 } |
|
210 |
|
211 void tst_QContactManager::dumpContactDifferences(const QContact& ca, const QContact& cb) |
|
212 { |
|
213 // Try to narrow down the differences |
|
214 QContact a(ca); |
|
215 QContact b(cb); |
|
216 |
|
217 QContactName n1 = a.detail(QContactName::DefinitionName); |
|
218 QContactName n2 = b.detail(QContactName::DefinitionName); |
|
219 |
|
220 // Check the name components in more detail |
|
221 QCOMPARE(n1.firstName(), n2.firstName()); |
|
222 QCOMPARE(n1.middleName(), n2.middleName()); |
|
223 QCOMPARE(n1.lastName(), n2.lastName()); |
|
224 QCOMPARE(n1.prefix(), n2.prefix()); |
|
225 QCOMPARE(n1.suffix(), n2.suffix()); |
|
226 QCOMPARE(n1.customLabel(), n2.customLabel()); |
|
227 |
|
228 // Check the display label |
|
229 QCOMPARE(a.displayLabel(), b.displayLabel()); |
|
230 |
|
231 // Now look at the rest |
|
232 QList<QContactDetail> aDetails = a.details(); |
|
233 QList<QContactDetail> bDetails = b.details(); |
|
234 |
|
235 // They can be in any order, so loop |
|
236 // First remove any matches |
|
237 foreach(QContactDetail d, aDetails) { |
|
238 foreach(QContactDetail d2, bDetails) { |
|
239 if(d == d2) { |
|
240 a.removeDetail(&d); |
|
241 b.removeDetail(&d2); |
|
242 break; |
|
243 } |
|
244 } |
|
245 } |
|
246 |
|
247 // Now dump the extra details that were unmatched in A (note that DisplayLabel and Type are always present). |
|
248 aDetails = a.details(); |
|
249 bDetails = b.details(); |
|
250 foreach(QContactDetail d, aDetails) { |
|
251 if (d.definitionName() != QContactDisplayLabel::DefinitionName && d.definitionName() != QContactType::DefinitionName) |
|
252 qDebug() << "A contact had extra detail:" << d.definitionName() << d.variantValues(); |
|
253 } |
|
254 // and same for B |
|
255 foreach(QContactDetail d, bDetails) { |
|
256 if (d.definitionName() != QContactDisplayLabel::DefinitionName && d.definitionName() != QContactType::DefinitionName) |
|
257 qDebug() << "B contact had extra detail:" << d.definitionName() << d.variantValues(); |
|
258 } |
|
259 |
|
260 // now test specifically the display label and the type |
|
261 if (a.displayLabel() != b.displayLabel()) { |
|
262 qDebug() << "A contact display label =" << a.displayLabel(); |
|
263 qDebug() << "B contact display label =" << b.displayLabel(); |
|
264 } |
|
265 if (a.type() != b.type()) { |
|
266 qDebug() << "A contact type =" << a.type(); |
|
267 qDebug() << "B contact type =" << b.type(); |
|
268 } |
|
269 } |
|
270 |
|
271 bool tst_QContactManager::isSuperset(const QContact& ca, const QContact& cb) |
|
272 { |
|
273 // returns true if contact ca is a superset of contact cb |
|
274 // we use this test instead of equality because dynamic information |
|
275 // such as presence/location, and synthesised information such as |
|
276 // display label and (possibly) type, may differ between a contact |
|
277 // in memory and the contact in the managed store. |
|
278 |
|
279 QContact a(ca); |
|
280 QContact b(cb); |
|
281 QList<QContactDetail> aDetails = a.details(); |
|
282 QList<QContactDetail> bDetails = b.details(); |
|
283 |
|
284 // They can be in any order, so loop |
|
285 // First remove any matches |
|
286 foreach(QContactDetail d, aDetails) { |
|
287 foreach(QContactDetail d2, bDetails) { |
|
288 if(d == d2) { |
|
289 a.removeDetail(&d); |
|
290 b.removeDetail(&d2); |
|
291 break; |
|
292 } |
|
293 } |
|
294 } |
|
295 |
|
296 // check for contact type updates |
|
297 if (!a.type().isEmpty()) |
|
298 if (!b.type().isEmpty()) |
|
299 if (a.type() != b.type()) |
|
300 return false; // nonempty type is different. |
|
301 |
|
302 // Now check to see if b has any details remaining; if so, a is not a superset. |
|
303 // Note that the DisplayLabel and Type can never be removed. |
|
304 if (b.details().size() > 2 |
|
305 || (b.details().size() == 2 && (b.details().value(0).definitionName() != QContactDisplayLabel::DefinitionName |
|
306 || b.details().value(1).definitionName() != QContactType::DefinitionName))) |
|
307 return false; |
|
308 return true; |
|
309 } |
|
310 |
|
311 void tst_QContactManager::dumpContact(const QContact& contact) |
|
312 { |
|
313 QContactManager m; |
|
314 qDebug() << "Contact: " << contact.id().localId() << "(" << m.synthesizedDisplayLabel(contact) << ")"; |
|
315 QList<QContactDetail> details = contact.details(); |
|
316 foreach(QContactDetail d, details) { |
|
317 qDebug() << " " << d.definitionName() << ":"; |
|
318 qDebug() << " Vals:" << d.variantValues(); |
|
319 } |
|
320 } |
|
321 |
|
322 void tst_QContactManager::dumpContacts(QContactManager *cm) |
|
323 { |
|
324 QList<QContactLocalId> ids = cm->contactIds(); |
|
325 |
|
326 qDebug() << "There are" << ids.count() << "contacts in" << cm->managerUri(); |
|
327 |
|
328 foreach(QContactLocalId id, ids) { |
|
329 QContact c = cm->contact(id); |
|
330 dumpContact(c); |
|
331 } |
|
332 } |
|
333 |
|
334 void tst_QContactManager::uriParsing_data() |
|
335 { |
|
336 QTest::addColumn<QString>("uri"); |
|
337 QTest::addColumn<bool>("good"); // is this a good uri or not |
|
338 QTest::addColumn<QString>("manager"); |
|
339 QTest::addColumn<QMap<QString, QString> >("parameters"); |
|
340 |
|
341 QMap<QString, QString> inparameters; |
|
342 inparameters.insert("foo", "bar"); |
|
343 inparameters.insert("bazflag", QString()); |
|
344 inparameters.insert("bar", "glob"); |
|
345 |
|
346 QMap<QString, QString> inparameters2; |
|
347 inparameters2.insert("this has spaces", QString()); |
|
348 inparameters2.insert("and& an", " &"); |
|
349 inparameters2.insert("and an ", "=quals"); |
|
350 |
|
351 QTest::newRow("built") << QContactManager::buildUri("manager", inparameters) << true << "manager" << inparameters; |
|
352 QTest::newRow("built with escaped parameters") << QContactManager::buildUri("manager", inparameters2) << true << "manager" << inparameters2; |
|
353 QTest::newRow("no scheme") << "this should not split" << false << QString() << tst_QContactManager_QStringMap(); |
|
354 QTest::newRow("wrong scheme") << "invalidscheme:foo bar" << false << QString() << tst_QContactManager_QStringMap(); |
|
355 QTest::newRow("right scheme, no colon") << "qtcontacts" << false << QString() << tst_QContactManager_QStringMap(); |
|
356 QTest::newRow("no manager, colon, no params") << "qtcontacts::" << false << "manager" << tst_QContactManager_QStringMap(); |
|
357 QTest::newRow("yes manager, no colon, no params") << "qtcontacts:manager" << true << "manager" << tst_QContactManager_QStringMap(); |
|
358 QTest::newRow("yes manager, yes colon, no params") << "qtcontacts:manager:" << true << "manager"<< tst_QContactManager_QStringMap(); |
|
359 QTest::newRow("yes params") << "qtcontacts:manager:foo=bar&bazflag=&bar=glob" << true << "manager" << inparameters; |
|
360 QTest::newRow("yes params but misformed") << "qtcontacts:manager:foo=bar&=gloo&bar=glob" << false << "manager" << inparameters; |
|
361 QTest::newRow("yes params but misformed 2") << "qtcontacts:manager:=&=gloo&bar=glob" << false << "manager" << inparameters; |
|
362 QTest::newRow("yes params but misformed 3") << "qtcontacts:manager:==" << false << "manager" << inparameters; |
|
363 QTest::newRow("yes params but misformed 4") << "qtcontacts:manager:&&" << false << "manager" << inparameters; |
|
364 QTest::newRow("yes params but misformed 5") << "qtcontacts:manager:&goo=bar" << false << "manager" << inparameters; |
|
365 QTest::newRow("yes params but misformed 6") << "qtcontacts:manager:goo&bar" << false << "manager" << inparameters; |
|
366 QTest::newRow("yes params but misformed 7") << "qtcontacts:manager:goo&bar&gob" << false << "manager" << inparameters; |
|
367 QTest::newRow("yes params but misformed 8") << "qtcontacts:manager:==&&==&goo=bar" << false << "manager" << inparameters; |
|
368 QTest::newRow("yes params but misformed 9") << "qtcontacts:manager:foo=bar=baz" << false << "manager" << inparameters; |
|
369 QTest::newRow("yes params but misformed 10") << "qtcontacts:manager:foo=bar=baz=glob" << false << "manager" << inparameters; |
|
370 QTest::newRow("no manager but yes params") << "qtcontacts::foo=bar&bazflag=&bar=glob" << false << QString() << inparameters; |
|
371 QTest::newRow("no manager or params") << "qtcontacts::" << false << QString() << inparameters; |
|
372 QTest::newRow("no manager or params or colon") << "qtcontacts:" << false << QString() << inparameters; |
|
373 } |
|
374 |
|
375 void tst_QContactManager::addManagers() |
|
376 { |
|
377 QTest::addColumn<QString>("uri"); |
|
378 |
|
379 QStringList managers = QContactManager::availableManagers(); |
|
380 |
|
381 /* Known one that will not pass */ |
|
382 managers.removeAll("invalid"); |
|
383 managers.removeAll("testdummy"); |
|
384 managers.removeAll("teststaticdummy"); |
|
385 managers.removeAll("maliciousplugin"); |
|
386 |
|
387 foreach(QString mgr, managers) { |
|
388 QMap<QString, QString> params; |
|
389 QTest::newRow(QString("mgr='%1'").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params); |
|
390 if (mgr == "memory") { |
|
391 params.insert("id", "tst_QContactManager"); |
|
392 QTest::newRow(QString("mgr='%1', params").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params); |
|
393 } |
|
394 } |
|
395 } |
|
396 |
|
397 /* |
|
398 * Helper method for creating a QContact instance with name and phone number |
|
399 * details. Name is generated according to the detail definition assuming that |
|
400 * either first and last name or custom label is supported. |
|
401 */ |
|
402 QContact tst_QContactManager::createContact( |
|
403 QContactDetailDefinition nameDef, |
|
404 QString firstName, |
|
405 QString lastName, |
|
406 QString phoneNumber) |
|
407 { |
|
408 QContact contact; |
|
409 |
|
410 if(!firstName.isEmpty() || !lastName.isEmpty()) { |
|
411 QContactName n; |
|
412 |
|
413 if(nameDef.fields().contains(QContactName::FieldFirstName) |
|
414 && nameDef.fields().contains(QContactName::FieldFirstName)) { |
|
415 n.setFirstName(firstName); |
|
416 n.setLastName(lastName); |
|
417 } else if(nameDef.fields().contains(QContactName::FieldCustomLabel)) { |
|
418 n.setCustomLabel(firstName + " " + lastName); |
|
419 } else { |
|
420 // assume that either first and last name or custom label is supported |
|
421 QTest::qWarn("Neither custom label nor first name/last name supported!"); |
|
422 return QContact(); |
|
423 } |
|
424 contact.saveDetail(&n); |
|
425 } |
|
426 |
|
427 if (!phoneNumber.isEmpty()) { |
|
428 QContactPhoneNumber ph; |
|
429 ph.setNumber(phoneNumber); |
|
430 contact.saveDetail(&ph); |
|
431 } |
|
432 |
|
433 return contact; |
|
434 } |
|
435 |
|
436 void tst_QContactManager::setContactName(QContactDetailDefinition nameDef, QContactName& contactName, const QString &name) const |
|
437 { |
|
438 // check which name fields are supported in the following order: |
|
439 // 1. custom label, 2. first name, 3. last name |
|
440 if(nameDef.fields().contains(QContactName::FieldCustomLabel)) { |
|
441 contactName.setCustomLabel(name); |
|
442 } else if(nameDef.fields().contains(QContactName::FieldFirstName)) { |
|
443 contactName.setFirstName(name); |
|
444 } else if(nameDef.fields().contains(QContactName::FieldLastName)) { |
|
445 contactName.setLastName(name); |
|
446 } else { |
|
447 // Assume that at least one of the above name fields is supported by the backend |
|
448 QVERIFY(false); |
|
449 } |
|
450 } |
|
451 |
|
452 void tst_QContactManager::metadata() |
|
453 { |
|
454 // ensure that the backend is publishing its metadata (name / parameters / uri) correctly |
|
455 QFETCH(QString, uri); |
|
456 QScopedPointer<QContactManager> cm(new QContactManager("memory")); |
|
457 QVERIFY(QContactManager::buildUri(cm->managerName(), cm->managerParameters()) == cm->managerUri()); |
|
458 } |
|
459 |
|
460 |
|
461 void tst_QContactManager::nullIdOperations() |
|
462 { |
|
463 QFETCH(QString, uri); |
|
464 QScopedPointer<QContactManager> cm(new QContactManager("memory")); |
|
465 QVERIFY(!cm->removeContact(QContactLocalId())); |
|
466 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
467 |
|
468 |
|
469 QContact c = cm->contact(QContactLocalId()); |
|
470 QVERIFY(c.id() == QContactId()); |
|
471 QVERIFY(c.isEmpty()); |
|
472 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
473 } |
|
474 |
|
475 void tst_QContactManager::uriParsing() |
|
476 { |
|
477 QFETCH(QString, uri); |
|
478 QFETCH(bool, good); |
|
479 QFETCH(QString, manager); |
|
480 QFETCH(tst_QContactManager_QStringMap, parameters); |
|
481 |
|
482 QString outmanager; |
|
483 QMap<QString, QString> outparameters; |
|
484 |
|
485 if (good) { |
|
486 /* Good split */ |
|
487 /* Test splitting */ |
|
488 QVERIFY(QContactManager::parseUri(uri, 0, 0)); // no out parms |
|
489 |
|
490 // 1 out param |
|
491 QVERIFY(QContactManager::parseUri(uri, &outmanager, 0)); |
|
492 QCOMPARE(manager, outmanager); |
|
493 QVERIFY(QContactManager::parseUri(uri, 0, &outparameters)); |
|
494 |
|
495 QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
|
496 |
|
497 QCOMPARE(parameters, outparameters); |
|
498 |
|
499 outmanager.clear(); |
|
500 outparameters.clear(); |
|
501 QVERIFY(QContactManager::parseUri(uri, &outmanager, &outparameters)); |
|
502 |
|
503 QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
|
504 |
|
505 QCOMPARE(manager, outmanager); |
|
506 QCOMPARE(parameters, outparameters); |
|
507 } else { |
|
508 /* bad splitting */ |
|
509 outmanager.clear(); |
|
510 outparameters.clear(); |
|
511 QVERIFY(QContactManager::parseUri(uri, 0, 0) == false); |
|
512 QVERIFY(QContactManager::parseUri(uri, &outmanager, 0) == false); |
|
513 QVERIFY(outmanager.isEmpty()); |
|
514 QVERIFY(QContactManager::parseUri(uri, 0, &outparameters) == false); |
|
515 QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
|
516 QVERIFY(outparameters.isEmpty()); |
|
517 |
|
518 /* make sure the in parameters don't change with a bad split */ |
|
519 outmanager = manager; |
|
520 outparameters = parameters; |
|
521 QVERIFY(QContactManager::parseUri(uri, &outmanager, 0) == false); |
|
522 QCOMPARE(manager, outmanager); |
|
523 QVERIFY(QContactManager::parseUri(uri, 0, &outparameters) == false); |
|
524 QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
|
525 QCOMPARE(parameters, outparameters); |
|
526 } |
|
527 } |
|
528 |
|
529 void tst_QContactManager::ctors() |
|
530 { |
|
531 /* test the different ctors to make sure we end up with the same uri */ |
|
532 QVERIFY(QContactManager::availableManagers().count() > 1); // invalid + something else |
|
533 QVERIFY(QContactManager::availableManagers().contains("invalid")); |
|
534 QString defaultStore = QContactManager::availableManagers().value(0); |
|
535 QVERIFY(defaultStore != "invalid"); |
|
536 |
|
537 qDebug() << "Available managers:" << QContactManager::availableManagers(); |
|
538 |
|
539 QMap<QString, QString> randomParameters; |
|
540 randomParameters.insert("something", "old"); |
|
541 randomParameters.insert("something...", "new"); |
|
542 randomParameters.insert("something ", "borrowed"); |
|
543 randomParameters.insert(" something", "blue"); |
|
544 |
|
545 QObject parent; |
|
546 |
|
547 QContactManager cm; // default |
|
548 QContactManager cm2(defaultStore); |
|
549 QContactManager cm3(defaultStore, QMap<QString, QString>()); |
|
550 QContactManager cm4(cm.managerUri()); // should fail |
|
551 |
|
552 QScopedPointer<QContactManager> cm5(QContactManager::fromUri(QContactManager::buildUri(defaultStore, QMap<QString, QString>()))); |
|
553 QScopedPointer<QContactManager> cm6(QContactManager::fromUri(cm.managerUri())); // uri is not a name; should fail. |
|
554 QScopedPointer<QContactManager> cm9(QContactManager::fromUri(QString(), &parent)); |
|
555 |
|
556 QVERIFY(cm9->parent() == &parent); |
|
557 |
|
558 /* OLD TEST WAS THIS: */ |
|
559 //QCOMPARE(cm.managerUri(), cm2.managerUri()); |
|
560 //QCOMPARE(cm.managerUri(), cm3.managerUri()); |
|
561 //QCOMPARE(cm.managerUri(), cm5->managerUri()); |
|
562 //QCOMPARE(cm.managerUri(), cm6->managerUri()); |
|
563 //QCOMPARE(cm.managerUri(), cm9->managerUri()); |
|
564 /* NEW TEST IS THIS: Test that the names of the managers are the same */ |
|
565 QCOMPARE(cm.managerName(), cm2.managerName()); |
|
566 QCOMPARE(cm.managerName(), cm3.managerName()); |
|
567 QCOMPARE(cm.managerName(), cm5->managerName()); |
|
568 QCOMPARE(cm.managerName(), cm6->managerName()); |
|
569 QCOMPARE(cm.managerName(), cm9->managerName()); |
|
570 |
|
571 QVERIFY(cm.managerUri() != cm4.managerUri()); // don't pass a uri to the ctor |
|
572 |
|
573 /* Test that we get invalid stores when we do silly things */ |
|
574 QContactManager em("non existent"); |
|
575 QContactManager em2("non existent", QMap<QString, QString>()); |
|
576 QContactManager em3("memory", randomParameters); |
|
577 |
|
578 /* Also invalid, since we don't have one of these anyway */ |
|
579 QScopedPointer<QContactManager> em4(QContactManager::fromUri("invalid uri")); |
|
580 QScopedPointer<QContactManager> em5(QContactManager::fromUri(QContactManager::buildUri("nonexistent", QMap<QString, QString>()))); |
|
581 QScopedPointer<QContactManager> em6(QContactManager::fromUri(em3.managerUri())); |
|
582 |
|
583 |
|
584 /* |
|
585 * Sets of stores that should be equivalent: |
|
586 * - 1, 2, 4, 5 |
|
587 * - 3, 6 |
|
588 */ |
|
589 |
|
590 /* First some URI testing for equivalent stores */ |
|
591 QVERIFY(em.managerUri() == em2.managerUri()); |
|
592 QVERIFY(em.managerUri() == em5->managerUri()); |
|
593 QVERIFY(em.managerUri() == em4->managerUri()); |
|
594 QVERIFY(em2.managerUri() == em4->managerUri()); |
|
595 QVERIFY(em2.managerUri() == em5->managerUri()); |
|
596 QVERIFY(em4->managerUri() == em5->managerUri()); |
|
597 |
|
598 QVERIFY(em3.managerUri() == em6->managerUri()); |
|
599 |
|
600 /* Test the stores that should not be the same */ |
|
601 QVERIFY(em.managerUri() != em3.managerUri()); |
|
602 QVERIFY(em.managerUri() != em6->managerUri()); |
|
603 |
|
604 /* now the components */ |
|
605 QCOMPARE(em.managerName(), QString("invalid")); |
|
606 QCOMPARE(em2.managerName(), QString("invalid")); |
|
607 QCOMPARE(em3.managerName(), QString("memory")); |
|
608 QCOMPARE(em4->managerName(), QString("invalid")); |
|
609 QCOMPARE(em5->managerName(), QString("invalid")); |
|
610 QCOMPARE(em6->managerName(), QString("memory")); |
|
611 QCOMPARE(em.managerParameters(), tst_QContactManager_QStringMap()); |
|
612 QCOMPARE(em2.managerParameters(), tst_QContactManager_QStringMap()); |
|
613 QCOMPARE(em4->managerParameters(), tst_QContactManager_QStringMap()); |
|
614 QCOMPARE(em5->managerParameters(), tst_QContactManager_QStringMap()); |
|
615 QCOMPARE(em3.managerParameters(), em6->managerParameters()); // memory engine discards the given params, replaces with id. |
|
616 |
|
617 |
|
618 // Finally test the platform specific engines are actually the defaults |
|
619 #if defined(Q_OS_SYMBIAN) |
|
620 QCOMPARE(defaultStore, QString("symbian")); |
|
621 #elif defined(Q_WS_MAEMO_6) |
|
622 QCOMPARE(defaultStore, QString("tracker")); |
|
623 #elif defined(Q_WS_MAEMO_5) |
|
624 QCOMPARE(defaultStore, QString("maemo5")); |
|
625 #elif defined(Q_OS_WINCE) |
|
626 QCOMPARE(defaultStore, QString("wince")); |
|
627 #else |
|
628 QCOMPARE(defaultStore, QString("memory")); |
|
629 #endif |
|
630 } |
|
631 |
|
632 void tst_QContactManager::doDump() |
|
633 { |
|
634 // Only do this if it has been explicitly selected |
|
635 if (QCoreApplication::arguments().contains("doDump")) { |
|
636 QFETCH(QString, uri); |
|
637 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
638 |
|
639 dumpContacts(cm.data()); |
|
640 } |
|
641 } |
|
642 |
|
643 Q_DECLARE_METATYPE(QVariant) |
|
644 |
|
645 void tst_QContactManager::doDumpSchema() |
|
646 { |
|
647 // Only do this if it has been explicitly selected |
|
648 if (QCoreApplication::arguments().contains("doDumpSchema")) { |
|
649 QFETCH(QString, uri); |
|
650 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
651 |
|
652 // Get the schema for each supported type |
|
653 foreach(QString type, cm->supportedContactTypes()) { |
|
654 QMap<QString, QContactDetailDefinition> defs = cm->detailDefinitions(type); |
|
655 |
|
656 foreach(QContactDetailDefinition def, defs.values()) { |
|
657 if (def.isUnique()) |
|
658 qDebug() << QString("%2::%1 (Unique) {").arg(def.name()).arg(type).toAscii().constData(); |
|
659 else |
|
660 qDebug() << QString("%2::%1 {").arg(def.name()).arg(type).toAscii().constData(); |
|
661 QMap<QString, QContactDetailFieldDefinition> fields = def.fields(); |
|
662 |
|
663 foreach(QString fname, fields.keys()) { |
|
664 QContactDetailFieldDefinition field = fields.value(fname); |
|
665 |
|
666 if (field.allowableValues().count() > 0) { |
|
667 // Make some pretty output |
|
668 QStringList allowedList; |
|
669 foreach(QVariant var, field.allowableValues()) { |
|
670 QString allowed; |
|
671 if (var.type() == QVariant::String) |
|
672 allowed = QString("'%1'").arg(var.toString()); |
|
673 else if (var.type() == QVariant::StringList) |
|
674 allowed = QString("'%1'").arg(var.toStringList().join(",")); |
|
675 else { |
|
676 // use the textstream << |
|
677 QDebug dbg(&allowed); |
|
678 dbg << var; |
|
679 } |
|
680 allowedList.append(allowed); |
|
681 } |
|
682 |
|
683 qDebug() << QString(" %2 %1 {%3}").arg(fname).arg(QMetaType::typeName(field.dataType())).arg(allowedList.join(",")).toAscii().constData(); |
|
684 } else |
|
685 qDebug() << QString(" %2 %1").arg(fname).arg(QMetaType::typeName(field.dataType())).toAscii().constData(); |
|
686 } |
|
687 |
|
688 qDebug() << "}"; |
|
689 } |
|
690 } |
|
691 } |
|
692 } |
|
693 |
|
694 void tst_QContactManager::add() |
|
695 { |
|
696 QFETCH(QString, uri); |
|
697 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
698 |
|
699 QContactDetailDefinition nameDef = cm->detailDefinition(QContactName::DefinitionName, QContactType::TypeContact); |
|
700 QContact alice = createContact(nameDef, "Alice", "inWonderland", "1234567"); |
|
701 int currCount = cm->contactIds().count(); |
|
702 QVERIFY(cm->saveContact(&alice)); |
|
703 QVERIFY(cm->error() == QContactManager::NoError); |
|
704 |
|
705 QVERIFY(alice.id() != QContactId()); |
|
706 QCOMPARE(cm->contactIds().count(), currCount+1); |
|
707 |
|
708 QContact added = cm->contact(alice.id().localId()); |
|
709 QVERIFY(added.id() != QContactId()); |
|
710 QVERIFY(added.id() == alice.id()); |
|
711 |
|
712 if (!isSuperset(added, alice)) { |
|
713 dumpContacts(cm.data()); |
|
714 dumpContactDifferences(added, alice); |
|
715 QCOMPARE(added, alice); |
|
716 } |
|
717 |
|
718 // now try adding a contact that does not exist in the database with non-zero id |
|
719 QContact nonexistent = createContact(nameDef, "nonexistent", "contact", ""); |
|
720 QVERIFY(cm->saveContact(&nonexistent)); // should work |
|
721 QVERIFY(cm->removeContact(nonexistent.id().localId())); // now nonexistent has an id which does not exist |
|
722 QVERIFY(!cm->saveContact(&nonexistent)); // hence, should fail |
|
723 QCOMPARE(cm->error(), QContactManager::DoesNotExistError); |
|
724 nonexistent.setId(QContactId()); |
|
725 QVERIFY(cm->saveContact(&nonexistent)); // after setting id to zero, should save |
|
726 QVERIFY(cm->removeContact(nonexistent.id().localId())); |
|
727 |
|
728 // now try adding a "megacontact" |
|
729 // - get list of all definitions supported by the manager |
|
730 // - add one detail of each definition to a contact |
|
731 // - save the contact |
|
732 // - read it back |
|
733 // - ensure that it's the same. |
|
734 QContact megacontact; |
|
735 QMap<QString, QContactDetailDefinition> defmap = cm->detailDefinitions(); |
|
736 QList<QContactDetailDefinition> defs = defmap.values(); |
|
737 foreach (const QContactDetailDefinition def, defs) { |
|
738 |
|
739 // Leave these warnings here - might need an API for this |
|
740 if (def.accessConstraint() == QContactDetailDefinition::ReadOnly) { |
|
741 continue; |
|
742 } |
|
743 |
|
744 // otherwise, create a new detail of the given type and save it to the contact |
|
745 QContactDetail det(def.name()); |
|
746 QMap<QString, QContactDetailFieldDefinition> fieldmap = def.fields(); |
|
747 QStringList fieldKeys = fieldmap.keys(); |
|
748 foreach (const QString& fieldKey, fieldKeys) { |
|
749 // get the field, and check to see that it's not constrained. |
|
750 QContactDetailFieldDefinition currentField = fieldmap.value(fieldKey); |
|
751 |
|
752 // Attempt to create a worthy value |
|
753 if (!currentField.allowableValues().isEmpty()) { |
|
754 // we want to save a value that will be accepted. |
|
755 if (currentField.dataType() == QVariant::StringList) |
|
756 det.setValue(fieldKey, QStringList() << currentField.allowableValues().first().toString()); |
|
757 else if (currentField.dataType() == QVariant::List) |
|
758 det.setValue(fieldKey, QVariantList() << currentField.allowableValues().first()); |
|
759 else |
|
760 det.setValue(fieldKey, currentField.allowableValues().first()); |
|
761 } else { |
|
762 // any value of the correct type will be accepted |
|
763 bool savedSuccessfully = false; |
|
764 QVariant dummyValue = QVariant(fieldKey); // try to get some unique string data |
|
765 if (dummyValue.canConvert(currentField.dataType())) { |
|
766 savedSuccessfully = dummyValue.convert(currentField.dataType()); |
|
767 if (savedSuccessfully) { |
|
768 // we have successfully created a (supposedly) valid field for this detail. |
|
769 det.setValue(fieldKey, dummyValue); |
|
770 continue; |
|
771 } |
|
772 } |
|
773 |
|
774 // nope, couldn't save the string value (test); try a date. |
|
775 dummyValue = QVariant(QDate::currentDate()); |
|
776 if (dummyValue.canConvert(currentField.dataType())) { |
|
777 savedSuccessfully = dummyValue.convert(currentField.dataType()); |
|
778 if (savedSuccessfully) { |
|
779 // we have successfully created a (supposedly) valid field for this detail. |
|
780 det.setValue(fieldKey, dummyValue); |
|
781 continue; |
|
782 } |
|
783 } |
|
784 |
|
785 // nope, couldn't convert a string or a date - try the integer value (42) |
|
786 dummyValue = QVariant(42); |
|
787 if (dummyValue.canConvert(currentField.dataType())) { |
|
788 savedSuccessfully = dummyValue.convert(currentField.dataType()); |
|
789 if (savedSuccessfully) { |
|
790 // we have successfully created a (supposedly) valid field for this detail. |
|
791 det.setValue(fieldKey, dummyValue); |
|
792 continue; |
|
793 } |
|
794 } |
|
795 |
|
796 // if we get here, we don't know what sort of value can be saved... |
|
797 } |
|
798 } |
|
799 megacontact.saveDetail(&det); |
|
800 } |
|
801 |
|
802 QVERIFY(cm->saveContact(&megacontact)); // must be able to save since built from definitions. |
|
803 QContact retrievedMegacontact = cm->contact(megacontact.id().localId()); |
|
804 if (retrievedMegacontact != megacontact) { |
|
805 dumpContactDifferences(megacontact, retrievedMegacontact); |
|
806 QEXPECT_FAIL("mgr='wince'", "Address Display Label mismatch", Continue); |
|
807 QCOMPARE(megacontact, retrievedMegacontact); |
|
808 } |
|
809 |
|
810 // now a contact with many details of a particular definition |
|
811 // this will fail on some backends; how do we query for this capability? |
|
812 QContact veryContactable = createContact(nameDef, "Very", "Contactable", ""); |
|
813 for (int i = 0; i < 50; i++) { |
|
814 QString phnStr = QString::number(i); |
|
815 QContactPhoneNumber vcphn; |
|
816 vcphn.setNumber(phnStr); |
|
817 QVERIFY(veryContactable.saveDetail(&vcphn)); |
|
818 } |
|
819 |
|
820 // check that all the numbers were added successfully, and that it can be saved. |
|
821 QVERIFY(veryContactable.details(QContactPhoneNumber::DefinitionName).size() == 50); |
|
822 QVERIFY(cm->saveContact(&veryContactable)); |
|
823 QContact retrievedContactable = cm->contact(veryContactable.id().localId()); |
|
824 if (retrievedContactable != veryContactable) { |
|
825 dumpContactDifferences(veryContactable, retrievedContactable); |
|
826 QEXPECT_FAIL("mgr='wince'", "Number of phones supported mismatch", Continue); |
|
827 QCOMPARE(veryContactable, retrievedContactable); |
|
828 } |
|
829 } |
|
830 |
|
831 void tst_QContactManager::update() |
|
832 { |
|
833 QFETCH(QString, uri); |
|
834 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
835 |
|
836 /* Save a new contact first */ |
|
837 QContactDetailDefinition nameDef = cm->detailDefinition(QContactName::DefinitionName, QContactType::TypeContact); |
|
838 QContact alice = createContact(nameDef, "Alice", "inWonderland", "1234567"); |
|
839 QVERIFY(cm->saveContact(&alice)); |
|
840 QVERIFY(cm->error() == QContactManager::NoError); |
|
841 |
|
842 /* Update name */ |
|
843 QContactName name = alice.detail(QContactName::DefinitionName); |
|
844 setContactName(nameDef, name, "updated"); |
|
845 alice.saveDetail(&name); |
|
846 QVERIFY(cm->saveContact(&alice)); |
|
847 QVERIFY(cm->error() == QContactManager::NoError); |
|
848 QContact updated = cm->contact(alice.localId()); |
|
849 QContactName updatedName = updated.detail(QContactName::DefinitionName); |
|
850 QCOMPARE(updatedName, name); |
|
851 |
|
852 if (cm->hasFeature(QContactManager::Groups)) { |
|
853 // Try changing types - not allowed |
|
854 // from contact -> group |
|
855 alice.setType(QContactType::TypeGroup); |
|
856 QContactName na = alice.detail(QContactName::DefinitionName); |
|
857 alice.removeDetail(&na); |
|
858 QVERIFY(!cm->saveContact(&alice)); |
|
859 QVERIFY(cm->error() == QContactManager::AlreadyExistsError); |
|
860 |
|
861 // from group -> contact |
|
862 QContact jabberwock = createContact(nameDef, "", "", "1234567890"); |
|
863 jabberwock.setType(QContactType::TypeGroup); |
|
864 QVERIFY(cm->saveContact(&jabberwock)); |
|
865 jabberwock.setType(QContactType::TypeContact); |
|
866 QVERIFY(!cm->saveContact(&jabberwock)); |
|
867 QVERIFY(cm->error() == QContactManager::AlreadyExistsError); |
|
868 } |
|
869 } |
|
870 |
|
871 void tst_QContactManager::remove() |
|
872 { |
|
873 QFETCH(QString, uri); |
|
874 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
875 |
|
876 /* Save a new contact first */ |
|
877 QContactDetailDefinition nameDef = cm->detailDefinition(QContactName::DefinitionName, QContactType::TypeContact); |
|
878 QContact alice = createContact(nameDef, "Alice", "inWonderland", "1234567"); |
|
879 QVERIFY(cm->saveContact(&alice)); |
|
880 QVERIFY(cm->error() == QContactManager::NoError); |
|
881 QVERIFY(alice.id() != QContactId()); |
|
882 |
|
883 /* Remove the created contact */ |
|
884 const int contactCount = cm->contactIds().count(); |
|
885 QVERIFY(cm->removeContact(alice.localId())); |
|
886 QCOMPARE(cm->contactIds().count(), contactCount - 1); |
|
887 QVERIFY(cm->contact(alice.localId()).isEmpty()); |
|
888 QCOMPARE(cm->error(), QContactManager::DoesNotExistError); |
|
889 } |
|
890 |
|
891 void tst_QContactManager::batch() |
|
892 { |
|
893 QFETCH(QString, uri); |
|
894 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
895 |
|
896 /* First test null pointer operations */ |
|
897 QVERIFY(!cm->saveContacts(0, 0)); |
|
898 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
899 |
|
900 QVERIFY(!cm->removeContacts(0, 0)); |
|
901 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
902 |
|
903 /* Now add 3 contacts, all valid */ |
|
904 QContact a; |
|
905 QContactName na; |
|
906 na.setFirstName("XXXXXX Albert"); |
|
907 a.saveDetail(&na); |
|
908 |
|
909 QContact b; |
|
910 QContactName nb; |
|
911 nb.setFirstName("XXXXXX Bob"); |
|
912 b.saveDetail(&nb); |
|
913 |
|
914 QContact c; |
|
915 QContactName nc; |
|
916 nc.setFirstName("XXXXXX Carol"); |
|
917 c.saveDetail(&nc); |
|
918 |
|
919 QList<QContact> contacts; |
|
920 contacts << a << b << c; |
|
921 |
|
922 QMap<int, QContactManager::Error> errorMap; |
|
923 // Add one dummy error to test if the errors are reset |
|
924 errorMap.insert(0, QContactManager::NoError); |
|
925 QVERIFY(cm->saveContacts(&contacts, &errorMap)); |
|
926 QVERIFY(cm->error() == QContactManager::NoError); |
|
927 QVERIFY(errorMap.count() == 0); |
|
928 |
|
929 /* Make sure our contacts got updated too */ |
|
930 QVERIFY(contacts.count() == 3); |
|
931 QVERIFY(contacts.at(0).id() != QContactId()); |
|
932 QVERIFY(contacts.at(1).id() != QContactId()); |
|
933 QVERIFY(contacts.at(2).id() != QContactId()); |
|
934 |
|
935 QVERIFY(contacts.at(0).detail(QContactName::DefinitionName) == na); |
|
936 QVERIFY(contacts.at(1).detail(QContactName::DefinitionName) == nb); |
|
937 QVERIFY(contacts.at(2).detail(QContactName::DefinitionName) == nc); |
|
938 |
|
939 /* Retrieve again */ |
|
940 a = cm->contact(contacts.at(0).id().localId()); |
|
941 b = cm->contact(contacts.at(1).id().localId()); |
|
942 c = cm->contact(contacts.at(2).id().localId()); |
|
943 QVERIFY(contacts.at(0).detail(QContactName::DefinitionName) == na); |
|
944 QVERIFY(contacts.at(1).detail(QContactName::DefinitionName) == nb); |
|
945 QVERIFY(contacts.at(2).detail(QContactName::DefinitionName) == nc); |
|
946 |
|
947 /* Now make an update to them all */ |
|
948 QContactPhoneNumber number; |
|
949 number.setNumber("1234567"); |
|
950 |
|
951 QVERIFY(contacts[0].saveDetail(&number)); |
|
952 number.setNumber("234567"); |
|
953 QVERIFY(contacts[1].saveDetail(&number)); |
|
954 number.setNumber("34567"); |
|
955 QVERIFY(contacts[2].saveDetail(&number)); |
|
956 |
|
957 QVERIFY(cm->saveContacts(&contacts, &errorMap)); |
|
958 QVERIFY(cm->error() == QContactManager::NoError); |
|
959 QVERIFY(errorMap.count() == 0); |
|
960 |
|
961 /* Retrieve them and check them again */ |
|
962 a = cm->contact(contacts.at(0).id().localId()); |
|
963 b = cm->contact(contacts.at(1).id().localId()); |
|
964 c = cm->contact(contacts.at(2).id().localId()); |
|
965 QVERIFY(contacts.at(0).detail(QContactName::DefinitionName) == na); |
|
966 QVERIFY(contacts.at(1).detail(QContactName::DefinitionName) == nb); |
|
967 QVERIFY(contacts.at(2).detail(QContactName::DefinitionName) == nc); |
|
968 |
|
969 QVERIFY(a.details<QContactPhoneNumber>().count() == 1); |
|
970 QVERIFY(b.details<QContactPhoneNumber>().count() == 1); |
|
971 QVERIFY(c.details<QContactPhoneNumber>().count() == 1); |
|
972 |
|
973 QVERIFY(a.details<QContactPhoneNumber>().at(0).number() == "1234567"); |
|
974 QVERIFY(b.details<QContactPhoneNumber>().at(0).number() == "234567"); |
|
975 QVERIFY(c.details<QContactPhoneNumber>().at(0).number() == "34567"); |
|
976 |
|
977 /* Now delete them all */ |
|
978 QList<QContactLocalId> ids; |
|
979 QContactLocalId removedIdForLater = b.id().localId(); |
|
980 ids << a.id().localId() << b.id().localId() << c.id().localId(); |
|
981 QVERIFY(cm->removeContacts(&ids, &errorMap)); |
|
982 QVERIFY(errorMap.count() == 0); |
|
983 QVERIFY(cm->error() == QContactManager::NoError); |
|
984 |
|
985 /* Make sure all the ids are now 0 */ |
|
986 QVERIFY(ids.count() == 3); |
|
987 QVERIFY(ids.at(0) == 0); |
|
988 QVERIFY(ids.at(1) == 0); |
|
989 QVERIFY(ids.at(2) == 0); |
|
990 |
|
991 /* Make sure the contacts really don't exist any more */ |
|
992 QVERIFY(cm->contact(a.id().localId()).id() == QContactId()); |
|
993 QVERIFY(cm->contact(a.id().localId()).isEmpty()); |
|
994 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
995 QVERIFY(cm->contact(b.id().localId()).id() == QContactId()); |
|
996 QVERIFY(cm->contact(b.id().localId()).isEmpty()); |
|
997 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
998 QVERIFY(cm->contact(c.id().localId()).id() == QContactId()); |
|
999 QVERIFY(cm->contact(c.id().localId()).isEmpty()); |
|
1000 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
1001 |
|
1002 /* Now try removing with all invalid ids (e.g. the ones we just removed) */ |
|
1003 ids.clear(); |
|
1004 ids << a.id().localId() << b.id().localId() << c.id().localId(); |
|
1005 QVERIFY(!cm->removeContacts(&ids, &errorMap)); |
|
1006 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
1007 QVERIFY(errorMap.count() == 3); |
|
1008 QVERIFY(errorMap.values().at(0) == QContactManager::DoesNotExistError); |
|
1009 QVERIFY(errorMap.values().at(1) == QContactManager::DoesNotExistError); |
|
1010 QVERIFY(errorMap.values().at(2) == QContactManager::DoesNotExistError); |
|
1011 |
|
1012 /* Try adding some new ones again, this time one with an error */ |
|
1013 contacts.clear(); |
|
1014 a.setId(QContactId()); |
|
1015 b.setId(QContactId()); |
|
1016 c.setId(QContactId()); |
|
1017 |
|
1018 /* Make B the bad guy */ |
|
1019 QContactDetail bad("does not exist and will break if you add it"); |
|
1020 bad.setValue("This is also bad", "Very bad"); |
|
1021 b.saveDetail(&bad); |
|
1022 |
|
1023 contacts << a << b << c; |
|
1024 QVERIFY(!cm->saveContacts(&contacts, &errorMap)); |
|
1025 /* We can't really say what the error will be.. maybe bad argument, maybe invalid detail */ |
|
1026 QVERIFY(cm->error() != QContactManager::NoError); |
|
1027 |
|
1028 /* It's permissible to fail all the adds, or to add the successful ones */ |
|
1029 QVERIFY(errorMap.count() > 0); |
|
1030 QVERIFY(errorMap.count() <= 3); |
|
1031 |
|
1032 // A might have gone through |
|
1033 if (errorMap.keys().contains(0)) { |
|
1034 QVERIFY(errorMap.value(0) != QContactManager::NoError); |
|
1035 QVERIFY(contacts.at(0).id() == QContactId()); |
|
1036 } else { |
|
1037 QVERIFY(contacts.at(0).id() != QContactId()); |
|
1038 } |
|
1039 |
|
1040 // B should have failed |
|
1041 QVERIFY(errorMap.value(1) == QContactManager::InvalidDetailError); |
|
1042 QVERIFY(contacts.at(1).id() == QContactId()); |
|
1043 |
|
1044 // C might have gone through |
|
1045 if (errorMap.keys().contains(2)) { |
|
1046 QVERIFY(errorMap.value(2) != QContactManager::NoError); |
|
1047 QVERIFY(contacts.at(2).id() == QContactId()); |
|
1048 } else { |
|
1049 QVERIFY(contacts.at(2).id() != QContactId()); |
|
1050 } |
|
1051 |
|
1052 /* Fix up B and re save it */ |
|
1053 QVERIFY(contacts[1].removeDetail(&bad)); |
|
1054 QVERIFY(cm->saveContacts(&contacts, &errorMap)); |
|
1055 QVERIFY(errorMap.count() == 0); |
|
1056 QVERIFY(cm->error() == QContactManager::NoError); |
|
1057 |
|
1058 /* Now delete 3 items, but with one bad argument */ |
|
1059 ids.clear(); |
|
1060 ids << contacts.at(0).id().localId(); |
|
1061 ids << removedIdForLater; |
|
1062 ids << contacts.at(2).id().localId(); |
|
1063 |
|
1064 QVERIFY(!cm->removeContacts(&ids, &errorMap)); |
|
1065 QVERIFY(cm->error() != QContactManager::NoError); |
|
1066 |
|
1067 /* Again, the backend has the choice of either removing the successful ones, or not */ |
|
1068 QVERIFY(errorMap.count() > 0); |
|
1069 QVERIFY(errorMap.count() <= 3); |
|
1070 |
|
1071 // A might have gone through |
|
1072 if (errorMap.keys().contains(0)) { |
|
1073 QVERIFY(errorMap.value(0) != QContactManager::NoError); |
|
1074 QVERIFY(contacts.at(0).id() == QContactId()); |
|
1075 } else { |
|
1076 QVERIFY(contacts.at(0).id() != QContactId()); |
|
1077 } |
|
1078 |
|
1079 /* B should definitely have failed */ |
|
1080 QVERIFY(errorMap.value(1) == QContactManager::DoesNotExistError); |
|
1081 QVERIFY(ids.at(1) == removedIdForLater); |
|
1082 |
|
1083 // A might have gone through |
|
1084 if (errorMap.keys().contains(2)) { |
|
1085 QVERIFY(errorMap.value(2) != QContactManager::NoError); |
|
1086 QVERIFY(contacts.at(2).id() == QContactId()); |
|
1087 } else { |
|
1088 QVERIFY(contacts.at(2).id() != QContactId()); |
|
1089 } |
|
1090 } |
|
1091 |
|
1092 void tst_QContactManager::invalidManager() |
|
1093 { |
|
1094 /* Create an invalid manager */ |
|
1095 QContactManager manager("this should never work"); |
|
1096 QVERIFY(manager.managerName() == "invalid"); |
|
1097 QVERIFY(manager.managerVersion() == 0); |
|
1098 |
|
1099 /* also, test the other ctor behaviour is sane also */ |
|
1100 QContactManager anotherManager("this should never work", 15); |
|
1101 QVERIFY(anotherManager.managerName() == "invalid"); |
|
1102 QVERIFY(anotherManager.managerVersion() == 0); |
|
1103 |
|
1104 /* Now test that all the operations fail */ |
|
1105 QVERIFY(manager.contactIds().count() == 0); |
|
1106 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1107 |
|
1108 QContact foo; |
|
1109 QContactName nf; |
|
1110 nf.setLastName("Lastname"); |
|
1111 foo.saveDetail(&nf); |
|
1112 |
|
1113 QVERIFY(manager.synthesizedDisplayLabel(foo).isEmpty()); |
|
1114 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1115 |
|
1116 QVERIFY(manager.saveContact(&foo) == false); |
|
1117 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1118 QVERIFY(foo.id() == QContactId()); |
|
1119 QVERIFY(manager.contactIds().count() == 0); |
|
1120 |
|
1121 QVERIFY(manager.contact(foo.id().localId()).id() == QContactId()); |
|
1122 QVERIFY(manager.contact(foo.id().localId()).isEmpty()); |
|
1123 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1124 |
|
1125 QVERIFY(manager.removeContact(foo.id().localId()) == false); |
|
1126 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1127 |
|
1128 QMap<int, QContactManager::Error> errorMap; |
|
1129 errorMap.insert(0, QContactManager::NoError); |
|
1130 QVERIFY(!manager.saveContacts(0, &errorMap)); |
|
1131 QVERIFY(errorMap.count() == 0); |
|
1132 QVERIFY(manager.error() == QContactManager::BadArgumentError); |
|
1133 |
|
1134 /* filters */ |
|
1135 QContactFilter f; // matches everything |
|
1136 QContactDetailFilter df; |
|
1137 df.setDetailDefinitionName(QContactDisplayLabel::DefinitionName, QContactDisplayLabel::FieldLabel); |
|
1138 QVERIFY(manager.contactIds(QContactFilter()).count() == 0); |
|
1139 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1140 QVERIFY(manager.contactIds(df).count() == 0); |
|
1141 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1142 QVERIFY(manager.contactIds(f | f).count() == 0); |
|
1143 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1144 QVERIFY(manager.contactIds(df | df).count() == 0); |
|
1145 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1146 |
|
1147 QVERIFY(manager.isFilterSupported(f) == false); |
|
1148 QVERIFY(manager.isFilterSupported(df) == false); |
|
1149 |
|
1150 QList<QContact> list; |
|
1151 list << foo; |
|
1152 |
|
1153 QVERIFY(!manager.saveContacts(&list, &errorMap)); |
|
1154 QVERIFY(errorMap.count() == 1); |
|
1155 QVERIFY(errorMap.value(0) == QContactManager::NotSupportedError); |
|
1156 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1157 |
|
1158 QVERIFY(!manager.removeContacts(0, &errorMap)); |
|
1159 QVERIFY(errorMap.count() == 0); |
|
1160 QVERIFY(manager.error() == QContactManager::BadArgumentError); |
|
1161 |
|
1162 QList<QContactLocalId> idlist; |
|
1163 idlist << foo.id().localId(); |
|
1164 QVERIFY(!manager.removeContacts(&idlist, &errorMap)); |
|
1165 QVERIFY(errorMap.count() == 1); |
|
1166 QVERIFY(errorMap.value(0) == QContactManager::NotSupportedError); |
|
1167 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1168 |
|
1169 /* Detail definitions */ |
|
1170 QVERIFY(manager.detailDefinitions().count() == 0); |
|
1171 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1172 |
|
1173 QContactDetailDefinition def; |
|
1174 def.setUnique(true); |
|
1175 def.setName("new field"); |
|
1176 QMap<QString, QContactDetailFieldDefinition> fields; |
|
1177 QContactDetailFieldDefinition currField; |
|
1178 currField.setDataType(QVariant::String); |
|
1179 fields.insert("value", currField); |
|
1180 def.setFields(fields); |
|
1181 |
|
1182 QVERIFY(manager.saveDetailDefinition(def, QContactType::TypeContact) == false); |
|
1183 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1184 QVERIFY(manager.saveDetailDefinition(def) == false); |
|
1185 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1186 QVERIFY(manager.detailDefinitions().count(QContactType::TypeContact) == 0); |
|
1187 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1188 QVERIFY(manager.detailDefinitions().count() == 0); |
|
1189 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1190 QVERIFY(manager.detailDefinition("new field").name() == QString()); |
|
1191 QVERIFY(manager.removeDetailDefinition(def.name(), QContactType::TypeContact) == false); |
|
1192 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1193 QVERIFY(manager.removeDetailDefinition(def.name()) == false); |
|
1194 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1195 QVERIFY(manager.detailDefinitions().count() == 0); |
|
1196 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::InvalidContactTypeError); |
|
1197 |
|
1198 /* Self contact id */ |
|
1199 QVERIFY(!manager.setSelfContactId(QContactLocalId(12))); |
|
1200 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1201 QVERIFY(manager.selfContactId() == QContactLocalId()); |
|
1202 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::DoesNotExistError); |
|
1203 |
|
1204 /* Relationships */ |
|
1205 QContactId idOne, idTwo; |
|
1206 idOne.setLocalId(QContactLocalId(15)); |
|
1207 idOne.setManagerUri(QString()); |
|
1208 idTwo.setLocalId(QContactLocalId(22)); |
|
1209 idTwo.setManagerUri(QString()); |
|
1210 QContactRelationship invalidRel; |
|
1211 invalidRel.setFirst(idOne); |
|
1212 invalidRel.setSecond(idTwo); |
|
1213 QList<QContactRelationship> invalidRelList; |
|
1214 invalidRelList << invalidRel; |
|
1215 QVERIFY(!manager.saveRelationship(&invalidRel)); |
|
1216 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1217 QVERIFY(manager.relationships().isEmpty()); |
|
1218 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1219 manager.saveRelationships(&invalidRelList); |
|
1220 QVERIFY(manager.error() == QContactManager::NotSupportedError); |
|
1221 manager.removeRelationships(invalidRelList); |
|
1222 QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::DoesNotExistError); |
|
1223 |
|
1224 /* Capabilities */ |
|
1225 QVERIFY(manager.supportedDataTypes().count() == 0); |
|
1226 QVERIFY(!manager.hasFeature(QContactManager::ActionPreferences)); |
|
1227 QVERIFY(!manager.hasFeature(QContactManager::MutableDefinitions)); |
|
1228 } |
|
1229 |
|
1230 void tst_QContactManager::memoryManager() |
|
1231 { |
|
1232 QMap<QString, QString> params; |
|
1233 QContactManager m1("memory"); |
|
1234 params.insert("random", "shouldNotBeUsed"); |
|
1235 QContactManager m2("memory", params); |
|
1236 params.insert("id", "shouldBeUsed"); |
|
1237 QContactManager m3("memory", params); |
|
1238 QContactManager m4("memory", params); |
|
1239 params.insert("id", QString("")); |
|
1240 QContactManager m5("memory", params); // should be another anonymous |
|
1241 |
|
1242 QVERIFY(m1.hasFeature(QContactManager::ActionPreferences)); |
|
1243 QVERIFY(m1.hasFeature(QContactManager::MutableDefinitions)); |
|
1244 QVERIFY(m1.hasFeature(QContactManager::Anonymous)); |
|
1245 |
|
1246 // add a contact to each of m1, m2, m3 |
|
1247 QContact c; |
|
1248 QContactName nc; |
|
1249 nc.setFirstName("John"); |
|
1250 nc.setLastName("Civilian"); |
|
1251 c.saveDetail(&nc); |
|
1252 m1.saveContact(&c); |
|
1253 c.setId(QContactId()); |
|
1254 QContact c2; |
|
1255 QContactName nc2 = c2.detail(QContactName::DefinitionName); |
|
1256 c2 = c; |
|
1257 nc2.setMiddleName("Public"); |
|
1258 c2.saveDetail(&nc2); |
|
1259 m2.saveContact(&c2); // save c2 first; c will be given a higher id |
|
1260 m2.saveContact(&c); // save c to m2 |
|
1261 c.setId(QContactId()); |
|
1262 nc.setSuffix("MD"); |
|
1263 c.saveDetail(&nc); |
|
1264 m3.saveContact(&c); |
|
1265 |
|
1266 /* test that m1 != m2 != m3 and that m3 == m4 */ |
|
1267 |
|
1268 // check the counts are correct - especially note m4 and m3. |
|
1269 QCOMPARE(m1.contactIds().count(), 1); |
|
1270 QCOMPARE(m2.contactIds().count(), 2); |
|
1271 QCOMPARE(m3.contactIds().count(), 1); |
|
1272 QCOMPARE(m4.contactIds().count(), 1); |
|
1273 QCOMPARE(m5.contactIds().count(), 0); |
|
1274 |
|
1275 // remove c2 from m2 - ensure that this doesn't affect any other manager. |
|
1276 m2.removeContact(c2.id().localId()); |
|
1277 QCOMPARE(m1.contactIds().count(), 1); |
|
1278 QCOMPARE(m2.contactIds().count(), 1); |
|
1279 QCOMPARE(m3.contactIds().count(), 1); |
|
1280 QCOMPARE(m4.contactIds().count(), 1); |
|
1281 QCOMPARE(m5.contactIds().count(), 0); |
|
1282 |
|
1283 // check that the contacts contained within are different. |
|
1284 // note that in the m1->m2 case, only the id will be different! |
|
1285 QVERIFY(m1.contact(m1.contactIds().at(0)) != m2.contact(m2.contactIds().at(0))); |
|
1286 QVERIFY(m1.contact(m1.contactIds().at(0)) != m3.contact(m3.contactIds().at(0))); |
|
1287 QVERIFY(m2.contact(m2.contactIds().at(0)) != m3.contact(m3.contactIds().at(0))); |
|
1288 QVERIFY(m3.contact(m3.contactIds().at(0)) == m4.contact(m4.contactIds().at(0))); |
|
1289 |
|
1290 // now, we should be able to remove from m4, and have m3 empty |
|
1291 QVERIFY(m4.removeContact(c.id().localId())); |
|
1292 QCOMPARE(m3.contactIds().count(), 0); |
|
1293 QCOMPARE(m4.contactIds().count(), 0); |
|
1294 QCOMPARE(m5.contactIds().count(), 0); |
|
1295 } |
|
1296 |
|
1297 void tst_QContactManager::nameSynthesis_data() |
|
1298 { |
|
1299 QTest::addColumn<QString>("expected"); |
|
1300 |
|
1301 QTest::addColumn<bool>("addname"); |
|
1302 QTest::addColumn<QString>("prefix"); |
|
1303 QTest::addColumn<QString>("first"); |
|
1304 QTest::addColumn<QString>("middle"); |
|
1305 QTest::addColumn<QString>("last"); |
|
1306 QTest::addColumn<QString>("suffix"); |
|
1307 |
|
1308 QTest::addColumn<bool>("addcompany"); |
|
1309 QTest::addColumn<QString>("company"); |
|
1310 |
|
1311 QTest::addColumn<bool>("addname2"); |
|
1312 QTest::addColumn<QString>("secondprefix"); |
|
1313 QTest::addColumn<QString>("secondfirst"); |
|
1314 QTest::addColumn<QString>("secondmiddle"); |
|
1315 QTest::addColumn<QString>("secondlast"); |
|
1316 QTest::addColumn<QString>("secondsuffix"); |
|
1317 |
|
1318 QTest::addColumn<bool>("addcompany2"); |
|
1319 QTest::addColumn<QString>("secondcompany"); |
|
1320 |
|
1321 QString e; // empty string.. gets a work out |
|
1322 |
|
1323 /* Various empty ones */ |
|
1324 QTest::newRow("empty contact") << e |
|
1325 << false << e << e << e << e << e |
|
1326 << false << e |
|
1327 << false << e << e << e << e << e |
|
1328 << false << e; |
|
1329 QTest::newRow("empty name") << e |
|
1330 << true << e << e << e << e << e |
|
1331 << false << e |
|
1332 << false << e << e << e << e << e |
|
1333 << false << e; |
|
1334 QTest::newRow("empty names") << e |
|
1335 << true << e << e << e << e << e |
|
1336 << false << e |
|
1337 << true << e << e << e << e << e |
|
1338 << false << e; |
|
1339 QTest::newRow("empty org") << e |
|
1340 << false << e << e << e << e << e |
|
1341 << true << e |
|
1342 << false << e << e << e << e << e |
|
1343 << true << e; |
|
1344 QTest::newRow("empty orgs") << e |
|
1345 << false << e << e << e << e << e |
|
1346 << true << e |
|
1347 << false << e << e << e << e << e |
|
1348 << true << e; |
|
1349 QTest::newRow("empty orgs and names") << e |
|
1350 << true << e << e << e << e << e |
|
1351 << true << e |
|
1352 << true << e << e << e << e << e |
|
1353 << true << e; |
|
1354 |
|
1355 /* Single values */ |
|
1356 QTest::newRow("prefix") << "Prefix" |
|
1357 << true << "Prefix" << e << e << e << e |
|
1358 << false << e |
|
1359 << false << e << e << e << e << e |
|
1360 << false << e; |
|
1361 QTest::newRow("first") << "First" |
|
1362 << true << e << "First" << e << e << e |
|
1363 << false << e |
|
1364 << false << e << e << e << e << e |
|
1365 << false << e; |
|
1366 QTest::newRow("middle") << "Middle" |
|
1367 << true << e << e << "Middle" << e << e |
|
1368 << false << e |
|
1369 << false << e << e << e << e << e |
|
1370 << false << e; |
|
1371 QTest::newRow("last") << "Last" |
|
1372 << true << e << e << e << "Last" << e |
|
1373 << false << e |
|
1374 << false << e << e << e << e << e |
|
1375 << false << e; |
|
1376 QTest::newRow("suffix") << "Suffix" |
|
1377 << true << e << e << e << e << "Suffix" |
|
1378 << false << e |
|
1379 << false << e << e << e << e << e |
|
1380 << false << e; |
|
1381 |
|
1382 /* Single values in the second name */ |
|
1383 QTest::newRow("prefix in second") << "Prefix" |
|
1384 << false << "Prefix" << e << e << e << e |
|
1385 << false << e |
|
1386 << true << "Prefix" << e << e << e << e |
|
1387 << false << e; |
|
1388 QTest::newRow("first in second") << "First" |
|
1389 << false << e << "First" << e << e << e |
|
1390 << false << e |
|
1391 << true << e << "First" << e << e << e |
|
1392 << false << e; |
|
1393 QTest::newRow("middle in second") << "Middle" |
|
1394 << false << e << e << "Middle" << e << e |
|
1395 << false << e |
|
1396 << true << e << e << "Middle" << e << e |
|
1397 << false << e; |
|
1398 QTest::newRow("last in second") << "Last" |
|
1399 << false << e << e << e << "Last" << e |
|
1400 << false << e |
|
1401 << true << e << e << e << "Last" << e |
|
1402 << false << e; |
|
1403 QTest::newRow("suffix in second") << "Suffix" |
|
1404 << false << e << e << e << e << "Suffix" |
|
1405 << false << e |
|
1406 << true << e << e << e << e << "Suffix" |
|
1407 << false << e; |
|
1408 |
|
1409 /* Multiple name values */ |
|
1410 QTest::newRow("prefix first") << "Prefix First" |
|
1411 << true << "Prefix" << "First" << e << e << e |
|
1412 << false << e |
|
1413 << false << e << e << e << e << e |
|
1414 << false << e; |
|
1415 QTest::newRow("prefix middle") << "Prefix Middle" |
|
1416 << true << "Prefix" << e << "Middle" << e << e |
|
1417 << false << e |
|
1418 << false << e << e << e << e << e |
|
1419 << false << e; |
|
1420 QTest::newRow("prefix last") << "Prefix Last" |
|
1421 << true << "Prefix" << e << e << "Last" << e |
|
1422 << false << e |
|
1423 << false << e << e << e << e << e |
|
1424 << false << e; |
|
1425 QTest::newRow("prefix suffix") << "Prefix Suffix" |
|
1426 << true << "Prefix" << e << e << e << "Suffix" |
|
1427 << false << e |
|
1428 << false << e << e << e << e << e |
|
1429 << false << e; |
|
1430 QTest::newRow("first middle") << "First Middle" |
|
1431 << true << e << "First" << "Middle" << e << e |
|
1432 << false << e |
|
1433 << false << e << e << e << e << e |
|
1434 << false << e; |
|
1435 QTest::newRow("first last") << "First Last" |
|
1436 << true << e << "First" << e << "Last" << e |
|
1437 << false << e |
|
1438 << false << e << e << e << e << e |
|
1439 << false << e; |
|
1440 QTest::newRow("first suffix") << "First Suffix" |
|
1441 << true << e << "First" << e << e << "Suffix" |
|
1442 << false << e |
|
1443 << false << e << e << e << e << e |
|
1444 << false << e; |
|
1445 QTest::newRow("middle last") << "Middle Last" |
|
1446 << true << e << e << "Middle" << "Last" << e |
|
1447 << false << e |
|
1448 << false << e << e << e << e << e |
|
1449 << false << e; |
|
1450 QTest::newRow("middle suffix") << "Middle Suffix" |
|
1451 << true << e << e << "Middle" << e << "Suffix" |
|
1452 << false << e |
|
1453 << false << e << e << e << e << e |
|
1454 << false << e; |
|
1455 QTest::newRow("last suffix") << "Last Suffix" |
|
1456 << true << e << e << e << "Last" << "Suffix" |
|
1457 << false << e |
|
1458 << false << e << e << e << e << e |
|
1459 << false << e; |
|
1460 |
|
1461 /* Everything.. */ |
|
1462 QTest::newRow("all name") << "Prefix First Middle Last Suffix" |
|
1463 << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
|
1464 << false << e |
|
1465 << false << e << e << e << e << e |
|
1466 << false << e; |
|
1467 QTest::newRow("all name second") << "Prefix First Middle Last Suffix" |
|
1468 << false << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
|
1469 << false << e |
|
1470 << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
|
1471 << false << e; |
|
1472 |
|
1473 /* Org */ |
|
1474 QTest::newRow("org") << "Company" |
|
1475 << false << e << e << e << e << e |
|
1476 << true << "Company" |
|
1477 << false << e << e << e << e << e |
|
1478 << false << e; |
|
1479 QTest::newRow("second org") << "Company" |
|
1480 << false << e << e << e << e << e |
|
1481 << false << e |
|
1482 << false << e << e << e << e << e |
|
1483 << true << "Company"; |
|
1484 |
|
1485 /* Mix */ |
|
1486 QTest::newRow("org and empty name") << "Company" |
|
1487 << true << e << e << e << e << e |
|
1488 << true << "Company" |
|
1489 << false << e << e << e << e << e |
|
1490 << false << e; |
|
1491 |
|
1492 QTest::newRow("name and empty org") << "Prefix First Middle Last Suffix" |
|
1493 << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
|
1494 << false << e |
|
1495 << false << e << e << e << e << e |
|
1496 << false << e; |
|
1497 |
|
1498 /* names are preferred to orgs */ |
|
1499 QTest::newRow("name and org") << "Prefix First Middle Last Suffix" |
|
1500 << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
|
1501 << true << "Company" |
|
1502 << false << e << e << e << e << e |
|
1503 << false << e; |
|
1504 |
|
1505 } |
|
1506 |
|
1507 void tst_QContactManager::nameSynthesis() |
|
1508 { |
|
1509 QContactManager cm("memory"); |
|
1510 |
|
1511 QFETCH(QString, expected); |
|
1512 |
|
1513 QFETCH(QString, prefix); |
|
1514 QFETCH(QString, first); |
|
1515 QFETCH(QString, middle); |
|
1516 QFETCH(QString, last); |
|
1517 QFETCH(QString, suffix); |
|
1518 QFETCH(QString, company); |
|
1519 |
|
1520 QFETCH(QString, secondprefix); |
|
1521 QFETCH(QString, secondfirst); |
|
1522 QFETCH(QString, secondmiddle); |
|
1523 QFETCH(QString, secondlast); |
|
1524 QFETCH(QString, secondsuffix); |
|
1525 QFETCH(QString, secondcompany); |
|
1526 |
|
1527 QFETCH(bool, addname); |
|
1528 QFETCH(bool, addname2); |
|
1529 QFETCH(bool, addcompany); |
|
1530 QFETCH(bool, addcompany2); |
|
1531 |
|
1532 /* Test the default name synthesis code */ |
|
1533 QContact c; |
|
1534 |
|
1535 QContactName name, name2; |
|
1536 QContactOrganization org, org2; |
|
1537 |
|
1538 name.setPrefix(prefix); |
|
1539 name.setFirstName(first); |
|
1540 name.setMiddleName(middle); |
|
1541 name.setLastName(last); |
|
1542 name.setSuffix(suffix); |
|
1543 |
|
1544 name2.setPrefix(secondprefix); |
|
1545 name2.setFirstName(secondfirst); |
|
1546 name2.setMiddleName(secondmiddle); |
|
1547 name2.setLastName(secondlast); |
|
1548 name2.setSuffix(secondsuffix); |
|
1549 |
|
1550 org.setName(company); |
|
1551 org2.setName(secondcompany); |
|
1552 |
|
1553 if (addname) |
|
1554 c.saveDetail(&name); |
|
1555 if (addname2) |
|
1556 c.saveDetail(&name2); |
|
1557 if (addcompany) |
|
1558 c.saveDetail(&org); |
|
1559 if (addcompany2) |
|
1560 c.saveDetail(&org2); |
|
1561 |
|
1562 // Finally! |
|
1563 QCOMPARE(cm.synthesizedDisplayLabel(c), expected); |
|
1564 } |
|
1565 |
|
1566 void tst_QContactManager::contactValidation() |
|
1567 { |
|
1568 /* Use the memory engine as a reference (validation is not engine specific) */ |
|
1569 QScopedPointer<QContactManager> cm(new QContactManager("memory")); |
|
1570 QContact c; |
|
1571 |
|
1572 /* |
|
1573 * Add some definitions for testing: |
|
1574 * |
|
1575 * 1) a unique detail |
|
1576 * 2) a detail with restricted values |
|
1577 * 3) a create only detail |
|
1578 * 4) a unique create only detail |
|
1579 */ |
|
1580 QContactDetailDefinition uniqueDef; |
|
1581 QMap<QString, QContactDetailFieldDefinition> fields; |
|
1582 QContactDetailFieldDefinition field; |
|
1583 field.setDataType(QVariant::String); |
|
1584 fields.insert("value", field); |
|
1585 |
|
1586 uniqueDef.setName("UniqueDetail"); |
|
1587 uniqueDef.setFields(fields); |
|
1588 uniqueDef.setUnique(true); |
|
1589 |
|
1590 QVERIFY(cm->saveDetailDefinition(uniqueDef)); |
|
1591 |
|
1592 QContactDetailDefinition restrictedDef; |
|
1593 restrictedDef.setName("RestrictedDetail"); |
|
1594 fields.clear(); |
|
1595 field.setAllowableValues(QVariantList() << "One" << "Two" << "Three"); |
|
1596 fields.insert("value", field); |
|
1597 restrictedDef.setFields(fields); |
|
1598 |
|
1599 QVERIFY(cm->saveDetailDefinition(restrictedDef)); |
|
1600 |
|
1601 // first, test an invalid definition |
|
1602 QContactDetail d1 = QContactDetail("UnknownDefinition"); |
|
1603 d1.setValue("test", "test"); |
|
1604 c.saveDetail(&d1); |
|
1605 QVERIFY(!cm->saveContact(&c)); |
|
1606 QCOMPARE(cm->error(), QContactManager::InvalidDetailError); |
|
1607 c.removeDetail(&d1); |
|
1608 |
|
1609 // second, test an invalid uniqueness constraint |
|
1610 QContactDetail d2 = QContactDetail("UniqueDetail"); |
|
1611 d2.setValue("value", "test"); |
|
1612 c.saveDetail(&d2); |
|
1613 |
|
1614 // One unique should be ok |
|
1615 QVERIFY(cm->saveContact(&c)); |
|
1616 QCOMPARE(cm->error(), QContactManager::NoError); |
|
1617 |
|
1618 // Two uniques should not be ok |
|
1619 QContactDetail d3 = QContactDetail("UniqueDetail"); |
|
1620 d3.setValue("value", "test2"); |
|
1621 c.saveDetail(&d3); |
|
1622 QVERIFY(!cm->saveContact(&c)); |
|
1623 QCOMPARE(cm->error(), QContactManager::AlreadyExistsError); |
|
1624 c.removeDetail(&d3); |
|
1625 c.removeDetail(&d2); |
|
1626 |
|
1627 // third, test an invalid field name |
|
1628 QContactDetail d4 = QContactDetail(QContactPhoneNumber::DefinitionName); |
|
1629 d4.setValue("test", "test"); |
|
1630 c.saveDetail(&d4); |
|
1631 QVERIFY(!cm->saveContact(&c)); |
|
1632 QCOMPARE(cm->error(), QContactManager::InvalidDetailError); |
|
1633 c.removeDetail(&d4); |
|
1634 |
|
1635 // fourth, test an invalid field data type |
|
1636 QContactDetail d5 = QContactDetail(QContactPhoneNumber::DefinitionName); |
|
1637 d5.setValue(QContactPhoneNumber::FieldNumber, QDateTime::currentDateTime()); |
|
1638 c.saveDetail(&d5); |
|
1639 QVERIFY(!cm->saveContact(&c)); |
|
1640 QCOMPARE(cm->error(), QContactManager::InvalidDetailError); |
|
1641 c.removeDetail(&d5); |
|
1642 |
|
1643 // fifth, test an invalid field value (not in the allowed list) |
|
1644 QContactDetail d6 = QContactDetail("RestrictedDetail"); |
|
1645 d6.setValue("value", "Seven"); // not in One, Two or Three |
|
1646 c.saveDetail(&d6); |
|
1647 QVERIFY(!cm->saveContact(&c)); |
|
1648 QCOMPARE(cm->error(), QContactManager::InvalidDetailError); |
|
1649 c.removeDetail(&d6); |
|
1650 |
|
1651 /* Now a valid value */ |
|
1652 d6.setValue("value", "Two"); |
|
1653 c.saveDetail(&d6); |
|
1654 QVERIFY(cm->saveContact(&c)); |
|
1655 QCOMPARE(cm->error(), QContactManager::NoError); |
|
1656 c.removeDetail(&d6); |
|
1657 |
|
1658 // Test a completely valid one. |
|
1659 QContactDetail d7 = QContactDetail(QContactPhoneNumber::DefinitionName); |
|
1660 d7.setValue(QContactPhoneNumber::FieldNumber, "0123456"); |
|
1661 c.saveDetail(&d7); |
|
1662 QVERIFY(cm->saveContact(&c)); |
|
1663 QCOMPARE(cm->error(), QContactManager::NoError); |
|
1664 c.removeDetail(&d7); |
|
1665 } |
|
1666 |
|
1667 void tst_QContactManager::signalEmission() |
|
1668 { |
|
1669 QFETCH(QString, uri); |
|
1670 QScopedPointer<QContactManager> m1(QContactManager::fromUri(uri)); |
|
1671 QScopedPointer<QContactManager> m2(QContactManager::fromUri(uri)); |
|
1672 |
|
1673 QVERIFY(m1->hasFeature(QContactManager::Anonymous) == |
|
1674 m2->hasFeature(QContactManager::Anonymous)); |
|
1675 |
|
1676 qRegisterMetaType<QContactLocalId>("QContactLocalId"); |
|
1677 qRegisterMetaType<QList<QContactLocalId> >("QList<QContactLocalId>"); |
|
1678 QSignalSpy spyCA(m1.data(), SIGNAL(contactsAdded(QList<QContactLocalId>))); |
|
1679 QSignalSpy spyCM(m1.data(), SIGNAL(contactsChanged(QList<QContactLocalId>))); |
|
1680 QSignalSpy spyCR(m1.data(), SIGNAL(contactsRemoved(QList<QContactLocalId>))); |
|
1681 |
|
1682 QList<QVariant> args; |
|
1683 QContact c; |
|
1684 QContactLocalId temp; |
|
1685 QList<QContact> batchAdd; |
|
1686 QList<QContactLocalId> batchRemove; |
|
1687 QList<QContactLocalId> sigids; |
|
1688 int addSigCount = 0; // the expected signal counts. |
|
1689 int modSigCount = 0; |
|
1690 int remSigCount = 0; |
|
1691 |
|
1692 // verify add emits signal added |
|
1693 QContactName nc; |
|
1694 nc.setFirstName("John"); |
|
1695 c.saveDetail(&nc); |
|
1696 m1->saveContact(&c); |
|
1697 addSigCount += 1; |
|
1698 QTRY_COMPARE(spyCA.count(), addSigCount); |
|
1699 args = spyCA.takeFirst(); |
|
1700 addSigCount -= 1; |
|
1701 QVERIFY(args.count() == 1); |
|
1702 temp = QContactLocalId(args.at(0).value<quint32>()); |
|
1703 |
|
1704 // verify save modified emits signal changed |
|
1705 nc.setLastName("Citizen"); |
|
1706 c.saveDetail(&nc); |
|
1707 m1->saveContact(&c); |
|
1708 modSigCount += 1; |
|
1709 QTRY_COMPARE(spyCM.count(), modSigCount); |
|
1710 args = spyCM.takeFirst(); |
|
1711 modSigCount -= 1; |
|
1712 QVERIFY(args.count() == 1); |
|
1713 QCOMPARE(temp, QContactLocalId(args.at(0).value<quint32>())); |
|
1714 |
|
1715 // verify remove emits signal removed |
|
1716 m1->removeContact(c.id().localId()); |
|
1717 remSigCount += 1; |
|
1718 QTRY_COMPARE(spyCR.count(), remSigCount); |
|
1719 args = spyCR.takeFirst(); |
|
1720 remSigCount -= 1; |
|
1721 QVERIFY(args.count() == 1); |
|
1722 QCOMPARE(temp, QContactLocalId(args.at(0).value<quint32>())); |
|
1723 |
|
1724 // verify multiple adds works as advertised |
|
1725 QContact c2, c3; |
|
1726 QContactName nc2, nc3; |
|
1727 nc2.setFirstName("Mark"); |
|
1728 nc3.setFirstName("Garry"); |
|
1729 c2.saveDetail(&nc2); |
|
1730 c3.saveDetail(&nc3); |
|
1731 QVERIFY(!m1->saveContact(&c)); // saving contact with nonexistent id fails |
|
1732 QVERIFY(m1->saveContact(&c2)); |
|
1733 addSigCount += 1; |
|
1734 QVERIFY(m1->saveContact(&c3)); |
|
1735 addSigCount += 1; |
|
1736 QTRY_COMPARE(spyCM.count(), modSigCount); |
|
1737 QTRY_COMPARE(spyCA.count(), addSigCount); |
|
1738 |
|
1739 // verify multiple modifies works as advertised |
|
1740 nc2.setLastName("M."); |
|
1741 c2.saveDetail(&nc2); |
|
1742 QVERIFY(m1->saveContact(&c2)); |
|
1743 modSigCount += 1; |
|
1744 nc2.setPrefix("Mr."); |
|
1745 nc3.setLastName("G."); |
|
1746 c2.saveDetail(&nc2); |
|
1747 c3.saveDetail(&nc3); |
|
1748 QVERIFY(m1->saveContact(&c2)); |
|
1749 modSigCount += 1; |
|
1750 QVERIFY(m1->saveContact(&c3)); |
|
1751 modSigCount += 1; |
|
1752 QTRY_COMPARE(spyCM.count(), modSigCount); |
|
1753 |
|
1754 // verify multiple removes works as advertised |
|
1755 m1->removeContact(c3.id().localId()); |
|
1756 remSigCount += 1; |
|
1757 m1->removeContact(c2.id().localId()); |
|
1758 remSigCount += 1; |
|
1759 QTRY_COMPARE(spyCR.count(), remSigCount); |
|
1760 |
|
1761 QVERIFY(!m1->removeContact(c.id().localId())); // not saved. |
|
1762 |
|
1763 /* Now test the batch equivalents */ |
|
1764 spyCA.clear(); |
|
1765 spyCM.clear(); |
|
1766 spyCR.clear(); |
|
1767 |
|
1768 /* Batch adds - set ids to zero so add succeeds. */ |
|
1769 c.setId(QContactId()); |
|
1770 c2.setId(QContactId()); |
|
1771 c3.setId(QContactId()); |
|
1772 batchAdd << c << c2 << c3; |
|
1773 QMap<int, QContactManager::Error> errorMap; |
|
1774 QVERIFY(m1->saveContacts(&batchAdd, &errorMap)); |
|
1775 |
|
1776 QVERIFY(batchAdd.count() == 3); |
|
1777 c = batchAdd.at(0); |
|
1778 c2 = batchAdd.at(1); |
|
1779 c3 = batchAdd.at(2); |
|
1780 |
|
1781 /* We basically loop, processing events, until we've seen an Add signal for each contact */ |
|
1782 sigids.clear(); |
|
1783 |
|
1784 QTRY_WAIT( while(spyCA.size() > 0) {sigids += spyCA.takeFirst().at(0).value<QList<QContactLocalId> >(); }, sigids.contains(c.localId()) && sigids.contains(c2.localId()) && sigids.contains(c3.localId())); |
|
1785 QTRY_COMPARE(spyCM.count(), 0); |
|
1786 QTRY_COMPARE(spyCR.count(), 0); |
|
1787 |
|
1788 /* Batch modifies */ |
|
1789 QContactDetailDefinition nameDef = m1->detailDefinition(QContactName::DefinitionName, QContactType::TypeContact); |
|
1790 QContactName modifiedName = c.detail(QContactName::DefinitionName); |
|
1791 setContactName(nameDef, modifiedName, "This is modified number 1"); |
|
1792 c.saveDetail(&modifiedName); |
|
1793 modifiedName = c2.detail(QContactName::DefinitionName); |
|
1794 setContactName(nameDef, modifiedName, "This is modified number 2"); |
|
1795 c2.saveDetail(&modifiedName); |
|
1796 modifiedName = c3.detail(QContactName::DefinitionName); |
|
1797 setContactName(nameDef, modifiedName, "This is modified number 3"); |
|
1798 c3.saveDetail(&modifiedName); |
|
1799 |
|
1800 batchAdd.clear(); |
|
1801 batchAdd << c << c2 << c3; |
|
1802 QVERIFY(m1->saveContacts(&batchAdd, &errorMap)); |
|
1803 |
|
1804 sigids.clear(); |
|
1805 QTRY_WAIT( while(spyCM.size() > 0) {sigids += spyCM.takeFirst().at(0).value<QList<QContactLocalId> >(); }, sigids.contains(c.localId()) && sigids.contains(c2.localId()) && sigids.contains(c3.localId())); |
|
1806 |
|
1807 /* Batch removes */ |
|
1808 batchRemove << c.id().localId() << c2.id().localId() << c3.id().localId(); |
|
1809 QVERIFY(m1->removeContacts(&batchRemove, &errorMap)); |
|
1810 |
|
1811 sigids.clear(); |
|
1812 QTRY_WAIT( while(spyCR.size() > 0) {sigids += spyCR.takeFirst().at(0).value<QList<QContactLocalId> >(); }, sigids.contains(c.localId()) && sigids.contains(c2.localId()) && sigids.contains(c3.localId())); |
|
1813 |
|
1814 QTRY_COMPARE(spyCA.count(), 0); |
|
1815 QTRY_COMPARE(spyCM.count(), 0); |
|
1816 |
|
1817 /* Now some cross manager testing */ |
|
1818 if (!m1->hasFeature(QContactManager::Anonymous)) { |
|
1819 // verify that signals are emitted for modifications made to other managers (same id). |
|
1820 QContactName ncs = c.detail(QContactName::DefinitionName); |
|
1821 ncs.setSuffix("Test"); |
|
1822 c.saveDetail(&ncs); |
|
1823 c.setId(QContactId()); // reset id so save can succeed. |
|
1824 m2->saveContact(&c); |
|
1825 ncs.setPrefix("Test2"); |
|
1826 c.saveDetail(&ncs); |
|
1827 m2->saveContact(&c); |
|
1828 QTRY_COMPARE(spyCA.count(), 1); // check that we received the update signals. |
|
1829 QTRY_COMPARE(spyCM.count(), 1); // check that we received the update signals. |
|
1830 m2->removeContact(c.localId()); |
|
1831 QTRY_COMPARE(spyCR.count(), 1); // check that we received the remove signal. |
|
1832 } |
|
1833 } |
|
1834 |
|
1835 void tst_QContactManager::errorStayingPut() |
|
1836 { |
|
1837 /* Make sure that when we clone a manager, we don't clone the error */ |
|
1838 QMap<QString, QString> params; |
|
1839 params.insert("id", "error isolation test"); |
|
1840 QContactManager m1("memory",params); |
|
1841 |
|
1842 QVERIFY(m1.error() == QContactManager::NoError); |
|
1843 |
|
1844 /* Remove an invalid contact to get an error */ |
|
1845 QVERIFY(m1.removeContact(0) == false); |
|
1846 QVERIFY(m1.error() == QContactManager::DoesNotExistError); |
|
1847 |
|
1848 /* Create a new manager with hopefully the same backend */ |
|
1849 QContactManager m2("memory", params); |
|
1850 |
|
1851 QVERIFY(m1.error() == QContactManager::DoesNotExistError); |
|
1852 QVERIFY(m2.error() == QContactManager::NoError); |
|
1853 |
|
1854 /* Cause an error on the other ones and check the first is not affected */ |
|
1855 m2.saveContacts(0, 0); |
|
1856 QVERIFY(m1.error() == QContactManager::DoesNotExistError); |
|
1857 QVERIFY(m2.error() == QContactManager::BadArgumentError); |
|
1858 |
|
1859 QContact c; |
|
1860 QContactDetail d("This does not exist and if it does this will break"); |
|
1861 d.setValue("Value that also doesn't exist", 5); |
|
1862 c.saveDetail(&d); |
|
1863 |
|
1864 QVERIFY(m1.saveContact(&c) == false); |
|
1865 QVERIFY(m1.error() == QContactManager::InvalidDetailError); |
|
1866 QVERIFY(m2.error() == QContactManager::BadArgumentError); |
|
1867 } |
|
1868 |
|
1869 void tst_QContactManager::detailDefinitions() |
|
1870 { |
|
1871 QFETCH(QString, uri); |
|
1872 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
1873 QMap<QString, QContactDetailDefinition> defs = cm->detailDefinitions(); |
|
1874 |
|
1875 /* Validate the existing definitions */ |
|
1876 |
|
1877 // Do some sanity checking on the definitions first |
|
1878 if (defs.keys().count() != defs.uniqueKeys().count()) { |
|
1879 qDebug() << "ERROR - duplicate definitions with the same name:"; |
|
1880 |
|
1881 QList<QString> defkeys = defs.keys(); |
|
1882 foreach(QString uniq, defs.uniqueKeys()) { |
|
1883 if (defkeys.count(uniq) > 1) { |
|
1884 qDebug() << QString(" %1").arg(uniq).toAscii().constData(); |
|
1885 defkeys.removeAll(uniq); |
|
1886 } |
|
1887 } |
|
1888 QVERIFY(defs.keys().count() == defs.uniqueKeys().count()); |
|
1889 } |
|
1890 |
|
1891 foreach(QContactDetailDefinition def, defs.values()) { |
|
1892 QMap<QString, QContactDetailFieldDefinition> fields = def.fields(); |
|
1893 |
|
1894 // Again some sanity checking |
|
1895 if (fields.keys().count() != fields.uniqueKeys().count()) { |
|
1896 qDebug() << "ERROR - duplicate fields with the same name:"; |
|
1897 |
|
1898 QList<QString> defkeys = fields.keys(); |
|
1899 foreach(QString uniq, fields.uniqueKeys()) { |
|
1900 if (defkeys.count(uniq) > 1) { |
|
1901 qDebug() << QString(" %2::%1").arg(uniq).arg(def.name()).toAscii().constData(); |
|
1902 defkeys.removeAll(uniq); |
|
1903 } |
|
1904 } |
|
1905 QVERIFY(fields.keys().count() == fields.uniqueKeys().count()); |
|
1906 } |
|
1907 |
|
1908 foreach(QContactDetailFieldDefinition field, def.fields().values()) { |
|
1909 // Sanity check the allowed values |
|
1910 if (field.allowableValues().count() > 0) { |
|
1911 if (field.dataType() == QVariant::StringList) { |
|
1912 // We accept QString or QStringList allowed values |
|
1913 foreach(QVariant var, field.allowableValues()) { |
|
1914 if (var.type() != QVariant::String && var.type() != QVariant::StringList) { |
|
1915 QString foo; |
|
1916 QDebug dbg(&foo); |
|
1917 dbg.nospace() << var; |
|
1918 qDebug().nospace() << "Field " << QString("%1::%2").arg(def.name()).arg(def.fields().key(field)).toAscii().constData() << " allowable value '" << foo.simplified().toAscii().constData() << "' not supported for field type " << QMetaType::typeName(field.dataType()); |
|
1919 } |
|
1920 QVERIFY(var.type() == QVariant::String || var.type() == QVariant::StringList); |
|
1921 } |
|
1922 } else if (field.dataType() == QVariant::List || field.dataType() == QVariant::Map || field.dataType() == (QVariant::Type) qMetaTypeId<QVariant>()) { |
|
1923 // Well, anything goes |
|
1924 } else { |
|
1925 // The type of each allowed value must match the data type |
|
1926 foreach(QVariant var, field.allowableValues()) { |
|
1927 if (var.type() != field.dataType()) { |
|
1928 QString foo; |
|
1929 QDebug dbg(&foo); |
|
1930 dbg.nospace() << var; |
|
1931 qDebug().nospace() << "Field " << QString("%1::%2").arg(def.name()).arg(def.fields().key(field)).toAscii().constData() << " allowable value '" << foo.simplified().toAscii().constData() << "' not supported for field type " << QMetaType::typeName(field.dataType()); |
|
1932 } |
|
1933 QVERIFY(var.type() == field.dataType()); |
|
1934 } |
|
1935 } |
|
1936 } |
|
1937 } |
|
1938 } |
|
1939 |
|
1940 |
|
1941 /* Try to make a credible definition */ |
|
1942 QContactDetailDefinition newDef; |
|
1943 QContactDetailFieldDefinition field; |
|
1944 QMap<QString, QContactDetailFieldDefinition> fields; |
|
1945 field.setDataType(cm->supportedDataTypes().value(0)); |
|
1946 fields.insert("New Value", field); |
|
1947 newDef.setName("New Definition"); |
|
1948 newDef.setFields(fields); |
|
1949 |
|
1950 /* Updated version of an existing definition */ |
|
1951 QContactDetailDefinition updatedDef = defs.begin().value(); // XXX TODO Fixme |
|
1952 fields = updatedDef.fields(); |
|
1953 fields.insert("New Value", field); |
|
1954 updatedDef.setFields(fields); |
|
1955 |
|
1956 /* A detail definition with valid allowed values (or really just one) */ |
|
1957 QContactDetailDefinition allowedDef = newDef; |
|
1958 field.setAllowableValues(field.allowableValues() << (QVariant(field.dataType()))); |
|
1959 fields.clear(); |
|
1960 fields.insert("Restricted value", field); |
|
1961 allowedDef.setFields(fields); |
|
1962 |
|
1963 /* Many invalid definitions */ |
|
1964 QContactDetailDefinition noIdDef; |
|
1965 noIdDef.setFields(fields); |
|
1966 |
|
1967 QContactDetailDefinition noFieldsDef; |
|
1968 noFieldsDef.setName("No fields"); |
|
1969 |
|
1970 QContactDetailDefinition invalidFieldKeyDef; |
|
1971 invalidFieldKeyDef.setName("Invalid field key"); |
|
1972 QMap<QString, QContactDetailFieldDefinition> badfields; |
|
1973 badfields.insert(QString(), field); |
|
1974 invalidFieldKeyDef.setFields(badfields); |
|
1975 |
|
1976 QContactDetailDefinition invalidFieldTypeDef; |
|
1977 invalidFieldTypeDef.setName("Invalid field type"); |
|
1978 badfields.clear(); |
|
1979 QContactDetailFieldDefinition badfield; |
|
1980 badfield.setDataType((QVariant::Type) qMetaTypeId<UnsupportedMetatype>()); |
|
1981 badfields.insert("Bad type", badfield); |
|
1982 invalidFieldTypeDef.setFields(badfields); |
|
1983 |
|
1984 QContactDetailDefinition invalidAllowedValuesDef; |
|
1985 invalidAllowedValuesDef.setName("Invalid field allowed values"); |
|
1986 badfields.clear(); |
|
1987 badfield.setDataType(field.dataType()); // use a supported type |
|
1988 badfield.setAllowableValues(QList<QVariant>() << "String" << 5); // but unsupported value |
|
1989 badfields.insert("Bad allowed", badfield); |
|
1990 invalidAllowedValuesDef.setFields(badfields); |
|
1991 |
|
1992 /* XXX Multiply defined fields.. depends on semantics. */ |
|
1993 |
|
1994 if (cm->hasFeature(QContactManager::MutableDefinitions)) { |
|
1995 /* First do some negative testing */ |
|
1996 |
|
1997 /* Bad add class */ |
|
1998 QVERIFY(cm->saveDetailDefinition(QContactDetailDefinition()) == false); |
|
1999 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
2000 |
|
2001 /* Bad remove string */ |
|
2002 QVERIFY(cm->removeDetailDefinition(QString()) == false); |
|
2003 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
2004 |
|
2005 QVERIFY(cm->saveDetailDefinition(noIdDef) == false); |
|
2006 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
2007 |
|
2008 QVERIFY(cm->saveDetailDefinition(noFieldsDef) == false); |
|
2009 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
2010 |
|
2011 QVERIFY(cm->saveDetailDefinition(invalidFieldKeyDef) == false); |
|
2012 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
2013 |
|
2014 QVERIFY(cm->saveDetailDefinition(invalidFieldTypeDef) == false); |
|
2015 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
2016 |
|
2017 QVERIFY(cm->saveDetailDefinition(invalidAllowedValuesDef) == false); |
|
2018 QVERIFY(cm->error() == QContactManager::BadArgumentError); |
|
2019 |
|
2020 /* Check that our new definition doesn't already exist */ |
|
2021 QVERIFY(cm->detailDefinition(newDef.name()).isEmpty()); |
|
2022 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
2023 |
|
2024 QVERIFY(cm->removeDetailDefinition(newDef.name()) == false); |
|
2025 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
2026 |
|
2027 /* Add a new definition */ |
|
2028 QVERIFY(cm->saveDetailDefinition(newDef) == true); |
|
2029 QVERIFY(cm->error() == QContactManager::NoError); |
|
2030 |
|
2031 /* Now retrieve it */ |
|
2032 QContactDetailDefinition def = cm->detailDefinition(newDef.name()); |
|
2033 QVERIFY(def == newDef); |
|
2034 |
|
2035 /* Update it */ |
|
2036 QMap<QString, QContactDetailFieldDefinition> newFields = def.fields(); |
|
2037 newFields.insert("Another new value", field); |
|
2038 newDef.setFields(newFields); |
|
2039 |
|
2040 QVERIFY(cm->saveDetailDefinition(newDef) == true); |
|
2041 QVERIFY(cm->error() == QContactManager::NoError); |
|
2042 |
|
2043 QVERIFY(cm->detailDefinition(newDef.name()) == newDef); |
|
2044 |
|
2045 /* Remove it */ |
|
2046 QVERIFY(cm->removeDetailDefinition(newDef.name()) == true); |
|
2047 QVERIFY(cm->error() == QContactManager::NoError); |
|
2048 |
|
2049 /* and make sure it does not exist any more */ |
|
2050 QVERIFY(cm->detailDefinition(newDef.name()) == QContactDetailDefinition()); |
|
2051 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
2052 |
|
2053 /* Add the other good one */ |
|
2054 QVERIFY(cm->saveDetailDefinition(allowedDef) == true); |
|
2055 QVERIFY(cm->error() == QContactManager::NoError); |
|
2056 |
|
2057 QVERIFY(allowedDef == cm->detailDefinition(allowedDef.name())); |
|
2058 |
|
2059 /* and remove it */ |
|
2060 QVERIFY(cm->removeDetailDefinition(allowedDef.name()) == true); |
|
2061 QVERIFY(cm->detailDefinition(allowedDef.name()) == QContactDetailDefinition()); |
|
2062 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
2063 |
|
2064 } else { |
|
2065 /* Bad add class */ |
|
2066 QVERIFY(cm->saveDetailDefinition(QContactDetailDefinition()) == false); |
|
2067 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2068 |
|
2069 /* Make sure we can't add/remove/modify detail definitions */ |
|
2070 QVERIFY(cm->removeDetailDefinition(QString()) == false); |
|
2071 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2072 |
|
2073 /* Try updating an existing definition */ |
|
2074 QVERIFY(cm->saveDetailDefinition(updatedDef) == false); |
|
2075 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2076 |
|
2077 /* Try removing an existing definition */ |
|
2078 QVERIFY(cm->removeDetailDefinition(updatedDef.name()) == false); |
|
2079 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2080 } |
|
2081 } |
|
2082 |
|
2083 void tst_QContactManager::displayName() |
|
2084 { |
|
2085 QFETCH(QString, uri); |
|
2086 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
2087 |
|
2088 /* |
|
2089 * Very similar to the tst_QContact functions, except we test |
|
2090 * saving and retrieving contacts updates the display label |
|
2091 */ |
|
2092 |
|
2093 /* Try to make this a bit more consistent by using a single name */ |
|
2094 QContact d; |
|
2095 QContactName name; |
|
2096 setContactName(cm->detailDefinition(QContactName::DefinitionName, QContactType::TypeContact), name, "Wesley"); |
|
2097 |
|
2098 QVERIFY(d.displayLabel().isEmpty()); |
|
2099 QVERIFY(d.saveDetail(&name)); |
|
2100 |
|
2101 QString synth = cm->synthesizedDisplayLabel(d); |
|
2102 |
|
2103 /* |
|
2104 * The display label is not updated until you save the contact. |
|
2105 */ |
|
2106 QVERIFY(cm->saveContact(&d)); |
|
2107 d = cm->contact(d.id().localId()); |
|
2108 QVERIFY(!d.isEmpty()); |
|
2109 QCOMPARE(d.displayLabel(), synth); |
|
2110 |
|
2111 /* Remove the detail via removeDetail */ |
|
2112 QContactDisplayLabel old; |
|
2113 int count = d.details().count(); |
|
2114 QVERIFY(!d.removeDetail(&old)); // should fail. |
|
2115 QVERIFY(d.isEmpty() == false); |
|
2116 QVERIFY(d.details().count() == count); // it should not be removed! |
|
2117 |
|
2118 /* Save the contact again */ |
|
2119 QVERIFY(cm->saveContact(&d)); |
|
2120 d = cm->contact(d.id().localId()); |
|
2121 QVERIFY(!d.isEmpty()); |
|
2122 |
|
2123 /* Make sure the label is still the synth version */ |
|
2124 QCOMPARE(d.displayLabel(), synth); |
|
2125 |
|
2126 /* And delete the contact */ |
|
2127 QVERIFY(cm->removeContact(d.id().localId())); |
|
2128 } |
|
2129 |
|
2130 void tst_QContactManager::actionPreferences() |
|
2131 { |
|
2132 QFETCH(QString, uri); |
|
2133 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
2134 |
|
2135 // early out if the manager doesn't support action preference saving. |
|
2136 if (!cm->hasFeature(QContactManager::ActionPreferences)) { |
|
2137 QSKIP("Manager does not support action preferences", SkipSingle); |
|
2138 } |
|
2139 |
|
2140 // create a sample contact |
|
2141 QContactAvatar a; |
|
2142 a.setAvatar("test.png"); |
|
2143 QContactPhoneNumber p1; |
|
2144 p1.setNumber("12345"); |
|
2145 QContactPhoneNumber p2; |
|
2146 p2.setNumber("34567"); |
|
2147 QContactPhoneNumber p3; |
|
2148 p3.setNumber("56789"); |
|
2149 QContactUrl u; |
|
2150 u.setUrl("http://test.nokia.com"); |
|
2151 QContactName n; |
|
2152 setContactName(cm->detailDefinition(QContactName::DefinitionName, QContactType::TypeContact), n, "TestContact"); |
|
2153 |
|
2154 QContact c; |
|
2155 c.saveDetail(&a); |
|
2156 c.saveDetail(&p1); |
|
2157 c.saveDetail(&p2); |
|
2158 c.saveDetail(&p3); |
|
2159 c.saveDetail(&u); |
|
2160 c.saveDetail(&n); |
|
2161 |
|
2162 // set a preference for dialing a particular saved phonenumber. |
|
2163 c.setPreferredDetail("Dial", p2); |
|
2164 |
|
2165 QVERIFY(cm->saveContact(&c)); // save the contact |
|
2166 QContact loaded = cm->contact(c.id().localId()); // reload the contact |
|
2167 |
|
2168 // test that the preference was saved correctly. |
|
2169 QContactDetail pref = loaded.preferredDetail("Dial"); |
|
2170 QVERIFY(pref == p2); |
|
2171 |
|
2172 cm->removeContact(c.id().localId()); |
|
2173 } |
|
2174 |
|
2175 void tst_QContactManager::changeSet() |
|
2176 { |
|
2177 QContactLocalId id(1); |
|
2178 |
|
2179 QContactChangeSet cs; |
|
2180 QVERIFY(cs.addedContacts().isEmpty()); |
|
2181 QVERIFY(cs.changedContacts().isEmpty()); |
|
2182 QVERIFY(cs.removedContacts().isEmpty()); |
|
2183 |
|
2184 cs.addedContacts().insert(id); |
|
2185 QVERIFY(!cs.addedContacts().isEmpty()); |
|
2186 QVERIFY(cs.changedContacts().isEmpty()); |
|
2187 QVERIFY(cs.removedContacts().isEmpty()); |
|
2188 QVERIFY(cs.addedContacts().contains(id)); |
|
2189 |
|
2190 cs.changedContacts().insert(id); |
|
2191 cs.changedContacts().insert(id); |
|
2192 QVERIFY(cs.changedContacts().size() == 1); // set, should only be added once. |
|
2193 QVERIFY(!cs.addedContacts().isEmpty()); |
|
2194 QVERIFY(!cs.changedContacts().isEmpty()); |
|
2195 QVERIFY(cs.removedContacts().isEmpty()); |
|
2196 QVERIFY(cs.changedContacts().contains(id)); |
|
2197 |
|
2198 QVERIFY(cs.dataChanged() == false); |
|
2199 QContactChangeSet cs2; |
|
2200 cs2 = cs; |
|
2201 QVERIFY(cs.addedContacts() == cs2.addedContacts()); |
|
2202 cs.emitSignals(0); |
|
2203 |
|
2204 cs2.clear(); |
|
2205 QVERIFY(cs.addedContacts() != cs2.addedContacts()); |
|
2206 |
|
2207 QContactChangeSet cs3(cs2); |
|
2208 QVERIFY(cs.addedContacts() != cs3.addedContacts()); |
|
2209 QVERIFY(cs2.addedContacts() == cs3.addedContacts()); |
|
2210 |
|
2211 cs.setDataChanged(true); |
|
2212 QVERIFY(cs.dataChanged() == true); |
|
2213 QVERIFY(cs.dataChanged() != cs2.dataChanged()); |
|
2214 QVERIFY(cs.dataChanged() != cs3.dataChanged()); |
|
2215 cs.emitSignals(0); |
|
2216 |
|
2217 cs.addedRelationshipsContacts().insert(id); |
|
2218 cs.emitSignals(0); |
|
2219 cs.removedRelationshipsContacts().insert(id); |
|
2220 cs.emitSignals(0); |
|
2221 |
|
2222 cs.oldAndNewSelfContactId() = QPair<QContactLocalId, QContactLocalId>(QContactLocalId(0), id); |
|
2223 cs2 = cs; |
|
2224 QVERIFY(cs2.addedRelationshipsContacts() == cs.addedRelationshipsContacts()); |
|
2225 QVERIFY(cs2.removedRelationshipsContacts() == cs.removedRelationshipsContacts()); |
|
2226 QVERIFY(cs2.oldAndNewSelfContactId() == cs.oldAndNewSelfContactId()); |
|
2227 cs.emitSignals(0); |
|
2228 cs.oldAndNewSelfContactId() = QPair<QContactLocalId, QContactLocalId>(id, QContactLocalId(0)); |
|
2229 QVERIFY(cs2.oldAndNewSelfContactId() != cs.oldAndNewSelfContactId()); |
|
2230 cs.setDataChanged(true); |
|
2231 cs.emitSignals(0); |
|
2232 } |
|
2233 |
|
2234 void tst_QContactManager::selfContactId() |
|
2235 { |
|
2236 QFETCH(QString, uri); |
|
2237 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
2238 |
|
2239 // early out if the manager doesn't support self contact id saving |
|
2240 QContactLocalId selfContact = cm->selfContactId(); |
|
2241 if (!cm->hasFeature(QContactManager::SelfContact)) { |
|
2242 // ensure that the error codes / return values are meaningful failures. |
|
2243 QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
|
2244 QVERIFY(!cm->setSelfContactId(QContactLocalId(123))); |
|
2245 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2246 QSKIP("Manager does not support the concept of a self-contact", SkipSingle); |
|
2247 } |
|
2248 |
|
2249 // create a new "self" contact and retrieve its Id |
|
2250 QVERIFY(cm->error() == QContactManager::NoError || cm->error() == QContactManager::DoesNotExistError); |
|
2251 QContact self; |
|
2252 QContactPhoneNumber selfPhn; |
|
2253 selfPhn.setNumber("12345"); |
|
2254 self.saveDetail(&selfPhn); |
|
2255 if (!cm->saveContact(&self)) { |
|
2256 QSKIP("Unable to save the generated self contact", SkipSingle); |
|
2257 } |
|
2258 QContactLocalId newSelfContact = self.localId(); |
|
2259 |
|
2260 // Setup signal spy |
|
2261 qRegisterMetaType<QContactLocalId>("QContactLocalId"); |
|
2262 QSignalSpy spy(cm.data(), SIGNAL(selfContactIdChanged(QContactLocalId,QContactLocalId))); |
|
2263 |
|
2264 // Set new self contact |
|
2265 QVERIFY(cm->setSelfContactId(newSelfContact)); |
|
2266 QVERIFY(cm->error() == QContactManager::NoError); |
|
2267 QTRY_VERIFY(spy.count() == 1); |
|
2268 QVERIFY(spy.at(0).count() == 2); |
|
2269 // note: for some reason qvariant_cast<QContactLocalId>(spy.at(0).at(0)) returns always zero |
|
2270 // because the type is not recognized. Hence the ugly casting below. |
|
2271 QVERIFY(*((const QContactLocalId*) spy.at(0).at(0).constData()) == selfContact); |
|
2272 QVERIFY(*((const QContactLocalId*) spy.at(0).at(1).constData()) == newSelfContact); |
|
2273 QVERIFY(cm->selfContactId() == newSelfContact); |
|
2274 |
|
2275 // Remove self contact |
|
2276 if(!cm->removeContact(self.localId())) { |
|
2277 QSKIP("Unable to remove self contact", SkipSingle); |
|
2278 } |
|
2279 QTRY_VERIFY(spy.count() == 2); |
|
2280 QVERIFY(spy.at(1).count() == 2); |
|
2281 QVERIFY(*((const QContactLocalId*) spy.at(1).at(0).constData()) == newSelfContact); |
|
2282 QVERIFY(*((const QContactLocalId*) spy.at(1).at(1).constData()) == QContactLocalId(0)); |
|
2283 QVERIFY(cm->selfContactId() == QContactLocalId(0)); // ensure reset after removed. |
|
2284 |
|
2285 // reset to original state. |
|
2286 cm->setSelfContactId(selfContact); |
|
2287 } |
|
2288 |
|
2289 QList<QContactDetail> tst_QContactManager::removeAllDefaultDetails(const QList<QContactDetail>& details) |
|
2290 { |
|
2291 QList<QContactDetail> newlist; |
|
2292 foreach (const QContactDetail d, details) { |
|
2293 if (d.definitionName() != QContactDisplayLabel::DefinitionName |
|
2294 && d.definitionName() != QContactType::DefinitionName |
|
2295 && d.definitionName() != QContactTimestamp::DefinitionName) { |
|
2296 newlist << d; |
|
2297 } |
|
2298 } |
|
2299 return newlist; |
|
2300 } |
|
2301 |
|
2302 void tst_QContactManager::detailOrders() |
|
2303 { |
|
2304 QFETCH(QString, uri); |
|
2305 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
2306 |
|
2307 if (!cm->hasFeature(QContactManager::DetailOrdering)) |
|
2308 QSKIP("Skipping: This manager does not support detail ordering!", SkipSingle); |
|
2309 |
|
2310 QContact a; |
|
2311 //phone numbers |
|
2312 |
|
2313 QContactDetailDefinition d = cm->detailDefinition(QContactPhoneNumber::DefinitionName, QContactType::TypeContact); |
|
2314 QContactDetailFieldDefinition supportedContexts = d.fields().value(QContactDetail::FieldContext); |
|
2315 QString contextOther = QContactDetail::ContextOther; |
|
2316 if (!supportedContexts.allowableValues().contains(contextOther)) { |
|
2317 contextOther = QString(); |
|
2318 } |
|
2319 |
|
2320 QContactPhoneNumber number1, number2, number3; |
|
2321 |
|
2322 number1.setNumber("11111111"); |
|
2323 number1.setContexts(QContactPhoneNumber::ContextHome); |
|
2324 |
|
2325 number2.setNumber("22222222"); |
|
2326 number2.setContexts(QContactPhoneNumber::ContextWork); |
|
2327 |
|
2328 number3.setNumber("33333333"); |
|
2329 if (!contextOther.isEmpty()) |
|
2330 number3.setContexts(contextOther); |
|
2331 |
|
2332 a.saveDetail(&number1); |
|
2333 a.saveDetail(&number2); |
|
2334 a.saveDetail(&number3); |
|
2335 |
|
2336 QVERIFY(cm->saveContact(&a)); |
|
2337 a = cm->contact(a.id().localId()); |
|
2338 |
|
2339 QList<QContactDetail> details = a.details(QContactPhoneNumber::DefinitionName); |
|
2340 QVERIFY(details.count() == 3); |
|
2341 QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome); |
|
2342 QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextWork); |
|
2343 QVERIFY(details.at(2).value(QContactPhoneNumber::FieldContext) == contextOther); |
|
2344 |
|
2345 QVERIFY(a.removeDetail(&number2)); |
|
2346 QVERIFY(cm->saveContact(&a)); |
|
2347 a = cm->contact(a.id().localId()); |
|
2348 details = a.details(QContactPhoneNumber::DefinitionName); |
|
2349 QVERIFY(details.count() == 2); |
|
2350 QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome); |
|
2351 QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == contextOther); |
|
2352 |
|
2353 a.saveDetail(&number2); |
|
2354 QVERIFY(cm->saveContact(&a)); |
|
2355 a = cm->contact(a.id().localId()); |
|
2356 |
|
2357 details = a.details(QContactPhoneNumber::DefinitionName); |
|
2358 QVERIFY(details.count() == 3); |
|
2359 QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome); |
|
2360 QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == contextOther); |
|
2361 QVERIFY(details.at(2).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextWork); |
|
2362 |
|
2363 //addresses |
|
2364 |
|
2365 d = cm->detailDefinition(QContactAddress::DefinitionName, QContactType::TypeContact); |
|
2366 supportedContexts = d.fields().value(QContactDetail::FieldContext); |
|
2367 contextOther = QString(QLatin1String(QContactDetail::ContextOther)); |
|
2368 if (!supportedContexts.allowableValues().contains(contextOther)) { |
|
2369 contextOther = QString(); |
|
2370 } |
|
2371 |
|
2372 QContactAddress address1, address2, address3; |
|
2373 |
|
2374 address1.setStreet("Brandl St"); |
|
2375 address1.setRegion("Brisbane"); |
|
2376 address3 = address2 = address1; |
|
2377 |
|
2378 address1.setContexts(QContactAddress::ContextHome); |
|
2379 address2.setContexts(QContactAddress::ContextWork); |
|
2380 if (!contextOther.isEmpty()) |
|
2381 address3.setContexts(contextOther); |
|
2382 |
|
2383 a.saveDetail(&address1); |
|
2384 a.saveDetail(&address2); |
|
2385 a.saveDetail(&address3); |
|
2386 |
|
2387 QVERIFY(cm->saveContact(&a)); |
|
2388 a = cm->contact(a.id().localId()); |
|
2389 |
|
2390 details = a.details(QContactAddress::DefinitionName); |
|
2391 QVERIFY(details.count() == 3); |
|
2392 |
|
2393 QVERIFY(details.at(0).value(QContactAddress::FieldContext) == QContactAddress::ContextHome); |
|
2394 QVERIFY(details.at(1).value(QContactAddress::FieldContext) == QContactAddress::ContextWork); |
|
2395 QVERIFY(details.at(2).value(QContactAddress::FieldContext) == contextOther); |
|
2396 |
|
2397 QVERIFY(a.removeDetail(&address2)); |
|
2398 QVERIFY(cm->saveContact(&a)); |
|
2399 a = cm->contact(a.id().localId()); |
|
2400 details = a.details(QContactAddress::DefinitionName); |
|
2401 QVERIFY(details.count() == 2); |
|
2402 QVERIFY(details.at(0).value(QContactAddress::FieldContext) == QContactAddress::ContextHome); |
|
2403 QVERIFY(details.at(1).value(QContactAddress::FieldContext) == contextOther); |
|
2404 |
|
2405 a.saveDetail(&address2); |
|
2406 QVERIFY(cm->saveContact(&a)); |
|
2407 a = cm->contact(a.id().localId()); |
|
2408 |
|
2409 details = a.details(QContactAddress::DefinitionName); |
|
2410 QVERIFY(details.count() == 3); |
|
2411 QVERIFY(details.at(0).value(QContactAddress::FieldContext) == QContactAddress::ContextHome); |
|
2412 QVERIFY(details.at(1).value(QContactAddress::FieldContext) == contextOther); |
|
2413 QVERIFY(details.at(2).value(QContactAddress::FieldContext) == QContactAddress::ContextWork); |
|
2414 |
|
2415 |
|
2416 //emails |
|
2417 d = cm->detailDefinition(QContactEmailAddress::DefinitionName, QContactType::TypeContact); |
|
2418 supportedContexts = d.fields().value(QContactDetail::FieldContext); |
|
2419 contextOther = QString(QLatin1String(QContactDetail::ContextOther)); |
|
2420 if (!supportedContexts.allowableValues().contains(contextOther)) { |
|
2421 contextOther = QString(); |
|
2422 } |
|
2423 |
|
2424 QContactEmailAddress email1, email2, email3; |
|
2425 |
|
2426 email1.setEmailAddress("aaron@example.com"); |
|
2427 email3 = email2 = email1; |
|
2428 email1.setContexts(QContactEmailAddress::ContextHome); |
|
2429 email2.setContexts(QContactEmailAddress::ContextWork); |
|
2430 if (!contextOther.isEmpty()) |
|
2431 email3.setContexts(contextOther); |
|
2432 |
|
2433 a.saveDetail(&email1); |
|
2434 a.saveDetail(&email2); |
|
2435 a.saveDetail(&email3); |
|
2436 |
|
2437 QVERIFY(cm->saveContact(&a)); |
|
2438 a = cm->contact(a.id().localId()); |
|
2439 |
|
2440 details = a.details(QContactEmailAddress::DefinitionName); |
|
2441 QVERIFY(details.count() == 3); |
|
2442 |
|
2443 QVERIFY(details.at(0).value(QContactEmailAddress::FieldContext) == QContactEmailAddress::ContextHome); |
|
2444 QVERIFY(details.at(1).value(QContactEmailAddress::FieldContext) == QContactEmailAddress::ContextWork); |
|
2445 QVERIFY(details.at(2).value(QContactEmailAddress::FieldContext) == contextOther); |
|
2446 |
|
2447 QVERIFY(a.removeDetail(&email2)); |
|
2448 QVERIFY(cm->saveContact(&a)); |
|
2449 a = cm->contact(a.id().localId()); |
|
2450 details = a.details(QContactEmailAddress::DefinitionName); |
|
2451 QVERIFY(details.count() == 2); |
|
2452 QVERIFY(details.at(0).value(QContactEmailAddress::FieldContext) == QContactEmailAddress::ContextHome); |
|
2453 QVERIFY(details.at(1).value(QContactEmailAddress::FieldContext) == contextOther); |
|
2454 |
|
2455 a.saveDetail(&email2); |
|
2456 QVERIFY(cm->saveContact(&a)); |
|
2457 a = cm->contact(a.id().localId()); |
|
2458 |
|
2459 details = a.details(QContactEmailAddress::DefinitionName); |
|
2460 QVERIFY(details.count() == 3); |
|
2461 QVERIFY(details.at(0).value(QContactEmailAddress::FieldContext) == QContactEmailAddress::ContextHome); |
|
2462 QVERIFY(details.at(1).value(QContactEmailAddress::FieldContext) == contextOther); |
|
2463 QVERIFY(details.at(2).value(QContactEmailAddress::FieldContext) == QContactEmailAddress::ContextWork); |
|
2464 |
|
2465 QVERIFY(cm->removeContact(a.id().localId())); |
|
2466 QVERIFY(cm->error() == QContactManager::NoError); |
|
2467 } |
|
2468 |
|
2469 void tst_QContactManager::relationships() |
|
2470 { |
|
2471 QFETCH(QString, uri); |
|
2472 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
2473 |
|
2474 // save some contacts |
|
2475 QContact source; |
|
2476 QContact dest1, dest2, dest3, dest4; |
|
2477 QContactPhoneNumber n1, n2, n3, n4; |
|
2478 n1.setNumber("1"); |
|
2479 n2.setNumber("2"); |
|
2480 n3.setNumber("3"); |
|
2481 n4.setNumber("4"); |
|
2482 |
|
2483 dest1.saveDetail(&n1); |
|
2484 dest2.saveDetail(&n2); |
|
2485 dest3.saveDetail(&n3); |
|
2486 dest4.saveDetail(&n3); |
|
2487 |
|
2488 cm->saveContact(&source); |
|
2489 cm->saveContact(&dest1); |
|
2490 cm->saveContact(&dest2); |
|
2491 cm->saveContact(&dest3); |
|
2492 cm->saveContact(&dest4); |
|
2493 |
|
2494 // check if manager supports relationships |
|
2495 if (!cm->hasFeature(QContactManager::Relationships)) { |
|
2496 // ensure that the operations all fail as required. |
|
2497 QContactRelationship r1, r2, r3; |
|
2498 r1.setFirst(source.id()); |
|
2499 r1.setSecond(dest1.id()); |
|
2500 r1.setRelationshipType(QContactRelationship::HasManager); |
|
2501 r2.setFirst(source.id()); |
|
2502 r2.setSecond(dest2.id()); |
|
2503 r2.setRelationshipType(QContactRelationship::HasManager); |
|
2504 r3.setFirst(source.id()); |
|
2505 r3.setSecond(dest3.id()); |
|
2506 r3.setRelationshipType(QContactRelationship::HasManager); |
|
2507 |
|
2508 QList<QContactRelationship> batchList; |
|
2509 batchList << r2 << r3; |
|
2510 |
|
2511 // test save and remove |
|
2512 QVERIFY(!cm->saveRelationship(&r1)); |
|
2513 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2514 QVERIFY(!cm->removeRelationship(r1)); |
|
2515 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2516 QVERIFY(cm->saveRelationships(&batchList).isEmpty()); |
|
2517 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2518 QVERIFY(cm->removeRelationships(batchList).isEmpty()); |
|
2519 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2520 |
|
2521 // test retrieval |
|
2522 QList<QContactRelationship> retrieveList; |
|
2523 retrieveList = cm->relationships(source.id(), QContactRelationshipFilter::First); |
|
2524 QVERIFY(retrieveList.isEmpty()); |
|
2525 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2526 retrieveList = cm->relationships(source.id(), QContactRelationshipFilter::Second); |
|
2527 QVERIFY(retrieveList.isEmpty()); |
|
2528 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2529 retrieveList = cm->relationships(source.id()); // Either |
|
2530 QVERIFY(retrieveList.isEmpty()); |
|
2531 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2532 |
|
2533 |
|
2534 retrieveList = cm->relationships(QContactRelationship::HasManager, source.id(), QContactRelationshipFilter::First); |
|
2535 QVERIFY(retrieveList.isEmpty()); |
|
2536 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2537 retrieveList = cm->relationships(QContactRelationship::HasManager, source.id(), QContactRelationshipFilter::Second); |
|
2538 QVERIFY(retrieveList.isEmpty()); |
|
2539 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2540 retrieveList = cm->relationships(QContactRelationship::HasManager, source.id(), QContactRelationshipFilter::Either); |
|
2541 QVERIFY(retrieveList.isEmpty()); |
|
2542 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2543 retrieveList = cm->relationships(QContactRelationship::HasManager, source.id()); |
|
2544 QVERIFY(retrieveList.isEmpty()); |
|
2545 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2546 retrieveList = cm->relationships(QContactRelationship::HasManager); |
|
2547 QVERIFY(retrieveList.isEmpty()); |
|
2548 QVERIFY(cm->error() == QContactManager::NotSupportedError); |
|
2549 return; |
|
2550 } |
|
2551 |
|
2552 // Get supported relationship types |
|
2553 QStringList availableRelationshipTypes = cm->supportedRelationshipTypes(); |
|
2554 |
|
2555 // Check arbitary relationship support |
|
2556 if (cm->hasFeature(QContactManager::ArbitraryRelationshipTypes)) { |
|
2557 // add some arbitary type for testing |
|
2558 if (availableRelationshipTypes.count()) |
|
2559 availableRelationshipTypes.insert(0, "test-arbitrary-relationship-type"); |
|
2560 else { |
|
2561 availableRelationshipTypes.append("test-arbitrary-relationship-type"); |
|
2562 availableRelationshipTypes.append(QContactRelationship::HasMember); |
|
2563 availableRelationshipTypes.append(QContactRelationship::HasAssistant); |
|
2564 } |
|
2565 } |
|
2566 |
|
2567 // Verify that we have relationship types. If there are none then the manager |
|
2568 // is saying it supports relationships but does not actually implement any |
|
2569 // relationship type. |
|
2570 QVERIFY(!availableRelationshipTypes.isEmpty()); |
|
2571 |
|
2572 // Some backends (eg. symbian) require that when type is "HasMember" |
|
2573 // then "first" contact must be a group. |
|
2574 if (availableRelationshipTypes.at(0) == QContactRelationship::HasMember) { |
|
2575 cm->removeContact(source.localId()); |
|
2576 source.setId(QContactId()); |
|
2577 source.setType(QContactType::TypeGroup); |
|
2578 cm->saveContact(&source); |
|
2579 } |
|
2580 |
|
2581 // Create some common contact id's for testing |
|
2582 QContactId dest1Uri = dest1.id(); |
|
2583 QContactId dest1EmptyUri; |
|
2584 dest1EmptyUri.setManagerUri(QString()); |
|
2585 dest1EmptyUri.setLocalId(dest1.id().localId()); |
|
2586 QContactId dest2Uri = dest2.id(); |
|
2587 QContactId dest3Uri = dest3.id(); |
|
2588 QContactId dest3EmptyUri; |
|
2589 dest3EmptyUri.setManagerUri(QString()); |
|
2590 dest3EmptyUri.setLocalId(dest3.id().localId()); |
|
2591 |
|
2592 // build our relationship - source is the manager all of the dest contacts. |
|
2593 QContactRelationship customRelationshipOne; |
|
2594 customRelationshipOne.setFirst(source.id()); |
|
2595 customRelationshipOne.setSecond(dest1EmptyUri); |
|
2596 customRelationshipOne.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2597 QCOMPARE(customRelationshipOne.first(), source.id()); |
|
2598 QCOMPARE(customRelationshipOne.second(), dest1EmptyUri); |
|
2599 QVERIFY(customRelationshipOne.relationshipType() == availableRelationshipTypes.at(0)); |
|
2600 |
|
2601 // save the relationship |
|
2602 int managerRelationshipsCount = cm->relationships(availableRelationshipTypes.at(0)).count(); |
|
2603 QVERIFY(cm->saveRelationship(&customRelationshipOne)); |
|
2604 // test that the empty manager URI has been updated. |
|
2605 QCOMPARE(customRelationshipOne.second(), dest1Uri); // updated with correct manager URI |
|
2606 |
|
2607 // test our accessors. |
|
2608 QCOMPARE(cm->relationships(availableRelationshipTypes.at(0)).count(), (managerRelationshipsCount + 1)); |
|
2609 QVERIFY(cm->relationships(availableRelationshipTypes.at(0), source.id()).count() == 1); |
|
2610 |
|
2611 // remove the dest1 contact, relationship should be removed. |
|
2612 cm->removeContact(dest1.localId()); |
|
2613 QCOMPARE(cm->relationships(availableRelationshipTypes.at(0), dest1Uri, QContactRelationshipFilter::Second).count(), 0); |
|
2614 |
|
2615 // modify and save the relationship |
|
2616 customRelationshipOne.setSecond(dest2Uri); |
|
2617 QVERIFY(cm->saveRelationship(&customRelationshipOne)); |
|
2618 |
|
2619 // attempt to save the relationship again. XXX TODO: what should the result be? currently succeeds (overwrites) |
|
2620 int relationshipsCount = cm->relationships().count(); |
|
2621 QVERIFY(cm->saveRelationship(&customRelationshipOne)); // succeeds, but just overwrites |
|
2622 QCOMPARE(relationshipsCount, cm->relationships().count()); // shouldn't change; save should have overwritten. |
|
2623 |
|
2624 // removing the source contact should result in removal of the relationship. |
|
2625 QVERIFY(cm->removeContact(source.id().localId())); |
|
2626 QCOMPARE(cm->relationships().count(), relationshipsCount - 1); // the relationship should have been removed. |
|
2627 |
|
2628 // now ensure that qcontact relationship caching works as required - perhaps this should be in tst_QContact? |
|
2629 source.setId(QContactId()); // reset id so we can resave |
|
2630 QVERIFY(cm->saveContact(&source)); // save source again. |
|
2631 customRelationshipOne.setFirst(source.id()); |
|
2632 customRelationshipOne.setSecond(dest2.id()); |
|
2633 QVERIFY(cm->saveRelationship(&customRelationshipOne)); |
|
2634 |
|
2635 // Add a second relationship |
|
2636 QContactRelationship customRelationshipTwo; |
|
2637 customRelationshipTwo.setFirst(source.id()); |
|
2638 if (availableRelationshipTypes.count() > 1) |
|
2639 customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(1)); |
|
2640 else |
|
2641 customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2642 customRelationshipTwo.setSecond(dest3.id()); |
|
2643 QVERIFY(cm->saveRelationship(&customRelationshipTwo)); |
|
2644 |
|
2645 // currently, the contacts are "stale" - no cached relationships |
|
2646 QVERIFY(dest3.relatedContacts().isEmpty()); |
|
2647 QVERIFY(dest3.relationships().isEmpty()); |
|
2648 QVERIFY(dest2.relatedContacts().isEmpty()); |
|
2649 QVERIFY(dest2.relationships().isEmpty()); |
|
2650 |
|
2651 // now refresh the contacts |
|
2652 dest3 = cm->contact(dest3.localId()); |
|
2653 dest2 = cm->contact(dest2.localId()); |
|
2654 source = cm->contact(source.localId()); |
|
2655 |
|
2656 // and test again. |
|
2657 QVERIFY(source.relatedContacts(QString(), QContactRelationshipFilter::First).isEmpty()); // source is always the first, so this should be empty. |
|
2658 QVERIFY(source.relatedContacts(QString(), QContactRelationshipFilter::Second).contains(dest2.id())); |
|
2659 QVERIFY(source.relatedContacts(QString(), QContactRelationshipFilter::Either).contains(dest2.id())); |
|
2660 QVERIFY(source.relatedContacts(QString(), QContactRelationshipFilter::Second).contains(dest3.id())); |
|
2661 QVERIFY(source.relatedContacts(QString(), QContactRelationshipFilter::Either).contains(dest3.id())); |
|
2662 QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationshipFilter::Second).contains(dest2.id())); |
|
2663 QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationshipFilter::First).isEmpty()); |
|
2664 |
|
2665 QVERIFY(dest2.relatedContacts().contains(source.id())); |
|
2666 QVERIFY(dest2.relationships().contains(customRelationshipOne)); |
|
2667 QVERIFY(!dest2.relationships().contains(customRelationshipTwo)); |
|
2668 QVERIFY(dest2.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipOne)); |
|
2669 QVERIFY(!dest2.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipTwo)); |
|
2670 QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0)).contains(source.id())); |
|
2671 QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationshipFilter::First).contains(source.id())); |
|
2672 QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationshipFilter::Second).isEmpty()); |
|
2673 QVERIFY(!dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationshipFilter::Second).contains(source.id())); |
|
2674 |
|
2675 QVERIFY(dest3.relatedContacts().contains(source.id())); |
|
2676 QVERIFY(!dest3.relationships().contains(customRelationshipOne)); |
|
2677 QVERIFY(dest3.relationships().contains(customRelationshipTwo)); |
|
2678 QVERIFY(!dest3.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipOne)); |
|
2679 |
|
2680 // Test iteration |
|
2681 QList<QContactRelationship> relats = source.relationships(); |
|
2682 QList<QContactRelationship>::iterator it = relats.begin(); |
|
2683 |
|
2684 while (it != relats.end()) { |
|
2685 QContactId firstId = it->first(); |
|
2686 QVERIFY(firstId == source.id()); |
|
2687 QVERIFY(it->second() == dest2.id() || it->second() == dest3.id()); |
|
2688 it++; |
|
2689 } |
|
2690 |
|
2691 if (availableRelationshipTypes.count() > 1) { |
|
2692 QVERIFY(source.relatedContacts(availableRelationshipTypes.at(1), QContactRelationshipFilter::Second).contains(dest3.id())); |
|
2693 QVERIFY(source.relatedContacts(availableRelationshipTypes.at(1), QContactRelationshipFilter::First).isEmpty()); |
|
2694 |
|
2695 QVERIFY(dest2.relationships(availableRelationshipTypes.at(1)).isEmpty()); |
|
2696 |
|
2697 QVERIFY(!dest3.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipTwo)); |
|
2698 QVERIFY(dest3.relationships(availableRelationshipTypes.at(1)).contains(customRelationshipTwo)); |
|
2699 QVERIFY(!dest3.relationships(availableRelationshipTypes.at(1)).contains(customRelationshipOne)); |
|
2700 QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1)).contains(source.id())); |
|
2701 QVERIFY(!dest3.relatedContacts(availableRelationshipTypes.at(0)).contains(source.id())); |
|
2702 QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1)).contains(source.id())); // role = either |
|
2703 QVERIFY(!dest3.relatedContacts(availableRelationshipTypes.at(1), QContactRelationshipFilter::Second).contains(source.id())); |
|
2704 QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1), QContactRelationshipFilter::First).contains(source.id())); |
|
2705 QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(1)).isEmpty()); |
|
2706 } |
|
2707 else { |
|
2708 QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationshipFilter::Second).contains(dest3.id())); |
|
2709 } |
|
2710 |
|
2711 // Cleanup a bit |
|
2712 QVERIFY(cm->removeRelationship(customRelationshipOne)); |
|
2713 QVERIFY(cm->removeRelationship(customRelationshipTwo)); |
|
2714 |
|
2715 // test batch API and ordering in contacts |
|
2716 QList<QContactRelationship> currentRelationships = cm->relationships(source.id(), QContactRelationshipFilter::First); |
|
2717 QList<QContactRelationship> batchList; |
|
2718 QContactRelationship br1, br2, br3; |
|
2719 br1.setFirst(source.id()); |
|
2720 br1.setSecond(dest2.id()); |
|
2721 br1.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2722 br2.setFirst(source.id()); |
|
2723 br2.setSecond(dest3.id()); |
|
2724 br2.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2725 if (availableRelationshipTypes.count() > 1) |
|
2726 { |
|
2727 br3.setFirst(source.id()); |
|
2728 br3.setSecond(dest3.id()); |
|
2729 br3.setRelationshipType(availableRelationshipTypes.at(1)); |
|
2730 } |
|
2731 else |
|
2732 { |
|
2733 br3.setFirst(source.id()); |
|
2734 br3.setSecond(dest4.id()); |
|
2735 br3.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2736 } |
|
2737 batchList << br1 << br2 << br3; |
|
2738 |
|
2739 // ensure that the batch save works properly |
|
2740 cm->saveRelationships(&batchList); |
|
2741 QVERIFY(cm->error() == QContactManager::NoError); |
|
2742 QList<QContactRelationship> batchRetrieve = cm->relationships(source.id(), QContactRelationshipFilter::First); |
|
2743 QVERIFY(batchRetrieve.contains(br1)); |
|
2744 QVERIFY(batchRetrieve.contains(br2)); |
|
2745 QVERIFY(batchRetrieve.contains(br3)); |
|
2746 |
|
2747 // Check relationship ordering support |
|
2748 if (cm->hasFeature(QContactManager::RelationshipOrdering)) |
|
2749 { |
|
2750 // test relationship ordering in the contact |
|
2751 source = cm->contact(source.localId()); |
|
2752 QList<QContactRelationship> cachedRelationships = source.relationships(); |
|
2753 QList<QContactRelationship> orderedRelationships = source.relationshipOrder(); |
|
2754 QCOMPARE(cachedRelationships, orderedRelationships); // initially, should be the same |
|
2755 QVERIFY(orderedRelationships.contains(br1)); |
|
2756 QVERIFY(orderedRelationships.contains(br2)); |
|
2757 QVERIFY(orderedRelationships.contains(br3)); |
|
2758 |
|
2759 // ensure that the reordering works as required. |
|
2760 QContactRelationship temp1 = orderedRelationships.takeAt(0); // now fiddle with the order |
|
2761 QContactRelationship temp2 = orderedRelationships.at(0); // this is the new first relationship |
|
2762 orderedRelationships.insert(2, temp1); // and save the old first back at position 3. |
|
2763 source.setRelationshipOrder(orderedRelationships); // set the new relationship order |
|
2764 cm->saveContact(&source); // save the contact to persist the new order |
|
2765 source = cm->contact(source.localId()); // reload the contact |
|
2766 QCOMPARE(source.relationshipOrder(), orderedRelationships); // ensure that it was persisted. |
|
2767 |
|
2768 // now lets try a negative reordering test: adding relationships which don't exist in the database. |
|
2769 QContactRelationship invalidRel; |
|
2770 invalidRel.setFirst(source.id()); |
|
2771 invalidRel.setSecond(dest2.id()); |
|
2772 invalidRel.setRelationshipType("test-nokia-invalid-relationship-type"); |
|
2773 orderedRelationships << invalidRel; |
|
2774 source.setRelationshipOrder(orderedRelationships); |
|
2775 QVERIFY(!cm->saveContact(&source)); |
|
2776 QVERIFY(cm->error() == QContactManager::InvalidRelationshipError); |
|
2777 orderedRelationships.removeOne(br3); |
|
2778 source.setRelationshipOrder(orderedRelationships); |
|
2779 QVERIFY(!cm->saveContact(&source)); |
|
2780 QVERIFY(cm->error() == QContactManager::InvalidRelationshipError); |
|
2781 source.setRelationshipOrder(QList<QContactRelationship>()); |
|
2782 QVERIFY(!cm->saveContact(&source)); |
|
2783 QVERIFY(cm->error() == QContactManager::InvalidRelationshipError); |
|
2784 } |
|
2785 |
|
2786 // remove a single relationship |
|
2787 QVERIFY(cm->removeRelationship(br3)); |
|
2788 batchRetrieve = cm->relationships(source.id(), QContactRelationshipFilter::First); |
|
2789 QVERIFY(batchRetrieve.contains(br1)); |
|
2790 QVERIFY(batchRetrieve.contains(br2)); |
|
2791 QVERIFY(!batchRetrieve.contains(br3)); // has already been removed. |
|
2792 |
|
2793 // now ensure that the batch remove works and we get returned to the original state. |
|
2794 batchList.removeOne(br3); |
|
2795 cm->removeRelationships(batchList); |
|
2796 QVERIFY(cm->error() == QContactManager::NoError); |
|
2797 QCOMPARE(cm->relationships(source.id(), QContactRelationshipFilter::First), currentRelationships); |
|
2798 |
|
2799 // attempt to save relationships between an existing source but non-existent destination |
|
2800 QContactId nonexistentDest; |
|
2801 quint32 idSeed = 0x5544; |
|
2802 QContactLocalId nonexistentLocalId = QContactLocalId(idSeed); |
|
2803 nonexistentDest.setManagerUri(cm->managerUri()); |
|
2804 while (true) { |
|
2805 nonexistentLocalId = cm->contact(nonexistentLocalId).localId(); |
|
2806 if (nonexistentLocalId == QContactLocalId(0)) { |
|
2807 // found a "spare" local id (no contact with that id) |
|
2808 break; |
|
2809 } |
|
2810 |
|
2811 // keep looking... |
|
2812 idSeed += 1; |
|
2813 nonexistentLocalId = QContactLocalId(idSeed); |
|
2814 QVERIFY(nonexistentLocalId != QContactLocalId(0)); // integer overflow check. |
|
2815 } |
|
2816 nonexistentDest.setLocalId(nonexistentLocalId); |
|
2817 QContactRelationship maliciousRel; |
|
2818 maliciousRel.setFirst(source.id()); |
|
2819 maliciousRel.setSecond(nonexistentDest); |
|
2820 maliciousRel.setRelationshipType("nokia-test-invalid-relationship-type"); |
|
2821 QVERIFY(!cm->saveRelationship(&maliciousRel)); |
|
2822 |
|
2823 // attempt to save a circular relationship |
|
2824 maliciousRel.setFirst(source.id()); |
|
2825 maliciousRel.setSecond(source.id()); |
|
2826 maliciousRel.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2827 QVERIFY(!cm->saveRelationship(&maliciousRel)); |
|
2828 |
|
2829 // more negative testing, but force manager to recognise the empty URI |
|
2830 QContactId circularId = source.id(); |
|
2831 circularId.setManagerUri(QString()); |
|
2832 maliciousRel.setFirst(circularId); |
|
2833 maliciousRel.setSecond(circularId); |
|
2834 maliciousRel.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2835 QVERIFY(!cm->saveRelationship(&maliciousRel)); |
|
2836 maliciousRel.setFirst(source.id()); |
|
2837 maliciousRel.setSecond(circularId); |
|
2838 maliciousRel.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2839 QVERIFY(!cm->saveRelationship(&maliciousRel)); |
|
2840 maliciousRel.setFirst(circularId); |
|
2841 maliciousRel.setSecond(source.id()); |
|
2842 maliciousRel.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2843 QVERIFY(!cm->saveRelationship(&maliciousRel)); |
|
2844 |
|
2845 // attempt to save a relationship where the source contact comes from another manager |
|
2846 circularId.setManagerUri("test-nokia-invalid-manager-uri"); |
|
2847 maliciousRel.setFirst(circularId); // an invalid source contact |
|
2848 maliciousRel.setSecond(dest2.id()); // a valid destination contact |
|
2849 maliciousRel.setRelationshipType(availableRelationshipTypes.at(0)); |
|
2850 QVERIFY(!cm->saveRelationship(&maliciousRel)); |
|
2851 |
|
2852 // remove the nonexistent relationship |
|
2853 relationshipsCount = cm->relationships().count(); |
|
2854 QVERIFY(!cm->removeRelationship(maliciousRel)); // does not exist; fail remove. |
|
2855 QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError); |
|
2856 QCOMPARE(cm->relationships().count(), relationshipsCount); // should be unchanged. |
|
2857 |
|
2858 // now clean up and remove our dests. |
|
2859 QVERIFY(cm->removeContact(source.localId())); |
|
2860 QVERIFY(cm->removeContact(dest2.localId())); |
|
2861 QVERIFY(cm->removeContact(dest3.localId())); |
|
2862 |
|
2863 // attempt to save relationships with nonexistent contacts |
|
2864 QVERIFY(!cm->saveRelationship(&br1)); |
|
2865 QVERIFY(cm->error() == QContactManager::InvalidRelationshipError); |
|
2866 cm->saveRelationships(&batchList); |
|
2867 QVERIFY(cm->error() == QContactManager::InvalidRelationshipError); |
|
2868 QVERIFY(!cm->removeRelationship(br1)); |
|
2869 QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError); |
|
2870 cm->removeRelationships(batchList); |
|
2871 QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError); |
|
2872 } |
|
2873 |
|
2874 void tst_QContactManager::contactType() |
|
2875 { |
|
2876 QFETCH(QString, uri); |
|
2877 QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
|
2878 |
|
2879 if (!cm->hasFeature(QContactManager::Groups)) |
|
2880 QSKIP("Skipping: This manager does not support group contacts!", SkipSingle); |
|
2881 |
|
2882 QContact g1, g2, c; |
|
2883 g1.setType(QContactType::TypeGroup); |
|
2884 g2.setType(QContactType::TypeGroup); |
|
2885 |
|
2886 QContactPhoneNumber g1p, g2p, cp; |
|
2887 g1p.setNumber("22222"); |
|
2888 g2p.setNumber("11111"); |
|
2889 cp.setNumber("33333"); |
|
2890 |
|
2891 g1.saveDetail(&g1p); |
|
2892 g2.saveDetail(&g2p); |
|
2893 c.saveDetail(&cp); |
|
2894 |
|
2895 QVERIFY(cm->saveContact(&g1)); |
|
2896 QVERIFY(cm->saveContact(&g2)); |
|
2897 QVERIFY(cm->saveContact(&c)); |
|
2898 |
|
2899 // test that the accessing by type works properly |
|
2900 QContactDetailFilter groupFilter; |
|
2901 groupFilter.setDetailDefinitionName(QContactType::DefinitionName, QContactType::FieldType); |
|
2902 groupFilter.setValue(QString(QLatin1String(QContactType::TypeGroup))); |
|
2903 QVERIFY(cm->contactIds(groupFilter).contains(g1.localId())); |
|
2904 QVERIFY(cm->contactIds(groupFilter).contains(g2.localId())); |
|
2905 QVERIFY(!cm->contactIds(groupFilter).contains(c.localId())); |
|
2906 |
|
2907 QList<QContactSortOrder> sortOrders; |
|
2908 QContactSortOrder byPhoneNumber; |
|
2909 byPhoneNumber.setDetailDefinitionName(QContactPhoneNumber::DefinitionName, QContactPhoneNumber::FieldNumber); |
|
2910 sortOrders.append(byPhoneNumber); |
|
2911 |
|
2912 // and ensure that sorting works properly with typed contacts also |
|
2913 QList<QContactLocalId> sortedIds = cm->contactIds(groupFilter, sortOrders); |
|
2914 QVERIFY(sortedIds.indexOf(g2.localId()) < sortedIds.indexOf(g1.localId())); |
|
2915 |
|
2916 cm->removeContact(g1.localId()); |
|
2917 cm->removeContact(g2.localId()); |
|
2918 cm->removeContact(c.localId()); |
|
2919 } |
|
2920 |
|
2921 QTEST_MAIN(tst_QContactManager) |
|
2922 #include "tst_qcontactmanager.moc" |