1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL21$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 or version 3 as published by the Free |
20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
22 | ** following information to ensure the GNU Lesser General Public License |
23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
25 | ** |
26 | ** As a special exception, The Qt Company gives you certain additional |
27 | ** rights. These rights are described in The Qt Company LGPL Exception |
28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
29 | ** |
30 | ** $QT_END_LICENSE$ |
31 | ** |
32 | ****************************************************************************/ |
33 | |
34 | #define QT_STATICPLUGIN |
35 | |
36 | #include <QtTest/QtTest> |
37 | #include <QtGlobal> |
38 | #include <QtCore/qnumeric.h> |
39 | |
40 | #include <QtContacts> |
41 | #include "qcontactmanagerdataholder.h" |
42 | |
43 | #if defined(USE_VERSIT_PLZ) |
44 | // This makes it easier to create specific QContacts |
45 | #include <QtVersit/qversitcontactimporter.h> |
46 | #include <QtVersit/qversitdocument.h> |
47 | #include <QtVersit/qversitreader.h> |
48 | QTVERSIT_USE_NAMESPACE |
49 | #endif |
50 | |
51 | QTCONTACTS_USE_NAMESPACE |
52 | |
53 | #define QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(params) params.remove(QString::fromLatin1(QTCONTACTS_VERSION_NAME)); \ |
54 | params.remove(QString::fromLatin1(QTCONTACTS_IMPLEMENTATION_VERSION_NAME)) |
55 | |
56 | #define QTRY_COMPARE_SIGNALS_LOCALID_COUNT(__signalSpy, __expectedCount) \ |
57 | do { \ |
58 | int __spiedSigCount = 0; \ |
59 | const int __step = 50; \ |
60 | const int __timeout = 5000; \ |
61 | for (int __i = 0; __i < __timeout; __i+=__step) { \ |
62 | /* accumulate added from signals */ \ |
63 | __spiedSigCount = 0; \ |
64 | const QList<QList<QVariant> > __spiedSignals = __signalSpy; \ |
65 | foreach (const QList<QVariant> &__arguments, __spiedSignals) { \ |
66 | foreach (QContactId __localId, __arguments.first().value<QList<QContactId> >()) { \ |
67 | QVERIFY(!(__localId.isNull())); \ |
68 | __spiedSigCount++; \ |
69 | } \ |
70 | } \ |
71 | if(__spiedSigCount == __expectedCount) { \ |
72 | break; \ |
73 | } \ |
74 | QTest::qWait(__step); \ |
75 | } \ |
76 | QCOMPARE(__spiedSigCount, __expectedCount); \ |
77 | } while(0) |
78 | |
79 | //TESTED_COMPONENT=src/contacts |
80 | |
81 | // to get QFETCH to work with the template expression... |
82 | typedef QMap<QString,QString> tst_QContactManager_QStringMap; |
83 | Q_DECLARE_METATYPE(tst_QContactManager_QStringMap) |
84 | Q_DECLARE_METATYPE(QList<QContactId>) |
85 | Q_DECLARE_METATYPE(QList<QContactDetail::DetailType>) |
86 | |
87 | /* A class that no backend can support */ |
88 | class UnsupportedMetatype { |
89 | int foo; |
90 | }; |
91 | Q_DECLARE_METATYPE(UnsupportedMetatype) |
92 | Q_DECLARE_METATYPE(QContact) |
93 | Q_DECLARE_METATYPE(QContactManager::Error) |
94 | Q_DECLARE_METATYPE(Qt::CaseSensitivity) |
95 | |
96 | class tst_QContactManager : public QObject |
97 | { |
98 | Q_OBJECT |
99 | |
100 | public: |
101 | tst_QContactManager(); |
102 | virtual ~tst_QContactManager(); |
103 | |
104 | private: |
105 | void dumpContactDifferences(const QContact& a, const QContact& b); |
106 | void dumpContact(const QContact &c); |
107 | void dumpContacts(QContactManager *cm); |
108 | bool isSuperset(const QContact& ca, const QContact& cb); |
109 | QList<QContactDetail> removeAllDefaultDetails(const QList<QContactDetail>& details); |
110 | void addManagers(); // add standard managers to the data |
111 | QContact createContact(QString firstName, QString lastName, QString phoneNumber); |
112 | void saveContactName(QContact *contact,QContactName *contactName, const QString &name) const; |
113 | |
114 | QScopedPointer<QContactManagerDataHolder> managerDataHolder; |
115 | |
116 | public slots: |
117 | void initTestCase(); |
118 | void cleanupTestCase(); |
119 | private slots: |
120 | |
121 | void doDump(); |
122 | void doDump_data() {addManagers();} |
123 | |
124 | /* Special test with special data */ |
125 | void uriParsing(); |
126 | void nameSynthesis(); |
127 | |
128 | /* Tests that are run on all managers */ |
129 | void metadata(); |
130 | void nullIdOperations(); |
131 | void add(); |
132 | void update(); |
133 | void remove(); |
134 | void addAndUpdate(); |
135 | void batch(); |
136 | void observerDeletion(); |
137 | void signalEmission(); |
138 | void actionPreferences(); |
139 | void selfContactId(); |
140 | void detailOrders(); |
141 | void relationships(); |
142 | void contactType(); |
143 | void lateDeletion(); |
144 | void compareVariant(); |
145 | void createCollection(); |
146 | void modifyCollection(); |
147 | void removeCollection(); |
148 | void saveContactIntoCollections(); |
149 | |
150 | #if defined(USE_VERSIT_PLZ) |
151 | void partialSave(); |
152 | void partialSave_data() {addManagers();} |
153 | #endif |
154 | |
155 | /* Tests that take no data */ |
156 | void errorStayingPut(); |
157 | void ctors(); |
158 | void invalidManager(); |
159 | void memoryManager(); |
160 | void overrideManager(); |
161 | void changeSet(); |
162 | void fetchHint(); |
163 | void lazyConnections(); |
164 | void testInterSectionOfIdFilters(); |
165 | void testInterSectionOfIdAndDetailFilters(); |
166 | |
167 | /* Special test with special data */ |
168 | void uriParsing_data(); |
169 | void nameSynthesis_data(); |
170 | void compareVariant_data(); |
171 | |
172 | /* Tests that are run on all managers */ |
173 | void metadata_data() {addManagers();} |
174 | void nullIdOperations_data() {addManagers();} |
175 | void add_data() {addManagers();} |
176 | void update_data() {addManagers();} |
177 | void remove_data() {addManagers();} |
178 | void addAndUpdate_data() {addManagers();} |
179 | void batch_data() {addManagers();} |
180 | void signalEmission_data() {addManagers();} |
181 | void actionPreferences_data() {addManagers();} |
182 | void selfContactId_data() {addManagers();} |
183 | void detailOrders_data() {addManagers();} |
184 | void relationships_data() {addManagers();} |
185 | void contactType_data() {addManagers();} |
186 | void lateDeletion_data() {addManagers();} |
187 | void testInterSectionOfIdFilters_data() {addManagers();} |
188 | void testInterSectionOfIdAndDetailFilters_data() {addManagers();} |
189 | void createCollection_data() {addManagers();} |
190 | void modifyCollection_data() {addManagers();} |
191 | void removeCollection_data() {addManagers();} |
192 | void saveContactIntoCollections_data() {addManagers();} |
193 | }; |
194 | |
195 | // Helper class that connects to a signal on ctor, and disconnects on dtor |
196 | class QTestSignalSink : public QObject { |
197 | Q_OBJECT |
198 | public: |
199 | // signal and object must remain valid for the lifetime |
200 | QTestSignalSink(QObject *object, const char *signal) |
201 | : mObject(object), mSignal(signal) |
202 | { |
203 | connect(sender: object, signal, receiver: this, SLOT(ignored())); |
204 | } |
205 | |
206 | ~QTestSignalSink() |
207 | { |
208 | disconnect(sender: mObject, signal: mSignal, receiver: this, SLOT(ignored())); |
209 | } |
210 | |
211 | public slots: |
212 | void ignored() {} |
213 | |
214 | private: |
215 | QObject *mObject; |
216 | const char * const mSignal; |
217 | }; |
218 | |
219 | QT_BEGIN_NAMESPACE |
220 | static uint qHash(const QMetaMethod &m) |
221 | { |
222 | return qHash(key: m.methodIndex()); |
223 | } |
224 | QT_END_NAMESPACE |
225 | |
226 | /* Two backends for testing lazy signal connections */ |
227 | class QContactLazyEngine2 : public QContactManagerEngine |
228 | { |
229 | public: |
230 | QContactLazyEngine2() {} |
231 | QString managerName() const {return "lazy2" ;} |
232 | |
233 | /*! \reimp */ |
234 | int managerVersion() const {return 0;} |
235 | |
236 | void connectNotify(const QMetaMethod &signal) |
237 | { |
238 | connectionCounts[signal]++; |
239 | } |
240 | void disconnectNotify(const QMetaMethod &signal) |
241 | { |
242 | connectionCounts[signal]--; |
243 | } |
244 | |
245 | static QHash<QMetaMethod, int> connectionCounts; // signal to count |
246 | }; |
247 | QHash<QMetaMethod, int> QContactLazyEngine2::connectionCounts; |
248 | |
249 | class QContactLazyEngine : public QContactManagerEngine |
250 | { |
251 | public: |
252 | QContactLazyEngine() {} |
253 | QString managerName() const { |
254 | return "lazy" ;} |
255 | |
256 | /*! \reimp */ |
257 | int managerVersion() const {return 0;} |
258 | |
259 | void connectNotify(const QMetaMethod &signal) |
260 | { |
261 | connectionCounts[signal]++; |
262 | } |
263 | void disconnectNotify(const QMetaMethod &signal) |
264 | { |
265 | connectionCounts[signal]--; |
266 | } |
267 | static QHash<QMetaMethod, int> connectionCounts; // signal to count |
268 | }; |
269 | QHash<QMetaMethod, int> QContactLazyEngine::connectionCounts; |
270 | |
271 | /* Static lazy engine factory */ |
272 | class LazyEngineFactory : public QContactManagerEngineFactory |
273 | { |
274 | Q_OBJECT |
275 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QContactManagerEngineFactoryInterface" FILE "lazy.json" ) |
276 | public: |
277 | QContactManagerEngine* engine(const QMap<QString, QString>& parameters, QContactManager::Error* error); |
278 | QString managerName() const {return "testlazy" ;} |
279 | }; |
280 | |
281 | QContactManagerEngine* LazyEngineFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error) |
282 | { |
283 | // Return one or the other |
284 | Q_UNUSED(error) |
285 | if (parameters.value(akey: "version" ) == QString("1" )) |
286 | return new QContactLazyEngine(); |
287 | else |
288 | return new QContactLazyEngine2(); |
289 | } |
290 | |
291 | static inline QContactId makeId(const QString &managerName, uint id) |
292 | { |
293 | return QContactId(QStringLiteral("qtcontacts:basic%1:" ).arg(a: managerName), QByteArray(reinterpret_cast<const char *>(&id), sizeof(uint))); |
294 | } |
295 | |
296 | tst_QContactManager::tst_QContactManager() |
297 | { |
298 | } |
299 | |
300 | tst_QContactManager::~tst_QContactManager() |
301 | { |
302 | } |
303 | |
304 | void tst_QContactManager::initTestCase() |
305 | { |
306 | managerDataHolder.reset(other: new QContactManagerDataHolder()); |
307 | |
308 | /* Make sure these other test plugins are NOT loaded by default */ |
309 | // These are now removed from the list of managers in addManagers() |
310 | //QVERIFY(!QContactManager::availableManagers().contains("testdummy")); |
311 | //QVERIFY(!QContactManager::availableManagers().contains("teststaticdummy")); |
312 | //QVERIFY(!QContactManager::availableManagers().contains("maliciousplugin")); |
313 | } |
314 | |
315 | void tst_QContactManager::cleanupTestCase() |
316 | { |
317 | managerDataHolder.reset(other: 0); |
318 | } |
319 | |
320 | void tst_QContactManager::dumpContactDifferences(const QContact& ca, const QContact& cb) |
321 | { |
322 | // Try to narrow down the differences |
323 | QContact a(ca); |
324 | QContact b(cb); |
325 | |
326 | QContactName n1 = a.detail(type: QContactName::Type); |
327 | QContactName n2 = b.detail(type: QContactName::Type); |
328 | |
329 | // Check the name components in more detail |
330 | QCOMPARE(n1.firstName(), n2.firstName()); |
331 | QCOMPARE(n1.middleName(), n2.middleName()); |
332 | QCOMPARE(n1.lastName(), n2.lastName()); |
333 | QCOMPARE(n1.prefix(), n2.prefix()); |
334 | QCOMPARE(n1.suffix(), n2.suffix()); |
335 | |
336 | // Now look at the rest |
337 | QList<QContactDetail> aDetails = a.details(); |
338 | QList<QContactDetail> bDetails = b.details(); |
339 | |
340 | // They can be in any order, so loop |
341 | // First remove any matches |
342 | foreach(QContactDetail d, aDetails) { |
343 | foreach(QContactDetail d2, bDetails) { |
344 | if(d == d2) { |
345 | a.removeDetail(detail: &d); |
346 | b.removeDetail(detail: &d2); |
347 | break; |
348 | } |
349 | } |
350 | } |
351 | |
352 | // Now dump the extra details that were unmatched in A (note that Type is always present). |
353 | // We ignore timestamp since it can get autogenerated too |
354 | aDetails = a.details(); |
355 | bDetails = b.details(); |
356 | foreach(QContactDetail d, aDetails) { |
357 | if (d.type() != QContactType::Type && d.type() != QContactTimestamp::Type) |
358 | qDebug() << "A contact had extra detail:" << d.type() << d.values(); |
359 | } |
360 | // and same for B |
361 | foreach(QContactDetail d, bDetails) { |
362 | if (d.type() != QContactType::Type && d.type() != QContactTimestamp::Type) |
363 | qDebug() << "B contact had extra detail:" << d.type() << d.values(); |
364 | } |
365 | |
366 | if (a.type() != b.type()) { |
367 | qDebug() << "A contact type =" << a.type(); |
368 | qDebug() << "B contact type =" << b.type(); |
369 | } |
370 | } |
371 | |
372 | bool tst_QContactManager::isSuperset(const QContact& ca, const QContact& cb) |
373 | { |
374 | // returns true if contact ca is a superset of contact cb |
375 | // we use this test instead of equality because dynamic information |
376 | // such as presence/location, and synthesized information such as (possibly) type, |
377 | // may differ between a contact in memory and the contact in the managed store. |
378 | |
379 | QContact a(ca); |
380 | QContact b(cb); |
381 | QList<QContactDetail> aDetails = a.details(); |
382 | QList<QContactDetail> bDetails = b.details(); |
383 | |
384 | // They can be in any order, so loop |
385 | // First remove any matches |
386 | foreach(QContactDetail d, aDetails) { |
387 | foreach(QContactDetail d2, bDetails) { |
388 | if(d == d2) { |
389 | a.removeDetail(detail: &d); |
390 | b.removeDetail(detail: &d2); |
391 | break; |
392 | } |
393 | } |
394 | } |
395 | |
396 | // Second remove any superset matches (eg, backend adds a field) |
397 | aDetails = a.details(); |
398 | bDetails = b.details(); |
399 | foreach (QContactDetail d, aDetails) { |
400 | foreach (QContactDetail d2, bDetails) { |
401 | if (d.type() == d2.type()) { |
402 | bool canRemove = true; |
403 | QMap<int, QVariant> d2map = d2.values(); |
404 | foreach (int key, d2map.keys()) { |
405 | if (d.value(field: key) != d2.value(field: key)) { |
406 | // d can have _more_ keys than d2, |
407 | // but not _less_; and it cannot |
408 | // change the value. |
409 | canRemove = false; |
410 | } |
411 | } |
412 | |
413 | if (canRemove) { |
414 | // if we get to here, we can remove the details. |
415 | a.removeDetail(detail: &d); |
416 | b.removeDetail(detail: &d2); |
417 | break; |
418 | } |
419 | } |
420 | } |
421 | } |
422 | |
423 | QList<QContactType::TypeValues> validTypes; |
424 | validTypes << QContactType::TypeContact << QContactType::TypeGroup; |
425 | // check for contact type updates |
426 | if (validTypes.contains(t: a.type())) |
427 | if (validTypes.contains(t: b.type())) |
428 | if (a.type() != b.type()) |
429 | return false; // nonempty type is different. |
430 | |
431 | // Now check to see if b has any details remaining; if so, a is not a superset. |
432 | // Note Type can never be removed. |
433 | if (b.details().size() > 1 |
434 | || (b.details().size() == 1 && (b.details().value(i: 0).type() != QContactType::Type))) |
435 | return false; |
436 | return true; |
437 | } |
438 | |
439 | void tst_QContactManager::dumpContact(const QContact& contact) |
440 | { |
441 | QContactManager m; |
442 | qDebug() << "Contact: " << contact.id(); |
443 | QList<QContactDetail> details = contact.details(); |
444 | foreach(QContactDetail d, details) { |
445 | qDebug() << " " << d.type() << ":" ; |
446 | qDebug() << " Vals:" << d.values(); |
447 | } |
448 | } |
449 | |
450 | void tst_QContactManager::dumpContacts(QContactManager *cm) |
451 | { |
452 | QList<QContactId> ids = cm->contactIds(); |
453 | |
454 | qDebug() << "There are" << ids.count() << "contacts in" << cm->managerUri(); |
455 | |
456 | foreach (QContactId id, ids) { |
457 | QContact c = cm->contact(contactId: id); |
458 | dumpContact(contact: c); |
459 | } |
460 | } |
461 | |
462 | void tst_QContactManager::uriParsing_data() |
463 | { |
464 | QTest::addColumn<QString>(name: "uri" ); |
465 | QTest::addColumn<bool>(name: "good" ); // is this a good uri or not |
466 | QTest::addColumn<QString>(name: "manager" ); |
467 | QTest::addColumn<QMap<QString, QString> >(name: "parameters" ); |
468 | |
469 | QMap<QString, QString> inparameters; |
470 | inparameters.insert(key: "foo" , value: "bar" ); |
471 | inparameters.insert(key: "bazflag" , value: QString()); |
472 | inparameters.insert(key: "bar" , value: "glob" ); |
473 | |
474 | QMap<QString, QString> inparameters2; |
475 | inparameters2.insert(key: "this has spaces" , value: QString()); |
476 | inparameters2.insert(key: "and& an" , value: " &" ); |
477 | inparameters2.insert(key: "and an " , value: "=quals" ); |
478 | |
479 | QTest::newRow(dataTag: "built" ) << QContactManager::buildUri(managerName: "manager" , params: inparameters) << true << "manager" << inparameters; |
480 | QTest::newRow(dataTag: "built with escaped parameters" ) << QContactManager::buildUri(managerName: "manager" , params: inparameters2) << true << "manager" << inparameters2; |
481 | QTest::newRow(dataTag: "no scheme" ) << "this should not split" << false << QString() << tst_QContactManager_QStringMap(); |
482 | QTest::newRow(dataTag: "wrong scheme" ) << "invalidscheme:foo bar" << false << QString() << tst_QContactManager_QStringMap(); |
483 | QTest::newRow(dataTag: "right scheme, no colon" ) << "qtcontacts" << false << QString() << tst_QContactManager_QStringMap(); |
484 | QTest::newRow(dataTag: "no manager, colon, no params" ) << "qtcontacts::" << false << "manager" << tst_QContactManager_QStringMap(); |
485 | QTest::newRow(dataTag: "yes manager, no colon, no params" ) << "qtcontacts:manager" << true << "manager" << tst_QContactManager_QStringMap(); |
486 | QTest::newRow(dataTag: "yes manager, yes colon, no params" ) << "qtcontacts:manager:" << true << "manager" << tst_QContactManager_QStringMap(); |
487 | QTest::newRow(dataTag: "yes params" ) << "qtcontacts:manager:foo=bar&bazflag=&bar=glob" << true << "manager" << inparameters; |
488 | QTest::newRow(dataTag: "yes params but misformed" ) << "qtcontacts:manager:foo=bar&=gloo&bar=glob" << false << "manager" << inparameters; |
489 | QTest::newRow(dataTag: "yes params but misformed 2" ) << "qtcontacts:manager:=&=gloo&bar=glob" << false << "manager" << inparameters; |
490 | QTest::newRow(dataTag: "yes params but misformed 3" ) << "qtcontacts:manager:==" << false << "manager" << inparameters; |
491 | QTest::newRow(dataTag: "yes params but misformed 4" ) << "qtcontacts:manager:&&" << false << "manager" << inparameters; |
492 | QTest::newRow(dataTag: "yes params but misformed 5" ) << "qtcontacts:manager:&goo=bar" << false << "manager" << inparameters; |
493 | QTest::newRow(dataTag: "yes params but misformed 6" ) << "qtcontacts:manager:goo&bar" << false << "manager" << inparameters; |
494 | QTest::newRow(dataTag: "yes params but misformed 7" ) << "qtcontacts:manager:goo&bar&gob" << false << "manager" << inparameters; |
495 | QTest::newRow(dataTag: "yes params but misformed 8" ) << "qtcontacts:manager:==&&==&goo=bar" << false << "manager" << inparameters; |
496 | QTest::newRow(dataTag: "yes params but misformed 9" ) << "qtcontacts:manager:foo=bar=baz" << false << "manager" << inparameters; |
497 | QTest::newRow(dataTag: "yes params but misformed 10" ) << "qtcontacts:manager:foo=bar=baz=glob" << false << "manager" << inparameters; |
498 | QTest::newRow(dataTag: "no manager but yes params" ) << "qtcontacts::foo=bar&bazflag=&bar=glob" << false << QString() << inparameters; |
499 | QTest::newRow(dataTag: "no manager or params" ) << "qtcontacts::" << false << QString() << inparameters; |
500 | QTest::newRow(dataTag: "no manager or params or colon" ) << "qtcontacts:" << false << QString() << inparameters; |
501 | } |
502 | |
503 | void tst_QContactManager::addManagers() |
504 | { |
505 | QTest::addColumn<QString>(name: "uri" ); |
506 | |
507 | QStringList managers = QContactManager::availableManagers(); |
508 | |
509 | /* Known one that will not pass */ |
510 | managers.removeAll(t: "invalid" ); |
511 | managers.removeAll(t: "testdummy" ); |
512 | managers.removeAll(t: "teststaticdummy" ); |
513 | managers.removeAll(t: "maliciousplugin" ); |
514 | managers.removeAll(t: "testlazy" ); |
515 | |
516 | // "internal" engines |
517 | managers.removeAll(t: "social" ); |
518 | managers.removeAll(t: "simcard" ); |
519 | managers.removeAll(t: "com.nokia.messaging.contacts.engines.mail.contactslookup" ); |
520 | |
521 | |
522 | foreach(QString mgr, managers) { |
523 | QMap<QString, QString> params; |
524 | QTest::newRow(dataTag: QString("mgr='%1'" ).arg(a: mgr).toLatin1().constData()) << QContactManager::buildUri(managerName: mgr, params); |
525 | if (mgr == "memory" ) { |
526 | params.insert(key: "id" , value: "tst_QContactManager" ); |
527 | QTest::newRow(dataTag: QString("mgr='%1', params" ).arg(a: mgr).toLatin1().constData()) << QContactManager::buildUri(managerName: mgr, params); |
528 | } |
529 | } |
530 | } |
531 | |
532 | /* |
533 | * Helper method for creating a QContact instance with name and phone number |
534 | * details. |
535 | */ |
536 | QContact tst_QContactManager::createContact( |
537 | QString firstName, |
538 | QString lastName, |
539 | QString phoneNumber) |
540 | { |
541 | QContact contact; |
542 | QContactName n; |
543 | |
544 | if (!firstName.isEmpty()) { |
545 | n.setFirstName(firstName); |
546 | }; |
547 | if (!lastName.isEmpty()) { |
548 | n.setLastName(lastName); |
549 | } |
550 | if (!n.isEmpty()) { |
551 | contact.saveDetail(detail: &n); |
552 | } |
553 | |
554 | if (!phoneNumber.isEmpty()) { |
555 | QContactPhoneNumber ph; |
556 | ph.setNumber(phoneNumber); |
557 | contact.saveDetail(detail: &ph); |
558 | } |
559 | |
560 | return contact; |
561 | } |
562 | |
563 | void tst_QContactManager::saveContactName(QContact *contact, QContactName *contactName, const QString &name) const |
564 | { |
565 | contactName->setFirstName(name); |
566 | contactName->setLastName(name); |
567 | contact->saveDetail(detail: contactName); |
568 | } |
569 | |
570 | void tst_QContactManager::metadata() |
571 | { |
572 | // ensure that the backend is publishing its metadata (name / parameters / uri) correctly |
573 | QFETCH(QString, uri); |
574 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
575 | QVERIFY(QContactManager::buildUri(cm->managerName(), cm->managerParameters()) == cm->managerUri()); |
576 | } |
577 | |
578 | |
579 | void tst_QContactManager::nullIdOperations() |
580 | { |
581 | QFETCH(QString, uri); |
582 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
583 | QVERIFY(!cm->removeContact(QContactId())); |
584 | QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
585 | |
586 | |
587 | QContact c = cm->contact(contactId: QContactId()); |
588 | QVERIFY(c.id() == QContactId()); |
589 | QVERIFY(c.isEmpty()); |
590 | QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
591 | } |
592 | |
593 | void tst_QContactManager::uriParsing() |
594 | { |
595 | QFETCH(QString, uri); |
596 | QFETCH(bool, good); |
597 | QFETCH(QString, manager); |
598 | QFETCH(tst_QContactManager_QStringMap, parameters); |
599 | |
600 | QString outmanager; |
601 | QMap<QString, QString> outparameters; |
602 | |
603 | if (good) { |
604 | /* Good split */ |
605 | /* Test splitting */ |
606 | QVERIFY(QContactManager::parseUri(uri, 0, 0)); // no out parms |
607 | |
608 | // 1 out param |
609 | QVERIFY(QContactManager::parseUri(uri, &outmanager, 0)); |
610 | QCOMPARE(manager, outmanager); |
611 | QVERIFY(QContactManager::parseUri(uri, 0, &outparameters)); |
612 | |
613 | QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
614 | |
615 | QCOMPARE(parameters, outparameters); |
616 | |
617 | outmanager.clear(); |
618 | outparameters.clear(); |
619 | QVERIFY(QContactManager::parseUri(uri, &outmanager, &outparameters)); |
620 | |
621 | QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
622 | |
623 | QCOMPARE(manager, outmanager); |
624 | QCOMPARE(parameters, outparameters); |
625 | } else { |
626 | /* bad splitting */ |
627 | outmanager.clear(); |
628 | outparameters.clear(); |
629 | QVERIFY(QContactManager::parseUri(uri, 0, 0) == false); |
630 | QVERIFY(QContactManager::parseUri(uri, &outmanager, 0) == false); |
631 | QVERIFY(outmanager.isEmpty()); |
632 | QVERIFY(QContactManager::parseUri(uri, 0, &outparameters) == false); |
633 | QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
634 | QVERIFY(outparameters.isEmpty()); |
635 | |
636 | /* make sure the in parameters don't change with a bad split */ |
637 | outmanager = manager; |
638 | outparameters = parameters; |
639 | QVERIFY(QContactManager::parseUri(uri, &outmanager, 0) == false); |
640 | QCOMPARE(manager, outmanager); |
641 | QVERIFY(QContactManager::parseUri(uri, 0, &outparameters) == false); |
642 | QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters); |
643 | QCOMPARE(parameters, outparameters); |
644 | } |
645 | } |
646 | |
647 | void tst_QContactManager::ctors() |
648 | { |
649 | /* test the different ctors to make sure we end up with the same uri */ |
650 | QVERIFY(QContactManager::availableManagers().count() >= 1); // invalid + something else |
651 | QVERIFY(QContactManager::availableManagers().contains("invalid" )); |
652 | QString defaultStore = QContactManager::availableManagers().value(i: 0); |
653 | |
654 | qDebug() << "Available managers:" << QContactManager::availableManagers(); |
655 | |
656 | QMap<QString, QString> randomParameters; |
657 | randomParameters.insert(key: "something" , value: "old" ); |
658 | randomParameters.insert(key: "something..." , value: "new" ); |
659 | randomParameters.insert(key: "something " , value: "borrowed" ); |
660 | randomParameters.insert(key: " something" , value: "blue" ); |
661 | |
662 | QObject parent; |
663 | |
664 | QContactManager cm; // default |
665 | QContactManager cm2(defaultStore); |
666 | QContactManager cm3(defaultStore, QMap<QString, QString>()); |
667 | |
668 | QContactManager cm9b(0); // QObject* ctor, should be same as cm2 etc |
669 | QContactManager cm9c(&parent); // same as cm2 etc. |
670 | |
671 | QScopedPointer<QContactManager> cm5(QContactManager::fromUri(uri: QContactManager::buildUri(managerName: defaultStore, params: QMap<QString, QString>()))); |
672 | QScopedPointer<QContactManager> cm6(QContactManager::fromUri(uri: cm.managerUri())); // uri is not a name; should fail. |
673 | QScopedPointer<QContactManager> cm9(QContactManager::fromUri(uri: QString(), parent: &parent)); |
674 | |
675 | QVERIFY(cm9->parent() == &parent); |
676 | QVERIFY(cm9b.parent() == 0); |
677 | QVERIFY(cm9c.parent() == &parent); |
678 | |
679 | |
680 | /* OLD TEST WAS THIS: */ |
681 | //QCOMPARE(cm.managerUri(), cm2.managerUri()); |
682 | //QCOMPARE(cm.managerUri(), cm3.managerUri()); |
683 | //QCOMPARE(cm.managerUri(), cm5->managerUri()); |
684 | //QCOMPARE(cm.managerUri(), cm6->managerUri()); |
685 | //QCOMPARE(cm.managerUri(), cm9->managerUri()); |
686 | /* NEW TEST IS THIS: Test that the names of the managers are the same */ |
687 | QCOMPARE(cm.managerName(), cm2.managerName()); |
688 | QCOMPARE(cm.managerName(), cm3.managerName()); |
689 | QCOMPARE(cm.managerName(), cm5->managerName()); |
690 | QCOMPARE(cm.managerName(), cm6->managerName()); |
691 | QCOMPARE(cm.managerName(), cm9->managerName()); |
692 | QCOMPARE(cm.managerName(), cm9b.managerName()); |
693 | QCOMPARE(cm.managerName(), cm9c.managerName()); |
694 | |
695 | /* Test that we get invalid stores when we do silly things */ |
696 | QContactManager em("non existent" ); |
697 | QContactManager em2("non existent" , QMap<QString, QString>()); |
698 | QContactManager em3("memory" , randomParameters); |
699 | |
700 | /* Also invalid, since we don't have one of these anyway */ |
701 | QScopedPointer<QContactManager> em4(QContactManager::fromUri(uri: "invalid uri" )); |
702 | QScopedPointer<QContactManager> em5(QContactManager::fromUri(uri: QContactManager::buildUri(managerName: "nonexistent" , params: QMap<QString, QString>()))); |
703 | QScopedPointer<QContactManager> em6(QContactManager::fromUri(uri: em3.managerUri())); |
704 | |
705 | |
706 | /* |
707 | * Sets of stores that should be equivalent: |
708 | * - 1, 2, 4, 5 |
709 | * - 3, 6 |
710 | */ |
711 | |
712 | /* First some URI testing for equivalent stores */ |
713 | QVERIFY(em.managerUri() == em2.managerUri()); |
714 | QVERIFY(em.managerUri() == em5->managerUri()); |
715 | QVERIFY(em.managerUri() == em4->managerUri()); |
716 | QVERIFY(em2.managerUri() == em4->managerUri()); |
717 | QVERIFY(em2.managerUri() == em5->managerUri()); |
718 | QVERIFY(em4->managerUri() == em5->managerUri()); |
719 | |
720 | QVERIFY(em3.managerUri() == em6->managerUri()); |
721 | |
722 | /* Test the stores that should not be the same */ |
723 | QVERIFY(em.managerUri() != em3.managerUri()); |
724 | QVERIFY(em.managerUri() != em6->managerUri()); |
725 | |
726 | /* now the components */ |
727 | QCOMPARE(em.managerName(), QString("invalid" )); |
728 | QCOMPARE(em2.managerName(), QString("invalid" )); |
729 | QCOMPARE(em3.managerName(), QString("memory" )); |
730 | QCOMPARE(em4->managerName(), QString("invalid" )); |
731 | QCOMPARE(em5->managerName(), QString("invalid" )); |
732 | QCOMPARE(em6->managerName(), QString("memory" )); |
733 | QCOMPARE(em.managerParameters(), tst_QContactManager_QStringMap()); |
734 | QCOMPARE(em2.managerParameters(), tst_QContactManager_QStringMap()); |
735 | QCOMPARE(em4->managerParameters(), tst_QContactManager_QStringMap()); |
736 | QCOMPARE(em5->managerParameters(), tst_QContactManager_QStringMap()); |
737 | QCOMPARE(em3.managerParameters(), em6->managerParameters()); // memory engine discards the given params, replaces with id. |
738 | |
739 | // Finally test the platform specific engines are actually the defaults |
740 | QCOMPARE(defaultStore, QString("invalid" )); |
741 | } |
742 | |
743 | void tst_QContactManager::doDump() |
744 | { |
745 | // Only do this if it has been explicitly selected |
746 | if (QCoreApplication::arguments().contains(str: "doDump" )) { |
747 | QFETCH(QString, uri); |
748 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
749 | |
750 | dumpContacts(cm: cm.data()); |
751 | } |
752 | } |
753 | |
754 | Q_DECLARE_METATYPE(QVariant) |
755 | |
756 | |
757 | void tst_QContactManager::add() |
758 | { |
759 | QFETCH(QString, uri); |
760 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
761 | |
762 | QContact alice = createContact(firstName: "Alice" , lastName: "inWonderland" , phoneNumber: "1234567" ); |
763 | int currCount = cm->contactIds().count(); |
764 | QVERIFY(cm->saveContact(&alice)); |
765 | QVERIFY(cm->error() == QContactManager::NoError); |
766 | |
767 | QVERIFY(!alice.id().managerUri().isEmpty()); |
768 | QVERIFY(!(alice.id().isNull())); |
769 | QCOMPARE(cm->contactIds().count(), currCount+1); |
770 | |
771 | QContact added = cm->contact(contactId: alice.id()); |
772 | QVERIFY(added.id() == alice.id()); |
773 | |
774 | if (!isSuperset(ca: added, cb: alice)) { |
775 | dumpContacts(cm: cm.data()); |
776 | dumpContactDifferences(ca: added, cb: alice); |
777 | QCOMPARE(added, alice); |
778 | } |
779 | |
780 | // now a contact with many details of a particular definition |
781 | // if the detail is not unique it should then support minimum of two of the same kind |
782 | const int nrOfdetails = 2; |
783 | QContact veryContactable = createContact(firstName: "Very" , lastName: "Contactable" , phoneNumber: "" ); |
784 | for (int i = 0; i < nrOfdetails; i++) { |
785 | QString phnStr = QString::number(i); |
786 | QContactPhoneNumber vcphn; |
787 | vcphn.setNumber(phnStr); |
788 | QVERIFY(veryContactable.saveDetail(&vcphn)); |
789 | } |
790 | |
791 | // check that all the numbers were added successfully |
792 | QVERIFY(veryContactable.details(QContactPhoneNumber::Type).size() == nrOfdetails); |
793 | |
794 | // check if it can be saved |
795 | QVERIFY(cm->saveContact(&veryContactable)); |
796 | |
797 | // verify save |
798 | QContact retrievedContactable = cm->contact(contactId: veryContactable.id()); |
799 | if (!isSuperset(ca: retrievedContactable, cb: veryContactable)) { |
800 | dumpContactDifferences(ca: veryContactable, cb: retrievedContactable); |
801 | QCOMPARE(veryContactable, retrievedContactable); |
802 | } |
803 | } |
804 | |
805 | void tst_QContactManager::testInterSectionOfIdAndDetailFilters() |
806 | { |
807 | QFETCH(QString, uri); |
808 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
809 | |
810 | //prepare filter data |
811 | QContact alice = createContact(firstName: "Alice" , lastName: "inWonderland" , phoneNumber: "1234567" ); |
812 | QVERIFY(cm->saveContact(&alice)); |
813 | |
814 | QContact john = createContact(firstName: "John" , lastName: "inFinland" , phoneNumber: "2345678" ); |
815 | QVERIFY(cm->saveContact(&john)); |
816 | |
817 | QContactIdFilter idFilter1; |
818 | QList<QContactId> contactIdList; |
819 | contactIdList.append(t: alice.id()); |
820 | idFilter1.setIds(contactIdList); |
821 | |
822 | QContactDetailFilter df; |
823 | df.setDetailType(type: QContactName::Type,field: QContactName::FieldFirstName); |
824 | df.setValue("Alice" ); |
825 | |
826 | contactIdList.clear(); |
827 | |
828 | QContactIntersectionFilter isf; |
829 | isf.append(filter: idFilter1); |
830 | isf.append(filter: df); |
831 | |
832 | //Intersection filter of a matching Idfilter and detailfilter |
833 | QList<QContact> contactList = cm->contacts(filter: isf); |
834 | QCOMPARE(contactList.size(), 1); |
835 | |
836 | contactIdList.clear(); |
837 | |
838 | //Intersection filter of a non matching Idfilter and detailfilter |
839 | isf.remove(filter: df); |
840 | df.setValue("John" ); |
841 | isf.append(filter: df); |
842 | |
843 | contactList = cm->contacts(filter: isf); |
844 | QCOMPARE(contactList.size(), 0); |
845 | } |
846 | |
847 | void tst_QContactManager::testInterSectionOfIdFilters() |
848 | { |
849 | QFETCH(QString, uri); |
850 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
851 | |
852 | //prepare filter data |
853 | QContact alice = createContact(firstName: "Alice" , lastName: "inWonderland" , phoneNumber: "1234567" ); |
854 | QVERIFY(cm->saveContact(&alice)); |
855 | |
856 | QContact john = createContact(firstName: "John" , lastName: "inFinland" , phoneNumber: "2345678" ); |
857 | QVERIFY(cm->saveContact(&john)); |
858 | |
859 | QContactIdFilter idFilter1; |
860 | QList<QContactId> contactIdList; |
861 | contactIdList.append(t: alice.id()); |
862 | idFilter1.setIds(contactIdList); |
863 | |
864 | QContactIdFilter idFilter2; |
865 | contactIdList.clear(); |
866 | contactIdList.append(t: john.id()); |
867 | idFilter2.setIds(contactIdList); |
868 | |
869 | contactIdList.clear(); |
870 | |
871 | //Test intersection filter with two different idFilters |
872 | QContactIntersectionFilter isf; |
873 | isf.append(filter: idFilter1); |
874 | isf.append(filter: idFilter2); |
875 | |
876 | QList<QContact> contactList = cm->contacts(filter: idFilter1); |
877 | QCOMPARE(contactList.size(), 1); |
878 | QCOMPARE(contactList.at(0).id(), alice.id()); |
879 | |
880 | contactIdList.clear(); |
881 | |
882 | //When we intersect with two idFilters each having different |
883 | //contact Ids the result should be zero |
884 | contactList = cm->contacts(filter: isf); |
885 | QCOMPARE(contactList.size(), 0); |
886 | |
887 | |
888 | //Test intersection filter with two idFilters |
889 | //each having same contactid as other the result should be 1 |
890 | isf.remove(filter: idFilter2); |
891 | contactIdList.append(t: alice.id()); |
892 | idFilter2.setIds(contactIdList); |
893 | |
894 | contactIdList.clear(); |
895 | |
896 | isf.append(filter: idFilter2); |
897 | contactList = cm->contacts(filter: isf); |
898 | QCOMPARE(contactList.size(), 1); |
899 | |
900 | contactIdList.clear(); |
901 | |
902 | // Test intersection filter with two idFilters |
903 | // idFilter1 has alice's contactId |
904 | // And idfilter2 has alice's and John's contactId |
905 | // The result should be one and its alice |
906 | |
907 | contactIdList << alice.id() << john.id(); |
908 | idFilter2.setIds(contactIdList); |
909 | isf.append(filter: idFilter2); |
910 | |
911 | contactIdList.clear(); |
912 | |
913 | contactList = cm->contacts(filter: isf); |
914 | QCOMPARE(contactList.size(), 1); |
915 | QCOMPARE(contactList.at(0).id(), alice.id()); |
916 | |
917 | //clean up filters and the contactIdList |
918 | isf.remove(filter: idFilter2); |
919 | isf.remove(filter: idFilter1); |
920 | contactIdList.clear(); |
921 | |
922 | //Test with null contactId filter: idFilter1 has one contact and idFilter2 has null id |
923 | //idFilters with null id should not return any thing so result should be zero |
924 | contactIdList.append(t: alice.id()); |
925 | idFilter1.setIds(contactIdList); |
926 | contactIdList.clear(); |
927 | contactIdList.append(t: QContactId()); |
928 | idFilter2.setIds(contactIdList); |
929 | isf.append(filter: idFilter1); |
930 | isf.append(filter: idFilter2); |
931 | QCOMPARE(isf.filters().size(), 2); |
932 | contactList = cm->contacts(filter: isf); |
933 | QCOMPARE(contactList.size(), 0); |
934 | |
935 | //clean up filters and the contactIdList |
936 | isf.remove(filter: idFilter2); |
937 | isf.remove(filter: idFilter1); |
938 | contactIdList.clear(); |
939 | |
940 | //Three filters: intersection of two IdFilters each having the same contact id |
941 | //as the other with an IdFilter having one different contactId the result should be zero |
942 | contactIdList.append(t: alice.id()); |
943 | idFilter1.setIds(contactIdList); |
944 | contactIdList.clear(); |
945 | |
946 | contactIdList.append(t: john.id()); |
947 | idFilter2.setIds(contactIdList); |
948 | contactIdList.clear(); |
949 | |
950 | QContactIdFilter idFilter3; |
951 | contactIdList.append(t: john.id()); |
952 | idFilter3.setIds(contactIdList); |
953 | contactIdList.clear(); |
954 | |
955 | isf.append(filter: idFilter1); |
956 | isf.append(filter: idFilter2); |
957 | isf.append(filter: idFilter3); |
958 | |
959 | QCOMPARE(isf.filters().size(), 3); |
960 | contactList = cm->contacts(filter: isf); |
961 | QCOMPARE(contactList.size(), 0); |
962 | |
963 | //clean up filters and the contactIdList |
964 | isf.remove(filter: idFilter1); |
965 | isf.remove(filter: idFilter2); |
966 | isf.remove(filter: idFilter3); |
967 | contactIdList.clear(); |
968 | } |
969 | |
970 | void tst_QContactManager::update() |
971 | { |
972 | QFETCH(QString, uri); |
973 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
974 | |
975 | /* Save a new contact first */ |
976 | int contactCount = cm->contacts().size(); |
977 | QContact alice = createContact(firstName: "Alice" , lastName: "inWonderland" , phoneNumber: "1234567" ); |
978 | QVERIFY(cm->saveContact(&alice)); |
979 | QVERIFY(cm->error() == QContactManager::NoError); |
980 | contactCount += 1; // added a new contact. |
981 | QCOMPARE(cm->contacts().size(), contactCount); |
982 | |
983 | /* Update name */ |
984 | QContactName name = alice.detail(type: QContactName::Type); |
985 | saveContactName(contact: &alice, contactName: &name, name: "updated" ); |
986 | QVERIFY(cm->saveContact(&alice)); |
987 | QVERIFY(cm->error() == QContactManager::NoError); |
988 | saveContactName(contact: &alice, contactName: &name, name: "updated2" ); |
989 | QVERIFY(cm->saveContact(&alice)); |
990 | QVERIFY(cm->error() == QContactManager::NoError); |
991 | alice = cm->contact(contactId: alice.id()); // force reload of (persisted) alice |
992 | QContact updated = cm->contact(contactId: alice.id()); |
993 | QContactName updatedName = updated.detail(type: QContactName::Type); |
994 | updatedName.setFirstName("updated2" ); // Necessary to ensure that updatedName and name are actually the same |
995 | QCOMPARE(updatedName, name); |
996 | QCOMPARE(cm->contacts().size(), contactCount); // contact count should be the same, no new contacts |
997 | |
998 | /* Test that adding a new detail doesn't cause unwanted side effects */ |
999 | int detailCount = alice.details().size(); |
1000 | QContactEmailAddress email; |
1001 | email.setEmailAddress("test@example.com" ); |
1002 | alice.saveDetail(detail: &email); |
1003 | QVERIFY(cm->saveContact(&alice)); |
1004 | QCOMPARE(cm->contacts().size(), contactCount); // contact count shoudl be the same, no new contacts |
1005 | |
1006 | // This test is dangerous, since backends can add timestamps etc... |
1007 | detailCount += 1; |
1008 | QCOMPARE(detailCount, alice.details().size()); // adding a detail should cause the detail count to increase by one. |
1009 | /* Test that removal of fields in a detail works */ |
1010 | QContactPhoneNumber phn = alice.detail<QContactPhoneNumber>(); |
1011 | phn.setNumber("1234567" ); |
1012 | phn.setContexts(QContactDetail::ContextHome); |
1013 | alice.saveDetail(detail: &phn); |
1014 | QVERIFY(cm->saveContact(&alice)); |
1015 | alice = cm->contact(contactId: alice.id()); // force reload of (persisted) alice |
1016 | QVERIFY(alice.detail<QContactPhoneNumber>().contexts().contains(QContactDetail::ContextHome)); // check context saved. |
1017 | phn = alice.detail<QContactPhoneNumber>(); // reload the detail, since it's key could have changed |
1018 | phn.setContexts(QList<int> ()); // remove context field. |
1019 | alice.saveDetail(detail: &phn); |
1020 | QVERIFY(cm->saveContact(&alice)); |
1021 | alice = cm->contact(contactId: alice.id()); // force reload of (persisted) alice |
1022 | QVERIFY(alice.detail<QContactPhoneNumber>().contexts().isEmpty()); // check context removed. |
1023 | QCOMPARE(cm->contacts().size(), contactCount); // removal of a field of a detail shouldn't affect the contact count |
1024 | |
1025 | // This test is dangerous, since backends can add timestamps etc... |
1026 | QCOMPARE(detailCount, alice.details().size()); // removing a field from a detail should affect the detail count |
1027 | |
1028 | /* Test that removal of details works */ |
1029 | phn = alice.detail<QContactPhoneNumber>(); // reload the detail, since it's key could have changed |
1030 | alice.removeDetail(detail: &phn); |
1031 | QVERIFY(cm->saveContact(&alice)); |
1032 | alice = cm->contact(contactId: alice.id()); // force reload of (persisted) alice |
1033 | QVERIFY(alice.details<QContactPhoneNumber>().isEmpty()); // no such detail. |
1034 | QCOMPARE(cm->contacts().size(), contactCount); // removal of a detail shouldn't affect the contact count |
1035 | |
1036 | // This test is dangerous, since backends can add timestamps etc... |
1037 | //detailCount -= 1; |
1038 | //QCOMPARE(detailCount, alice.details().size()); // removing a detail should cause the detail count to decrease by one. |
1039 | |
1040 | if (cm->supportedContactTypes().contains(t: QContactType::TypeGroup)) { |
1041 | // Try changing types - not allowed |
1042 | // from contact -> group |
1043 | alice.setType(QContactType::TypeGroup); |
1044 | QContactName na = alice.detail(type: QContactName::Type); |
1045 | alice.removeDetail(detail: &na); |
1046 | QVERIFY(!cm->saveContact(&alice)); |
1047 | QVERIFY(cm->error() == QContactManager::AlreadyExistsError); |
1048 | |
1049 | // from group -> contact |
1050 | QContact jabberwock = createContact(firstName: "" , lastName: "" , phoneNumber: "1234567890" ); |
1051 | jabberwock.setType(QContactType::TypeGroup); |
1052 | QVERIFY(cm->saveContact(&jabberwock)); |
1053 | jabberwock.setType(QContactType::TypeContact); |
1054 | QVERIFY(!cm->saveContact(&jabberwock)); |
1055 | QVERIFY(cm->error() == QContactManager::AlreadyExistsError); |
1056 | } |
1057 | } |
1058 | |
1059 | void tst_QContactManager::remove() |
1060 | { |
1061 | QFETCH(QString, uri); |
1062 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
1063 | |
1064 | /* Save a new contact first */ |
1065 | QContact alice = createContact(firstName: "Alice" , lastName: "inWonderland" , phoneNumber: "1234567" ); |
1066 | QVERIFY(cm->saveContact(&alice)); |
1067 | QVERIFY(cm->error() == QContactManager::NoError); |
1068 | QVERIFY(alice.id() != QContactId()); |
1069 | |
1070 | /* Remove the created contact */ |
1071 | const int contactCount = cm->contactIds().count(); |
1072 | QVERIFY(cm->removeContact(alice.id())); |
1073 | QCOMPARE(cm->contactIds().count(), contactCount - 1); |
1074 | QVERIFY(cm->contact(alice.id()).isEmpty()); |
1075 | QCOMPARE(cm->error(), QContactManager::DoesNotExistError); |
1076 | } |
1077 | |
1078 | void tst_QContactManager::addAndUpdate() |
1079 | { |
1080 | QFETCH(QString, uri); |
1081 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
1082 | int originalCount = cm->contactIds().size(); |
1083 | // save a few new contacts |
1084 | QList<QContact> saveList; |
1085 | QContactName nameDetail; |
1086 | for (int i=0; i<20; i++) { |
1087 | QContact testContact; |
1088 | nameDetail.setFirstName(QStringLiteral("Test Contact " ) + QString::number(i)); |
1089 | testContact.saveDetail(detail: &nameDetail); |
1090 | saveList << testContact; |
1091 | } |
1092 | QMap<int, QContactManager::Error> errorMap; |
1093 | cm->saveContacts(contacts: &saveList, errorMap: &errorMap); |
1094 | QCOMPARE(cm->contactIds().size(), originalCount + saveList.size()); |
1095 | QCOMPARE(errorMap.size(), 0); |
1096 | // update previously saved contacts |
1097 | for (int i=0; i<saveList.size(); i++) { |
1098 | QContactPhoneNumber phn; |
1099 | phn.setNumber(QString::number(i)); |
1100 | saveList[i].saveDetail(detail: &phn); |
1101 | } |
1102 | // add new contacts in front of the saveList list |
1103 | for (int i=20; i<40; i++) { |
1104 | QContact testContact; |
1105 | QContactName nameDetail; |
1106 | nameDetail.setFirstName(QStringLiteral("Test Contact " ) + QString::number(i)); |
1107 | testContact.saveDetail(detail: &nameDetail); |
1108 | saveList.insert(i: 0, t: testContact); |
1109 | } |
1110 | cm->saveContacts(contacts: &saveList, errorMap: &errorMap); |
1111 | QCOMPARE(cm->contactIds().size(), originalCount + saveList.size()); |
1112 | QCOMPARE(errorMap.size(), 0); |
1113 | foreach (const QContact contact, saveList) { |
1114 | QVERIFY(cm->removeContact(contact.id())); |
1115 | } |
1116 | } |
1117 | |
1118 | void tst_QContactManager::batch() |
1119 | { |
1120 | QFETCH(QString, uri); |
1121 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
1122 | |
1123 | /* First test null pointer operations */ |
1124 | QVERIFY(!cm->saveContacts(NULL, NULL)); |
1125 | QVERIFY(cm->error() == QContactManager::BadArgumentError); |
1126 | |
1127 | QVERIFY(!cm->removeContacts(QList<QContactId>(), NULL)); |
1128 | QVERIFY(cm->error() == QContactManager::BadArgumentError); |
1129 | |
1130 | // Get supported name field |
1131 | int nameField = QContactName::FieldFirstName; |
1132 | |
1133 | /* Now add 3 contacts, all valid */ |
1134 | QContact a; |
1135 | QContactName na; |
1136 | na.setValue(field: nameField, value: "XXXXXX Albert" ); |
1137 | a.saveDetail(detail: &na); |
1138 | |
1139 | QContact b; |
1140 | QContactName nb; |
1141 | nb.setValue(field: nameField, value: "XXXXXX Bob" ); |
1142 | b.saveDetail(detail: &nb); |
1143 | |
1144 | QContact c; |
1145 | QContactName nc; |
1146 | nc.setValue(field: nameField, value: "XXXXXX Carol" ); |
1147 | c.saveDetail(detail: &nc); |
1148 | |
1149 | QList<QContact> contacts; |
1150 | contacts << a << b << c; |
1151 | |
1152 | QMap<int, QContactManager::Error> errorMap; |
1153 | // Add one dummy error to test if the errors are reset |
1154 | errorMap.insert(key: 0, value: QContactManager::NoError); |
1155 | QVERIFY(cm->saveContacts(&contacts, &errorMap)); |
1156 | QVERIFY(cm->error() == QContactManager::NoError); |
1157 | QVERIFY(errorMap.count() == 0); |
1158 | |
1159 | /* Make sure our contacts got updated too */ |
1160 | QVERIFY(contacts.count() == 3); |
1161 | QVERIFY(contacts.at(0).id() != QContactId()); |
1162 | QVERIFY(contacts.at(1).id() != QContactId()); |
1163 | QVERIFY(contacts.at(2).id() != QContactId()); |
1164 | |
1165 | QVERIFY(contacts.at(0).detail(QContactName::Type) == na); |
1166 | QVERIFY(contacts.at(1).detail(QContactName::Type) == nb); |
1167 | QVERIFY(contacts.at(2).detail(QContactName::Type) == nc); |
1168 | |
1169 | /* Retrieve again */ |
1170 | a = cm->contact(contactId: contacts.at(i: 0).id()); |
1171 | b = cm->contact(contactId: contacts.at(i: 1).id()); |
1172 | c = cm->contact(contactId: contacts.at(i: 2).id()); |
1173 | QVERIFY(contacts.at(0).detail(QContactName::Type) == na); |
1174 | QVERIFY(contacts.at(1).detail(QContactName::Type) == nb); |
1175 | QVERIFY(contacts.at(2).detail(QContactName::Type) == nc); |
1176 | |
1177 | /* Save again, with a null error map */ |
1178 | QVERIFY(cm->saveContacts(&contacts, NULL)); |
1179 | QVERIFY(cm->error() == QContactManager::NoError); |
1180 | |
1181 | /* Now make an update to them all */ |
1182 | QContactPhoneNumber number; |
1183 | number.setNumber("1234567" ); |
1184 | |
1185 | QVERIFY(contacts[0].saveDetail(&number)); |
1186 | number.setNumber("234567" ); |
1187 | QVERIFY(contacts[1].saveDetail(&number)); |
1188 | number.setNumber("34567" ); |
1189 | QVERIFY(contacts[2].saveDetail(&number)); |
1190 | |
1191 | QVERIFY(cm->saveContacts(&contacts, &errorMap)); |
1192 | QVERIFY(cm->error() == QContactManager::NoError); |
1193 | QVERIFY(errorMap.count() == 0); |
1194 | |
1195 | /* Retrieve them and check them again */ |
1196 | a = cm->contact(contactId: contacts.at(i: 0).id()); |
1197 | b = cm->contact(contactId: contacts.at(i: 1).id()); |
1198 | c = cm->contact(contactId: contacts.at(i: 2).id()); |
1199 | QVERIFY(contacts.at(0).detail(QContactName::Type) == na); |
1200 | QVERIFY(contacts.at(1).detail(QContactName::Type) == nb); |
1201 | QVERIFY(contacts.at(2).detail(QContactName::Type) == nc); |
1202 | |
1203 | QVERIFY(a.details<QContactPhoneNumber>().count() == 1); |
1204 | QVERIFY(b.details<QContactPhoneNumber>().count() == 1); |
1205 | QVERIFY(c.details<QContactPhoneNumber>().count() == 1); |
1206 | |
1207 | QVERIFY(a.details<QContactPhoneNumber>().at(0).number() == "1234567" ); |
1208 | QVERIFY(b.details<QContactPhoneNumber>().at(0).number() == "234567" ); |
1209 | QVERIFY(c.details<QContactPhoneNumber>().at(0).number() == "34567" ); |
1210 | |
1211 | /* Retrieve them with the batch ID fetch API */ |
1212 | QList<QContactId> batchIds; |
1213 | batchIds << a.id() << b.id() << c.id(); |
1214 | |
1215 | // Null error map first (doesn't crash) |
1216 | QList<QContact> batchFetch = cm->contacts(contactIds: batchIds, fetchHint: QContactFetchHint(), errorMap: 0); |
1217 | QVERIFY(cm->error() == QContactManager::NoError); |
1218 | QVERIFY(batchFetch.count() == 3); |
1219 | QVERIFY(batchFetch.at(0).detail(QContactName::Type) == na); |
1220 | QVERIFY(batchFetch.at(1).detail(QContactName::Type) == nb); |
1221 | QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nc); |
1222 | |
1223 | // With error map |
1224 | batchFetch = cm->contacts(contactIds: batchIds, fetchHint: QContactFetchHint(), errorMap: &errorMap); |
1225 | QVERIFY(cm->error() == QContactManager::NoError); |
1226 | QVERIFY(errorMap.count() == 0); |
1227 | QVERIFY(batchFetch.count() == 3); |
1228 | QVERIFY(batchFetch.at(0).detail(QContactName::Type) == na); |
1229 | QVERIFY(batchFetch.at(1).detail(QContactName::Type) == nb); |
1230 | QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nc); |
1231 | |
1232 | /* Now an empty id */ |
1233 | batchIds.clear(); |
1234 | batchIds << QContactId() << a.id() << b.id() << c.id(); |
1235 | batchFetch = cm->contacts(contactIds: batchIds, fetchHint: QContactFetchHint(), errorMap: 0); |
1236 | QVERIFY(cm->error() != QContactManager::NoError); |
1237 | QVERIFY(batchFetch.count() == 4); |
1238 | QVERIFY(batchFetch.at(0).detail(QContactName::Type) == QContactDetail()); |
1239 | QVERIFY(batchFetch.at(1).detail(QContactName::Type) == na); |
1240 | QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nb); |
1241 | QVERIFY(batchFetch.at(3).detail(QContactName::Type) == nc); |
1242 | |
1243 | batchFetch = cm->contacts(contactIds: batchIds, fetchHint: QContactFetchHint(), errorMap: &errorMap); |
1244 | QVERIFY(cm->error() != QContactManager::NoError); |
1245 | QVERIFY(batchFetch.count() == 4); |
1246 | QVERIFY(errorMap.count() == 1); |
1247 | QVERIFY(errorMap[0] == QContactManager::DoesNotExistError); |
1248 | QVERIFY(batchFetch.at(0).detail(QContactName::Type) == QContactDetail()); |
1249 | QVERIFY(batchFetch.at(1).detail(QContactName::Type) == na); |
1250 | QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nb); |
1251 | QVERIFY(batchFetch.at(3).detail(QContactName::Type) == nc); |
1252 | |
1253 | /* Now multiple of the same contact */ |
1254 | batchIds.clear(); |
1255 | batchIds << c.id() << b.id() << c.id() << a.id() << a.id(); |
1256 | batchFetch = cm->contacts(contactIds: batchIds, fetchHint: QContactFetchHint(), errorMap: &errorMap); |
1257 | QVERIFY(cm->error() == QContactManager::NoError); |
1258 | QVERIFY(batchFetch.count() == 5); |
1259 | QVERIFY(errorMap.count() == 0); |
1260 | QVERIFY(batchFetch.at(0).detail(QContactName::Type) == nc); |
1261 | QVERIFY(batchFetch.at(1).detail(QContactName::Type) == nb); |
1262 | QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nc); |
1263 | QVERIFY(batchFetch.at(3).detail(QContactName::Type) == na); |
1264 | QVERIFY(batchFetch.at(4).detail(QContactName::Type) == na); |
1265 | |
1266 | /* Now delete them all */ |
1267 | QList<QContactId> ids; |
1268 | ids << a.id() << b.id() << c.id(); |
1269 | QVERIFY(cm->removeContacts(ids, &errorMap)); |
1270 | QVERIFY(errorMap.count() == 0); |
1271 | QVERIFY(cm->error() == QContactManager::NoError); |
1272 | |
1273 | /* Make sure the contacts really don't exist any more */ |
1274 | QVERIFY(cm->contact(a.id()).id() == QContactId()); |
1275 | QVERIFY(cm->contact(a.id()).isEmpty()); |
1276 | QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
1277 | QVERIFY(cm->contact(b.id()).id() == QContactId()); |
1278 | QVERIFY(cm->contact(b.id()).isEmpty()); |
1279 | QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
1280 | QVERIFY(cm->contact(c.id()).id() == QContactId()); |
1281 | QVERIFY(cm->contact(c.id()).isEmpty()); |
1282 | QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
1283 | |
1284 | /* Now try removing with all invalid ids (e.g. the ones we just removed) */ |
1285 | ids.clear(); |
1286 | ids << a.id() << b.id() << c.id(); |
1287 | QVERIFY(!cm->removeContacts(ids, &errorMap)); |
1288 | QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
1289 | QVERIFY(errorMap.count() == 3); |
1290 | QVERIFY(errorMap.values().at(0) == QContactManager::DoesNotExistError); |
1291 | QVERIFY(errorMap.values().at(1) == QContactManager::DoesNotExistError); |
1292 | QVERIFY(errorMap.values().at(2) == QContactManager::DoesNotExistError); |
1293 | |
1294 | /* And again with a null error map */ |
1295 | QVERIFY(!cm->removeContacts(ids, NULL)); |
1296 | QVERIFY(cm->error() == QContactManager::DoesNotExistError); |
1297 | |
1298 | /* Try adding some new ones again, this time one with an error */ |
1299 | contacts.clear(); |
1300 | a.setId(QContactId()); |
1301 | b.setId(QContactId()); |
1302 | c.setId(QContactId()); |
1303 | |
1304 | /* Make B the bad guy */ |
1305 | QContactDetail bad(static_cast<QContactDetail::DetailType>(123456));//does not exist and will break if you add it |
1306 | bad.setValue(field: 12345, value: "Very bad" ); |
1307 | b.saveDetail(detail: &bad); |
1308 | |
1309 | contacts << a << b << c; |
1310 | |
1311 | /* Fix up B and re save it */ |
1312 | QVERIFY(contacts[1].removeDetail(&bad)); |
1313 | QVERIFY(cm->saveContacts(&contacts, &errorMap)); |
1314 | QVERIFY(errorMap.count() == 0); |
1315 | QVERIFY(cm->error() == QContactManager::NoError); |
1316 | |
1317 | // Save and remove a fourth contact. Store the id. |
1318 | a.setId(QContactId()); |
1319 | QVERIFY(cm->saveContact(&a)); |
1320 | QContactId removedId = a.id(); |
1321 | QVERIFY(cm->removeContact(removedId)); |
1322 | |
1323 | /* Now delete 3 items, but with one bad argument */ |
1324 | ids.clear(); |
1325 | ids << contacts.at(i: 0).id(); |
1326 | ids << removedId; |
1327 | ids << contacts.at(i: 2).id(); |
1328 | |
1329 | QVERIFY(!cm->removeContacts(ids, &errorMap)); |
1330 | QVERIFY(cm->error() != QContactManager::NoError); |
1331 | |
1332 | /* Again, the backend has the choice of either removing the successful ones, or not */ |
1333 | QVERIFY(errorMap.count() > 0); |
1334 | QVERIFY(errorMap.count() <= 3); |
1335 | |
1336 | // A might have gone through |
1337 | if (errorMap.keys().contains(t: 0)) { |
1338 | QVERIFY(errorMap.value(0) != QContactManager::NoError); |
1339 | QVERIFY(contacts.at(0).id() == QContactId()); |
1340 | } else { |
1341 | QVERIFY(contacts.at(0).id() != QContactId()); |
1342 | } |
1343 | |
1344 | /* B should definitely have failed */ |
1345 | QVERIFY(errorMap.value(1) == QContactManager::DoesNotExistError); |
1346 | QVERIFY(ids.at(1) == removedId); |
1347 | |
1348 | // A might have gone through |
1349 | if (errorMap.keys().contains(t: 2)) { |
1350 | QVERIFY(errorMap.value(2) != QContactManager::NoError); |
1351 | QVERIFY(contacts.at(2).id() == QContactId()); |
1352 | } else { |
1353 | QVERIFY(contacts.at(2).id() != QContactId()); |
1354 | } |
1355 | } |
1356 | |
1357 | void tst_QContactManager::invalidManager() |
1358 | { |
1359 | /* Create an invalid manager */ |
1360 | QContactManager manager("this should never work" ); |
1361 | QVERIFY(manager.managerName() == "invalid" ); |
1362 | QVERIFY(manager.managerVersion() == 0); |
1363 | |
1364 | /* also, test the other ctor behaviour is sane also */ |
1365 | QContactManager anotherManager("this should never work" , 15); |
1366 | QVERIFY(anotherManager.managerName() == "invalid" ); |
1367 | QVERIFY(anotherManager.managerVersion() == 0); |
1368 | |
1369 | /* Now test that all the operations fail */ |
1370 | QVERIFY(manager.contactIds().count() == 0); |
1371 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1372 | |
1373 | QContact foo; |
1374 | QContactName nf; |
1375 | nf.setLastName("Lastname" ); |
1376 | foo.saveDetail(detail: &nf); |
1377 | |
1378 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1379 | |
1380 | QVERIFY(manager.saveContact(&foo) == false); |
1381 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1382 | QVERIFY(foo.id() == QContactId()); |
1383 | QVERIFY(manager.contactIds().count() == 0); |
1384 | |
1385 | QVERIFY(manager.contact(foo.id()).id() == QContactId()); |
1386 | QVERIFY(manager.contact(foo.id()).isEmpty()); |
1387 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1388 | |
1389 | QVERIFY(manager.removeContact(foo.id()) == false); |
1390 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1391 | |
1392 | QMap<int, QContactManager::Error> errorMap; |
1393 | errorMap.insert(key: 0, value: QContactManager::NoError); |
1394 | QVERIFY(!manager.saveContacts(0, &errorMap)); |
1395 | QVERIFY(manager.errorMap().count() == 0); |
1396 | QVERIFY(errorMap.count() == 0); |
1397 | QVERIFY(manager.error() == QContactManager::BadArgumentError); |
1398 | |
1399 | /* filters */ |
1400 | QContactFilter f; // matches everything |
1401 | QContactDetailFilter df; |
1402 | df.setDetailType(type: QContactDisplayLabel::Type, field: QContactDisplayLabel::FieldLabel); |
1403 | QVERIFY(manager.contactIds(QContactFilter()).count() == 0); |
1404 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1405 | QVERIFY(manager.contactIds(df).count() == 0); |
1406 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1407 | QVERIFY(manager.contactIds(f | f).count() == 0); |
1408 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1409 | QVERIFY(manager.contactIds(df | df).count() == 0); |
1410 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1411 | |
1412 | QVERIFY(manager.isFilterSupported(f) == false); |
1413 | QVERIFY(manager.isFilterSupported(df) == false); |
1414 | |
1415 | QList<QContact> list; |
1416 | list << foo; |
1417 | |
1418 | QVERIFY(!manager.saveContacts(&list, &errorMap)); |
1419 | QVERIFY(errorMap.count() == 0); |
1420 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1421 | |
1422 | QVERIFY(!manager.removeContacts(QList<QContactId>(), &errorMap)); |
1423 | QVERIFY(errorMap.count() == 0); |
1424 | QVERIFY(manager.error() == QContactManager::BadArgumentError); |
1425 | |
1426 | QList<QContactId> idlist; |
1427 | idlist << foo.id(); |
1428 | QVERIFY(!manager.removeContacts(idlist, &errorMap)); |
1429 | QVERIFY(errorMap.count() == 0); |
1430 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1431 | |
1432 | /* Self contact id */ |
1433 | QVERIFY(!manager.setSelfContactId(QContactId())); |
1434 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1435 | QVERIFY(manager.selfContactId() == QContactId()); |
1436 | QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::DoesNotExistError); |
1437 | |
1438 | /* Relationships */ |
1439 | QContact one, two; |
1440 | QContactRelationship invalidRel; |
1441 | invalidRel.setFirst(one.id()); |
1442 | invalidRel.setSecond(two.id()); |
1443 | QList<QContactRelationship> invalidRelList; |
1444 | invalidRelList << invalidRel; |
1445 | QVERIFY(!manager.saveRelationship(&invalidRel)); |
1446 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1447 | QVERIFY(manager.relationships().isEmpty()); |
1448 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1449 | manager.saveRelationships(relationships: &invalidRelList, NULL); |
1450 | QVERIFY(manager.error() == QContactManager::NotSupportedError); |
1451 | manager.removeRelationships(relationships: invalidRelList, NULL); |
1452 | QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::DoesNotExistError); |
1453 | |
1454 | /* Capabilities */ |
1455 | QVERIFY(manager.supportedDataTypes().count() == 0); |
1456 | } |
1457 | |
1458 | void tst_QContactManager::memoryManager() |
1459 | { |
1460 | QMap<QString, QString> params; |
1461 | QContactManager m1("memory" ); |
1462 | params.insert(key: "random" , value: "shouldNotBeUsed" ); |
1463 | QContactManager m2("memory" , params); |
1464 | params.insert(key: "id" , value: "shouldBeUsed" ); |
1465 | QContactManager m3("memory" , params); |
1466 | QContactManager m4("memory" , params); |
1467 | params.insert(key: "id" , value: QString("" )); |
1468 | QContactManager m5("memory" , params); // should be another anonymous |
1469 | |
1470 | // add a contact to each of m1, m2, m3 |
1471 | QContact c; |
1472 | QContactName nc; |
1473 | nc.setFirstName("John" ); |
1474 | nc.setLastName("Civilian" ); |
1475 | c.saveDetail(detail: &nc); |
1476 | m1.saveContact(contact: &c); |
1477 | |
1478 | // reset ids |
1479 | c.setId(QContactId()); |
1480 | c.setCollectionId(QContactCollectionId()); |
1481 | |
1482 | QContact c2; |
1483 | QContactName nc2 = c2.detail(type: QContactName::Type); |
1484 | c2 = c; |
1485 | nc2.setMiddleName("Public" ); |
1486 | c2.saveDetail(detail: &nc2); |
1487 | |
1488 | m2.saveContact(contact: &c2); // save c2 first; c will be given a higher id |
1489 | m2.saveContact(contact: &c); // save c to m2 |
1490 | |
1491 | // reset ids |
1492 | c.setId(QContactId()); |
1493 | c.setCollectionId(QContactCollectionId()); |
1494 | nc.setSuffix("MD" ); |
1495 | c.saveDetail(detail: &nc); |
1496 | m3.saveContact(contact: &c); |
1497 | |
1498 | /* test that m1 != m2 != m3 and that m3 == m4 */ |
1499 | |
1500 | // check the counts are correct - especially note m4 and m3. |
1501 | QCOMPARE(m1.contactIds().count(), 1); |
1502 | QCOMPARE(m2.contactIds().count(), 2); |
1503 | QCOMPARE(m3.contactIds().count(), 1); |
1504 | QCOMPARE(m4.contactIds().count(), 1); |
1505 | QCOMPARE(m5.contactIds().count(), 0); |
1506 | |
1507 | // remove c2 from m2 - ensure that this doesn't affect any other manager. |
1508 | m2.removeContact(contactId: c2.id()); |
1509 | QCOMPARE(m1.contactIds().count(), 1); |
1510 | QCOMPARE(m2.contactIds().count(), 1); |
1511 | QCOMPARE(m3.contactIds().count(), 1); |
1512 | QCOMPARE(m4.contactIds().count(), 1); |
1513 | QCOMPARE(m5.contactIds().count(), 0); |
1514 | |
1515 | // check that the contacts contained within are different. |
1516 | // note that in the m1->m2 case, only the id will be different! |
1517 | QVERIFY(m1.contact(m1.contactIds().at(0)) != m2.contact(m2.contactIds().at(0))); |
1518 | QVERIFY(m1.contact(m1.contactIds().at(0)) != m3.contact(m3.contactIds().at(0))); |
1519 | QVERIFY(m2.contact(m2.contactIds().at(0)) != m3.contact(m3.contactIds().at(0))); |
1520 | QVERIFY(m3.contact(m3.contactIds().at(0)) == m4.contact(m4.contactIds().at(0))); |
1521 | |
1522 | // now, we should be able to remove from m4, and have m3 empty |
1523 | QVERIFY(m4.removeContact(c.id())); |
1524 | QCOMPARE(m3.contactIds().count(), 0); |
1525 | QCOMPARE(m4.contactIds().count(), 0); |
1526 | QCOMPARE(m5.contactIds().count(), 0); |
1527 | } |
1528 | |
1529 | void tst_QContactManager::overrideManager() |
1530 | { |
1531 | QString defaultStore = QContactManager::availableManagers().value(i: 0); |
1532 | |
1533 | // preserve existing environment override |
1534 | QString overrideManager = qgetenv(varName: "QTCONTACTS_MANAGER_OVERRIDE" ); |
1535 | |
1536 | // override with specific managers |
1537 | qputenv(varName: "QTCONTACTS_MANAGER_OVERRIDE" , value: "memory" ); |
1538 | QContactManager m1; |
1539 | QCOMPARE(m1.managerName(), QString::fromLatin1("memory" )); |
1540 | |
1541 | qputenv(varName: "QTCONTACTS_MANAGER_OVERRIDE" , value: "invalid" ); |
1542 | QContactManager m2; |
1543 | QCOMPARE(m2.managerName(), QString::fromLatin1("invalid" )); |
1544 | |
1545 | qputenv(varName: "QTCONTACTS_MANAGER_OVERRIDE" , value: "" ); |
1546 | QContactManager m3; |
1547 | QCOMPARE(m3.managerName(), defaultStore); |
1548 | |
1549 | qputenv(varName: "QTCONTACTS_MANAGER_OVERRIDE" , value: overrideManager.toLatin1()); |
1550 | } |
1551 | |
1552 | void tst_QContactManager::nameSynthesis_data() |
1553 | { |
1554 | QTest::addColumn<QString>(name: "expected" ); |
1555 | |
1556 | QTest::addColumn<bool>(name: "addname" ); |
1557 | QTest::addColumn<QString>(name: "prefix" ); |
1558 | QTest::addColumn<QString>(name: "first" ); |
1559 | QTest::addColumn<QString>(name: "middle" ); |
1560 | QTest::addColumn<QString>(name: "last" ); |
1561 | QTest::addColumn<QString>(name: "suffix" ); |
1562 | |
1563 | QTest::addColumn<bool>(name: "addcompany" ); |
1564 | QTest::addColumn<QString>(name: "company" ); |
1565 | |
1566 | QTest::addColumn<bool>(name: "addname2" ); |
1567 | QTest::addColumn<QString>(name: "secondprefix" ); |
1568 | QTest::addColumn<QString>(name: "secondfirst" ); |
1569 | QTest::addColumn<QString>(name: "secondmiddle" ); |
1570 | QTest::addColumn<QString>(name: "secondlast" ); |
1571 | QTest::addColumn<QString>(name: "secondsuffix" ); |
1572 | |
1573 | QTest::addColumn<bool>(name: "addcompany2" ); |
1574 | QTest::addColumn<QString>(name: "secondcompany" ); |
1575 | |
1576 | QString e; // empty string.. gets a work out |
1577 | |
1578 | /* Various empty ones */ |
1579 | QTest::newRow(dataTag: "empty contact" ) << e |
1580 | << false << e << e << e << e << e |
1581 | << false << e |
1582 | << false << e << e << e << e << e |
1583 | << false << e; |
1584 | QTest::newRow(dataTag: "empty name" ) << e |
1585 | << true << e << e << e << e << e |
1586 | << false << e |
1587 | << false << e << e << e << e << e |
1588 | << false << e; |
1589 | QTest::newRow(dataTag: "empty names" ) << e |
1590 | << true << e << e << e << e << e |
1591 | << false << e |
1592 | << true << e << e << e << e << e |
1593 | << false << e; |
1594 | QTest::newRow(dataTag: "empty org" ) << e |
1595 | << false << e << e << e << e << e |
1596 | << true << e |
1597 | << false << e << e << e << e << e |
1598 | << true << e; |
1599 | QTest::newRow(dataTag: "empty orgs" ) << e |
1600 | << false << e << e << e << e << e |
1601 | << true << e |
1602 | << false << e << e << e << e << e |
1603 | << true << e; |
1604 | QTest::newRow(dataTag: "empty orgs and names" ) << e |
1605 | << true << e << e << e << e << e |
1606 | << true << e |
1607 | << true << e << e << e << e << e |
1608 | << true << e; |
1609 | |
1610 | /* Single values */ |
1611 | QTest::newRow(dataTag: "prefix" ) << "Prefix" |
1612 | << true << "Prefix" << e << e << e << e |
1613 | << false << e |
1614 | << false << e << e << e << e << e |
1615 | << false << e; |
1616 | QTest::newRow(dataTag: "first" ) << "First" |
1617 | << true << e << "First" << e << e << e |
1618 | << false << e |
1619 | << false << e << e << e << e << e |
1620 | << false << e; |
1621 | QTest::newRow(dataTag: "middle" ) << "Middle" |
1622 | << true << e << e << "Middle" << e << e |
1623 | << false << e |
1624 | << false << e << e << e << e << e |
1625 | << false << e; |
1626 | QTest::newRow(dataTag: "last" ) << "Last" |
1627 | << true << e << e << e << "Last" << e |
1628 | << false << e |
1629 | << false << e << e << e << e << e |
1630 | << false << e; |
1631 | QTest::newRow(dataTag: "suffix" ) << "Suffix" |
1632 | << true << e << e << e << e << "Suffix" |
1633 | << false << e |
1634 | << false << e << e << e << e << e |
1635 | << false << e; |
1636 | |
1637 | /* Single values in the second name */ |
1638 | QTest::newRow(dataTag: "prefix in second" ) << "Prefix" |
1639 | << false << "Prefix" << e << e << e << e |
1640 | << false << e |
1641 | << true << "Prefix" << e << e << e << e |
1642 | << false << e; |
1643 | QTest::newRow(dataTag: "first in second" ) << "First" |
1644 | << false << e << "First" << e << e << e |
1645 | << false << e |
1646 | << true << e << "First" << e << e << e |
1647 | << false << e; |
1648 | QTest::newRow(dataTag: "middle in second" ) << "Middle" |
1649 | << false << e << e << "Middle" << e << e |
1650 | << false << e |
1651 | << true << e << e << "Middle" << e << e |
1652 | << false << e; |
1653 | QTest::newRow(dataTag: "last in second" ) << "Last" |
1654 | << false << e << e << e << "Last" << e |
1655 | << false << e |
1656 | << true << e << e << e << "Last" << e |
1657 | << false << e; |
1658 | QTest::newRow(dataTag: "suffix in second" ) << "Suffix" |
1659 | << false << e << e << e << e << "Suffix" |
1660 | << false << e |
1661 | << true << e << e << e << e << "Suffix" |
1662 | << false << e; |
1663 | |
1664 | /* Multiple name values */ |
1665 | QTest::newRow(dataTag: "prefix first" ) << "Prefix First" |
1666 | << true << "Prefix" << "First" << e << e << e |
1667 | << false << e |
1668 | << false << e << e << e << e << e |
1669 | << false << e; |
1670 | QTest::newRow(dataTag: "prefix middle" ) << "Prefix Middle" |
1671 | << true << "Prefix" << e << "Middle" << e << e |
1672 | << false << e |
1673 | << false << e << e << e << e << e |
1674 | << false << e; |
1675 | QTest::newRow(dataTag: "prefix last" ) << "Prefix Last" |
1676 | << true << "Prefix" << e << e << "Last" << e |
1677 | << false << e |
1678 | << false << e << e << e << e << e |
1679 | << false << e; |
1680 | QTest::newRow(dataTag: "prefix suffix" ) << "Prefix Suffix" |
1681 | << true << "Prefix" << e << e << e << "Suffix" |
1682 | << false << e |
1683 | << false << e << e << e << e << e |
1684 | << false << e; |
1685 | QTest::newRow(dataTag: "first middle" ) << "First Middle" |
1686 | << true << e << "First" << "Middle" << e << e |
1687 | << false << e |
1688 | << false << e << e << e << e << e |
1689 | << false << e; |
1690 | QTest::newRow(dataTag: "first last" ) << "First Last" |
1691 | << true << e << "First" << e << "Last" << e |
1692 | << false << e |
1693 | << false << e << e << e << e << e |
1694 | << false << e; |
1695 | QTest::newRow(dataTag: "first suffix" ) << "First Suffix" |
1696 | << true << e << "First" << e << e << "Suffix" |
1697 | << false << e |
1698 | << false << e << e << e << e << e |
1699 | << false << e; |
1700 | QTest::newRow(dataTag: "middle last" ) << "Middle Last" |
1701 | << true << e << e << "Middle" << "Last" << e |
1702 | << false << e |
1703 | << false << e << e << e << e << e |
1704 | << false << e; |
1705 | QTest::newRow(dataTag: "middle suffix" ) << "Middle Suffix" |
1706 | << true << e << e << "Middle" << e << "Suffix" |
1707 | << false << e |
1708 | << false << e << e << e << e << e |
1709 | << false << e; |
1710 | QTest::newRow(dataTag: "last suffix" ) << "Last Suffix" |
1711 | << true << e << e << e << "Last" << "Suffix" |
1712 | << false << e |
1713 | << false << e << e << e << e << e |
1714 | << false << e; |
1715 | |
1716 | /* Everything.. */ |
1717 | QTest::newRow(dataTag: "all name" ) << "Prefix First Middle Last Suffix" |
1718 | << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
1719 | << false << e |
1720 | << false << e << e << e << e << e |
1721 | << false << e; |
1722 | QTest::newRow(dataTag: "all name second" ) << "Prefix First Middle Last Suffix" |
1723 | << false << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
1724 | << false << e |
1725 | << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
1726 | << false << e; |
1727 | |
1728 | /* Org */ |
1729 | QTest::newRow(dataTag: "org" ) << "Company" |
1730 | << false << e << e << e << e << e |
1731 | << true << "Company" |
1732 | << false << e << e << e << e << e |
1733 | << false << e; |
1734 | QTest::newRow(dataTag: "second org" ) << "Company" |
1735 | << false << e << e << e << e << e |
1736 | << false << e |
1737 | << false << e << e << e << e << e |
1738 | << true << "Company" ; |
1739 | |
1740 | /* Mix */ |
1741 | QTest::newRow(dataTag: "org and empty name" ) << "Company" |
1742 | << true << e << e << e << e << e |
1743 | << true << "Company" |
1744 | << false << e << e << e << e << e |
1745 | << false << e; |
1746 | |
1747 | QTest::newRow(dataTag: "name and empty org" ) << "Prefix First Middle Last Suffix" |
1748 | << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
1749 | << false << e |
1750 | << false << e << e << e << e << e |
1751 | << false << e; |
1752 | |
1753 | /* names are preferred to orgs */ |
1754 | QTest::newRow(dataTag: "name and org" ) << "Prefix First Middle Last Suffix" |
1755 | << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix" |
1756 | << true << "Company" |
1757 | << false << e << e << e << e << e |
1758 | << false << e; |
1759 | |
1760 | } |
1761 | |
1762 | void tst_QContactManager::nameSynthesis() |
1763 | { |
1764 | QContactManager cm("memory" ); |
1765 | |
1766 | QFETCH(QString, expected); |
1767 | |
1768 | QFETCH(QString, prefix); |
1769 | QFETCH(QString, first); |
1770 | QFETCH(QString, middle); |
1771 | QFETCH(QString, last); |
1772 | QFETCH(QString, suffix); |
1773 | QFETCH(QString, company); |
1774 | |
1775 | QFETCH(QString, secondprefix); |
1776 | QFETCH(QString, secondfirst); |
1777 | QFETCH(QString, secondmiddle); |
1778 | QFETCH(QString, secondlast); |
1779 | QFETCH(QString, secondsuffix); |
1780 | QFETCH(QString, secondcompany); |
1781 | |
1782 | QFETCH(bool, addname); |
1783 | QFETCH(bool, addname2); |
1784 | QFETCH(bool, addcompany); |
1785 | QFETCH(bool, addcompany2); |
1786 | |
1787 | /* Test the default name synthesis code */ |
1788 | QContact c; |
1789 | |
1790 | QContactName name, name2; |
1791 | QContactOrganization org, org2; |
1792 | |
1793 | name.setPrefix(prefix); |
1794 | name.setFirstName(first); |
1795 | name.setMiddleName(middle); |
1796 | name.setLastName(last); |
1797 | name.setSuffix(suffix); |
1798 | |
1799 | name2.setPrefix(secondprefix); |
1800 | name2.setFirstName(secondfirst); |
1801 | name2.setMiddleName(secondmiddle); |
1802 | name2.setLastName(secondlast); |
1803 | name2.setSuffix(secondsuffix); |
1804 | |
1805 | org.setName(company); |
1806 | org2.setName(secondcompany); |
1807 | |
1808 | if (addname) |
1809 | c.saveDetail(detail: &name); |
1810 | if (addname2) |
1811 | c.saveDetail(detail: &name2); |
1812 | if (addcompany) |
1813 | c.saveDetail(detail: &org); |
1814 | if (addcompany2) |
1815 | c.saveDetail(detail: &org2); |
1816 | } |
1817 | |
1818 | void tst_QContactManager::observerDeletion() |
1819 | { |
1820 | QContactManager *manager = new QContactManager("memory" ); |
1821 | QContact c; |
1822 | QVERIFY(manager->saveContact(&c)); |
1823 | QContactId id = c.id(); |
1824 | QContactObserver *observer = new QContactObserver(manager, id); |
1825 | Q_UNUSED(observer) |
1826 | delete manager; |
1827 | delete observer; |
1828 | // Test for bug MOBILITY-2566 - that QContactObserver doesn't crash when it is |
1829 | // destroyed after the associated QContactManager |
1830 | } |
1831 | |
1832 | void tst_QContactManager::signalEmission() |
1833 | { |
1834 | QTest::qWait(ms: 500); // clear the signal queue |
1835 | QFETCH(QString, uri); |
1836 | QScopedPointer<QContactManager> m1(QContactManager::fromUri(uri)); |
1837 | |
1838 | qRegisterMetaType<QContactId>(typeName: "QContactId" ); |
1839 | qRegisterMetaType<QList<QContactId> >(typeName: "QList<QContactId>" ); |
1840 | qRegisterMetaType<QList<QContactDetail::DetailType> >(typeName: "QList<QContactDetail::DetailType>" ); |
1841 | |
1842 | QSignalSpy spyCA(m1.data(), SIGNAL(contactsAdded(QList<QContactId>))); |
1843 | QSignalSpy spyCM(m1.data(), SIGNAL(contactsChanged(QList<QContactId>, QList<QContactDetail::DetailType>))); |
1844 | QSignalSpy spyCR(m1.data(), SIGNAL(contactsRemoved(QList<QContactId>))); |
1845 | |
1846 | QTestSignalSink casink(m1.data(), SIGNAL(contactsAdded(QList<QContactId>))); |
1847 | QTestSignalSink cmsink(m1.data(), SIGNAL(contactsChanged(QList<QContactId>, QList<QContactDetail::DetailType>))); |
1848 | QTestSignalSink crsink(m1.data(), SIGNAL(contactsRemoved(QList<QContactId>))); |
1849 | |
1850 | |
1851 | QList<QVariant> args; |
1852 | QList<QContactId> arg; |
1853 | QList<QContactCollectionId> collectionIdList; |
1854 | QContact c; |
1855 | QList<QContact> batchAdd; |
1856 | QList<QContactId> batchRemove; |
1857 | int addSigCount = 0; // the expected signal counts. |
1858 | int modSigCount = 0; |
1859 | int remSigCount = 0; |
1860 | |
1861 | // verify add emits signal added |
1862 | QContactName nc; |
1863 | saveContactName(contact: &c, contactName: &nc, name: "John" ); |
1864 | QVERIFY(m1->saveContact(&c)); |
1865 | QContactId cid = c.id(); |
1866 | addSigCount += 1; |
1867 | QTRY_COMPARE(spyCA.count(), addSigCount); |
1868 | args = spyCA.takeFirst(); |
1869 | addSigCount -= 1; |
1870 | arg = args.first().value<QList<QContactId> >(); |
1871 | QVERIFY(arg.count() == 1); |
1872 | QCOMPARE(QContactId(arg.at(0)), cid); |
1873 | |
1874 | QScopedPointer<QContactObserver> c1Observer(new QContactObserver(m1.data(), cid)); |
1875 | QScopedPointer<QSignalSpy> spyCOM1(new QSignalSpy(c1Observer.data(), SIGNAL(contactChanged(QList<QContactDetail::DetailType>)))); |
1876 | QScopedPointer<QSignalSpy> spyCOR1(new QSignalSpy(c1Observer.data(), SIGNAL(contactRemoved()))); |
1877 | |
1878 | // verify save modified emits signal changed |
1879 | saveContactName(contact: &c, contactName: &nc, name: "Citizen" ); |
1880 | QVERIFY(m1->saveContact(&c)); |
1881 | modSigCount += 1; |
1882 | QTRY_COMPARE(spyCM.count(), modSigCount); |
1883 | QTRY_COMPARE(spyCOM1->count(), 1); |
1884 | args = spyCM.takeFirst(); |
1885 | modSigCount -= 1; |
1886 | QCOMPARE(args.count(), 2); |
1887 | arg = args.at(i: 0).value<QList<QContactId> >(); |
1888 | QVERIFY(arg.count() == 1); |
1889 | QCOMPARE(QContactId(arg.at(0)), cid); |
1890 | QCOMPARE(args.at(1).userType(), qMetaTypeId<QList<QContactDetail::DetailType> >()); |
1891 | args = spyCOM1->takeFirst(); |
1892 | QCOMPARE(args.count(), 1); |
1893 | QCOMPARE(args.at(0).userType(), qMetaTypeId<QList<QContactDetail::DetailType> >()); |
1894 | |
1895 | // verify remove emits signal removed |
1896 | m1->removeContact(contactId: c.id()); |
1897 | remSigCount += 1; |
1898 | QTRY_COMPARE(spyCR.count(), remSigCount); |
1899 | QTRY_COMPARE(spyCOR1->count(), 1); |
1900 | args = spyCR.takeFirst(); |
1901 | remSigCount -= 1; |
1902 | arg = args.first().value<QList<QContactId> >(); |
1903 | QVERIFY(arg.count() == 1); |
1904 | QCOMPARE(QContactId(arg.at(0)), cid); |
1905 | |
1906 | // verify multiple adds works as advertised |
1907 | QContact c2, c3; |
1908 | QContactName nc2, nc3; |
1909 | saveContactName(contact: &c2, contactName: &nc2, name: "Mark" ); |
1910 | saveContactName(contact: &c3, contactName: &nc3, name: "Garry" ); |
1911 | QVERIFY(m1->saveContact(&c2)); |
1912 | QVERIFY(m1->saveContact(&c3)); |
1913 | QTRY_COMPARE(spyCM.count(), modSigCount); |
1914 | QTRY_VERIFY(spyCA.count() > addSigCount); |
1915 | addSigCount = spyCA.count(); |
1916 | |
1917 | spyCOM1->clear(); |
1918 | spyCOR1->clear(); |
1919 | QScopedPointer<QContactObserver> c2Observer(new QContactObserver(m1.data(), c2.id())); |
1920 | QScopedPointer<QContactObserver> c3Observer(new QContactObserver(m1.data(), c3.id())); |
1921 | QScopedPointer<QSignalSpy> spyCOM2(new QSignalSpy(c2Observer.data(), SIGNAL(contactChanged(QList<QContactDetail::DetailType>)))); |
1922 | QScopedPointer<QSignalSpy> spyCOM3(new QSignalSpy(c3Observer.data(), SIGNAL(contactChanged(QList<QContactDetail::DetailType>)))); |
1923 | QScopedPointer<QSignalSpy> spyCOR2(new QSignalSpy(c2Observer.data(), SIGNAL(contactRemoved()))); |
1924 | QScopedPointer<QSignalSpy> spyCOR3(new QSignalSpy(c3Observer.data(), SIGNAL(contactRemoved()))); |
1925 | |
1926 | // verify multiple modifies works as advertised |
1927 | saveContactName(contact: &c2, contactName: &nc2, name: "M." ); |
1928 | QVERIFY(m1->saveContact(&c2)); |
1929 | saveContactName(contact: &c2, contactName: &nc2, name: "Mark" ); |
1930 | saveContactName(contact: &c3, contactName: &nc3, name: "G." ); |
1931 | QVERIFY(m1->saveContact(&c2)); |
1932 | QVERIFY(m1->saveContact(&c3)); |
1933 | QTRY_VERIFY(spyCM.count() > modSigCount); |
1934 | modSigCount = spyCM.count(); |
1935 | QTRY_VERIFY(spyCOM2->count() > 0); |
1936 | QTRY_VERIFY(spyCOM3->count() > 0); |
1937 | QCOMPARE(spyCOM1->count(), 0); |
1938 | |
1939 | // verify multiple removes works as advertised |
1940 | m1->removeContact(contactId: c3.id()); |
1941 | remSigCount += 1; |
1942 | m1->removeContact(contactId: c2.id()); |
1943 | remSigCount += 1; |
1944 | QTRY_VERIFY(spyCOR2->count() > 0); |
1945 | QTRY_VERIFY(spyCOR3->count() > 0); |
1946 | QCOMPARE(spyCOR1->count(), 0); |
1947 | |
1948 | /* Now test the batch equivalents */ |
1949 | spyCA.clear(); |
1950 | spyCM.clear(); |
1951 | spyCR.clear(); |
1952 | |
1953 | /* Batch adds - set ids to zero so add succeeds. */ |
1954 | c.setId(QContactId()); |
1955 | c2.setId(QContactId()); |
1956 | c3.setId(QContactId()); |
1957 | batchAdd << c << c2 << c3; |
1958 | QMap<int, QContactManager::Error> errorMap; |
1959 | QVERIFY(m1->saveContacts(&batchAdd, &errorMap)); |
1960 | |
1961 | QVERIFY(batchAdd.count() == 3); |
1962 | c = batchAdd.at(i: 0); |
1963 | c2 = batchAdd.at(i: 1); |
1964 | c3 = batchAdd.at(i: 2); |
1965 | |
1966 | // We want to see one contactsAdded signal listing id's for all three contacts. |
1967 | QTRY_COMPARE(spyCA.count(), 1); |
1968 | { |
1969 | QList<QContactId> sigids = spyCA.takeFirst().at(i: 0).value<QList<QContactId> >(); |
1970 | QVERIFY(sigids.contains(c.id())); |
1971 | QVERIFY(sigids.contains(c2.id())); |
1972 | QVERIFY(sigids.contains(c3.id())); |
1973 | } |
1974 | |
1975 | QTRY_COMPARE(spyCM.count(), 0); |
1976 | |
1977 | c1Observer.reset(other: new QContactObserver(m1.data(), c.id())); |
1978 | c2Observer.reset(other: new QContactObserver(m1.data(), c2.id())); |
1979 | c3Observer.reset(other: new QContactObserver(m1.data(), c3.id())); |
1980 | spyCOM1.reset(other: new QSignalSpy(c1Observer.data(), SIGNAL(contactChanged(QList<QContactDetail::DetailType>)))); |
1981 | spyCOM2.reset(other: new QSignalSpy(c2Observer.data(), SIGNAL(contactChanged(QList<QContactDetail::DetailType>)))); |
1982 | spyCOM3.reset(other: new QSignalSpy(c3Observer.data(), SIGNAL(contactChanged(QList<QContactDetail::DetailType>)))); |
1983 | spyCOR1.reset(other: new QSignalSpy(c1Observer.data(), SIGNAL(contactRemoved()))); |
1984 | spyCOR2.reset(other: new QSignalSpy(c2Observer.data(), SIGNAL(contactRemoved()))); |
1985 | spyCOR3.reset(other: new QSignalSpy(c3Observer.data(), SIGNAL(contactRemoved()))); |
1986 | QTRY_COMPARE(spyCR.count(), 0); |
1987 | |
1988 | /* Batch modifies */ |
1989 | QContactName modifiedName = c.detail(type: QContactName::Type); |
1990 | saveContactName(contact: &c, contactName: &modifiedName, name: "Modified number 1" ); |
1991 | modifiedName = c2.detail(type: QContactName::Type); |
1992 | saveContactName(contact: &c2, contactName: &modifiedName, name: "Modified number 2" ); |
1993 | modifiedName = c3.detail(type: QContactName::Type); |
1994 | saveContactName(contact: &c3, contactName: &modifiedName, name: "Modified number 3" ); |
1995 | |
1996 | batchAdd.clear(); |
1997 | batchAdd << c << c2 << c3; |
1998 | QVERIFY(m1->saveContacts(&batchAdd, &errorMap)); |
1999 | |
2000 | // We want to see one contactsChanged signal listing id's for all three contacts. |
2001 | QTRY_COMPARE(spyCM.count(), 1); |
2002 | { |
2003 | QList<QContactId> sigids = spyCM.takeFirst().at(i: 0).value<QList<QContactId> >(); |
2004 | QVERIFY(sigids.contains(c.id())); |
2005 | QVERIFY(sigids.contains(c2.id())); |
2006 | QVERIFY(sigids.contains(c3.id())); |
2007 | } |
2008 | QTRY_COMPARE(spyCOM1->count(), 1); |
2009 | QTRY_COMPARE(spyCOM2->count(), 1); |
2010 | QTRY_COMPARE(spyCOM3->count(), 1); |
2011 | |
2012 | /* Batch removes */ |
2013 | batchRemove << c.id() << c2.id() << c3.id(); |
2014 | QVERIFY(m1->removeContacts(batchRemove, &errorMap)); |
2015 | |
2016 | // We want to see one contactsRemoved signal listing id's for all three contacts. |
2017 | QTRY_COMPARE(spyCR.count(), 1); |
2018 | { |
2019 | QList<QContactId> sigids = spyCR.takeFirst().at(i: 0).value<QList<QContactId> >(); |
2020 | QVERIFY(sigids.contains(c.id())); |
2021 | QVERIFY(sigids.contains(c2.id())); |
2022 | QVERIFY(sigids.contains(c3.id())); |
2023 | } |
2024 | QTRY_COMPARE(spyCOR1->count(), 1); |
2025 | QTRY_COMPARE(spyCOR2->count(), 1); |
2026 | QTRY_COMPARE(spyCOR3->count(), 1); |
2027 | |
2028 | QTRY_COMPARE(spyCA.count(), 0); |
2029 | QTRY_COMPARE(spyCM.count(), 0); |
2030 | |
2031 | QScopedPointer<QContactManager> m2(QContactManager::fromUri(uri)); |
2032 | } |
2033 | |
2034 | void tst_QContactManager::errorStayingPut() |
2035 | { |
2036 | /* Make sure that when we clone a manager, we don't clone the error */ |
2037 | QMap<QString, QString> params; |
2038 | params.insert(key: "id" , value: "error isolation test" ); |
2039 | QContactManager m1("memory" ,params); |
2040 | |
2041 | QVERIFY(m1.error() == QContactManager::NoError); |
2042 | |
2043 | /* Remove an invalid contact to get an error */ |
2044 | QVERIFY(m1.removeContact(QContactId()) == false); |
2045 | QVERIFY(m1.error() == QContactManager::DoesNotExistError); |
2046 | |
2047 | /* Create a new manager with hopefully the same backend */ |
2048 | QContactManager m2("memory" , params); |
2049 | |
2050 | QVERIFY(m1.error() == QContactManager::DoesNotExistError); |
2051 | QVERIFY(m2.error() == QContactManager::NoError); |
2052 | |
2053 | /* Cause an error on the other ones and check the first is not affected */ |
2054 | m2.saveContacts(contacts: 0, errorMap: 0); |
2055 | QVERIFY(m1.error() == QContactManager::DoesNotExistError); |
2056 | QVERIFY(m2.error() == QContactManager::BadArgumentError); |
2057 | |
2058 | QContact c; |
2059 | int unknown = 12345; |
2060 | QContactDetail::DetailType unknownType = static_cast<QContactDetail::DetailType>(unknown); |
2061 | QContactDetail d(unknownType); |
2062 | d.setValue(field: unknown, value: 5); |
2063 | c.saveDetail(detail: &d); |
2064 | |
2065 | QVERIFY(m1.saveContact(&c) == false); |
2066 | QVERIFY(m1.error() == QContactManager::InvalidDetailError); |
2067 | QVERIFY(m2.error() == QContactManager::BadArgumentError); |
2068 | } |
2069 | |
2070 | void tst_QContactManager::actionPreferences() |
2071 | { |
2072 | QFETCH(QString, uri); |
2073 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
2074 | |
2075 | // create a sample contact |
2076 | QContactAvatar a; |
2077 | a.setImageUrl(QUrl("test.png" )); |
2078 | QContactPhoneNumber p1; |
2079 | p1.setNumber("12345" ); |
2080 | QContactPhoneNumber p2; |
2081 | p2.setNumber("34567" ); |
2082 | QContactPhoneNumber p3; |
2083 | p3.setNumber("56789" ); |
2084 | QContactUrl u; |
2085 | u.setUrl("http://test.nokia.com" ); |
2086 | QContactName n; |
2087 | QContact c; |
2088 | saveContactName(contact: &c, contactName: &n, name: "TestContact" ); |
2089 | c.saveDetail(detail: &a); |
2090 | c.saveDetail(detail: &p1); |
2091 | c.saveDetail(detail: &p2); |
2092 | c.saveDetail(detail: &p3); |
2093 | c.saveDetail(detail: &u); |
2094 | |
2095 | // set a preference for dialing a particular saved phonenumber. |
2096 | c.setPreferredDetail(actionName: "Dial" , preferredDetail: p2); |
2097 | |
2098 | QVERIFY(cm->saveContact(&c)); // save the contact |
2099 | QContact loaded = cm->contact(contactId: c.id()); // reload the contact |
2100 | |
2101 | // test that the preference was saved correctly. |
2102 | QContactDetail pref = loaded.preferredDetail(actionName: "Dial" ); |
2103 | QVERIFY(pref == p2); |
2104 | |
2105 | cm->removeContact(contactId: c.id()); |
2106 | } |
2107 | |
2108 | void tst_QContactManager::changeSet() |
2109 | { |
2110 | QContactId id = makeId(managerName: "a" , id: 1); |
2111 | QContactChangeSet changeSet; |
2112 | QVERIFY(changeSet.addedContacts().isEmpty()); |
2113 | QVERIFY(changeSet.changedContacts().isEmpty()); |
2114 | QVERIFY(changeSet.removedContacts().isEmpty()); |
2115 | |
2116 | changeSet.insertAddedContact(addedContactId: id); |
2117 | QVERIFY(!changeSet.addedContacts().isEmpty()); |
2118 | QVERIFY(changeSet.changedContacts().isEmpty()); |
2119 | QVERIFY(changeSet.removedContacts().isEmpty()); |
2120 | QVERIFY(changeSet.addedContacts().contains(id)); |
2121 | |
2122 | changeSet.insertChangedContact(addedContactId: id, typesChanged: QList<QContactDetail::DetailType>()); |
2123 | changeSet.insertChangedContacts(addedContactIds: QList<QContactId>() << id, typesChanged: QList<QContactDetail::DetailType>()); |
2124 | QCOMPARE(changeSet.changedContacts().size(), 1); // set, should only be added once. |
2125 | QCOMPARE(changeSet.changedContacts().first().second.size(), 1); // only one changed contact ID |
2126 | QVERIFY(!changeSet.addedContacts().isEmpty()); |
2127 | QVERIFY(!changeSet.changedContacts().isEmpty()); |
2128 | QVERIFY(changeSet.removedContacts().isEmpty()); |
2129 | |
2130 | changeSet.clearChangedContacts(); |
2131 | changeSet.insertChangedContacts(addedContactIds: QList<QContactId>() << id, typesChanged: QList<QContactDetail::DetailType>() << QContactName::Type); |
2132 | changeSet.insertChangedContacts(addedContactIds: QList<QContactId>() << id, typesChanged: QList<QContactDetail::DetailType>() << QContactBirthday::Type); |
2133 | QCOMPARE(changeSet.changedContacts().size(), 2); // should be added twice with differing change types |
2134 | QVERIFY(!changeSet.addedContacts().isEmpty()); |
2135 | QVERIFY(!changeSet.changedContacts().isEmpty()); |
2136 | QVERIFY(changeSet.removedContacts().isEmpty()); |
2137 | QSet<QContactId> changedIds; |
2138 | QSet<QContactDetail::DetailType> changedTypes; |
2139 | foreach (const QContactChangeSet::ContactChangeList &changes, changeSet.changedContacts()) { |
2140 | changedIds |= changes.second.toSet(); |
2141 | if (changes.second.contains(t: id)) { |
2142 | changedTypes |= changes.first.toSet(); |
2143 | } |
2144 | } |
2145 | QCOMPARE(changedIds, (QList<QContactId>() << id).toSet()); |
2146 | QCOMPARE(changedTypes, (QList<QContactDetail::DetailType>() << QContactName::Type << QContactBirthday::Type).toSet()); |
2147 | changeSet.clearChangedContacts(); |
2148 | QVERIFY(changeSet.changedContacts().isEmpty()); |
2149 | |
2150 | QList<QContactId> l1, l2; |
2151 | foreach (int n, QList<int>() << 1 << 1 << 1 << 2 << 2 << 3 << 3 << 4 << 4 << 4 << 5 << 10 << 9 << 8 << 8 << 8 << 7 << 7 << 6) { |
2152 | ((qrand() % 2) ? l1 : l2).append(t: makeId(managerName: "a" , id: n)); |
2153 | } |
2154 | changeSet.clearChangedContacts(); |
2155 | changeSet.insertChangedContacts(addedContactIds: l1, typesChanged: QList<QContactDetail::DetailType>() << QContactName::Type << QContactBirthday::Type); |
2156 | changeSet.insertChangedContacts(addedContactIds: l2, typesChanged: QList<QContactDetail::DetailType>() << QContactBirthday::Type << QContactName::Type << QContactBirthday::Type); |
2157 | QCOMPARE(changeSet.changedContacts().size(), 1); |
2158 | QList<QContactId> expected((l1.toSet() | l2.toSet()).toList()); |
2159 | qSort(c&: expected); |
2160 | QCOMPARE(changeSet.changedContacts().first().second, expected); |
2161 | |
2162 | changeSet.insertRemovedContacts(addedContactIds: QList<QContactId>() << id); |
2163 | QVERIFY(changeSet.removedContacts().contains(id)); |
2164 | changeSet.clearRemovedContacts(); |
2165 | QVERIFY(changeSet.removedContacts().isEmpty()); |
2166 | |
2167 | QVERIFY(changeSet.dataChanged() == false); |
2168 | QContactChangeSet changeSet2; |
2169 | changeSet2 = changeSet; |
2170 | QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts()); |
2171 | changeSet.emitSignals(engine: 0); |
2172 | |
2173 | changeSet2.clearAddedContacts(); |
2174 | QVERIFY(changeSet2.addedContacts().isEmpty()); |
2175 | changeSet2.insertAddedContacts(addedContactIds: changeSet.addedContacts().toList()); |
2176 | QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts()); |
2177 | |
2178 | changeSet2.clearAll(); |
2179 | QVERIFY(changeSet.addedContacts() != changeSet2.addedContacts()); |
2180 | |
2181 | QContactChangeSet changeSet3(changeSet2); |
2182 | QVERIFY(changeSet.addedContacts() != changeSet3.addedContacts()); |
2183 | QVERIFY(changeSet2.addedContacts() == changeSet3.addedContacts()); |
2184 | |
2185 | changeSet.setDataChanged(true); |
2186 | QVERIFY(changeSet.dataChanged() == true); |
2187 | QVERIFY(changeSet.dataChanged() != changeSet2.dataChanged()); |
2188 | QVERIFY(changeSet.dataChanged() != changeSet3.dataChanged()); |
2189 | changeSet.emitSignals(engine: 0); |
2190 | |
2191 | changeSet.addedRelationshipsContacts().insert(value: id); |
2192 | changeSet.insertAddedRelationshipsContacts(affectedContactIds: QList<QContactId>() << id); |
2193 | QVERIFY(changeSet.addedRelationshipsContacts().contains(id)); |
2194 | changeSet.clearAddedRelationshipsContacts(); |
2195 | QVERIFY(changeSet.addedRelationshipsContacts().isEmpty()); |
2196 | changeSet.insertRemovedRelationshipsContacts(affectedContactIds: QList<QContactId>() << id); |
2197 | QVERIFY(changeSet.removedRelationshipsContacts().contains(id)); |
2198 | changeSet.clearRemovedRelationshipsContacts(); |
2199 | QVERIFY(changeSet.removedRelationshipsContacts().isEmpty()); |
2200 | changeSet.emitSignals(engine: 0); |
2201 | changeSet.removedRelationshipsContacts().insert(value: id); |
2202 | changeSet.emitSignals(engine: 0); |
2203 | |
2204 | changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(QContactId(), id)); |
2205 | changeSet2 = changeSet; |
2206 | QVERIFY(changeSet2.addedRelationshipsContacts() == changeSet.addedRelationshipsContacts()); |
2207 | QVERIFY(changeSet2.removedRelationshipsContacts() == changeSet.removedRelationshipsContacts()); |
2208 | QVERIFY(changeSet2.oldAndNewSelfContactId() == changeSet.oldAndNewSelfContactId()); |
2209 | changeSet.emitSignals(engine: 0); |
2210 | changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(id, QContactId())); |
2211 | QVERIFY(changeSet2.oldAndNewSelfContactId() != changeSet.oldAndNewSelfContactId()); |
2212 | changeSet.setDataChanged(true); |
2213 | changeSet.emitSignals(engine: 0); |
2214 | } |
2215 | |
2216 | void tst_QContactManager::fetchHint() |
2217 | { |
2218 | // This just tests the accessors and mutators (API). |
2219 | // See tst_qcontactmanagerfiltering for the "backend support" test. |
2220 | QContactFetchHint hint; |
2221 | hint.setOptimizationHints(QContactFetchHint::NoBinaryBlobs); |
2222 | QCOMPARE(hint.optimizationHints(), QContactFetchHint::NoBinaryBlobs); |
2223 | QStringList rels; |
2224 | rels << QContactRelationship::HasMember(); |
2225 | hint.setRelationshipTypesHint(rels); |
2226 | QCOMPARE(hint.relationshipTypesHint(), rels); |
2227 | QList<QContactDetail::DetailType> types; |
2228 | types << QContactName::Type |
2229 | << QContactPhoneNumber::Type; |
2230 | hint.setDetailTypesHint(types); |
2231 | QCOMPARE(hint.detailTypesHint(), types); |
2232 | QSize prefImageSize(33, 33); |
2233 | hint.setPreferredImageSize(prefImageSize); |
2234 | QCOMPARE(hint.preferredImageSize(), prefImageSize); |
2235 | int limit = 15; |
2236 | hint.setMaxCountHint(limit); |
2237 | QCOMPARE(hint.maxCountHint(), limit); |
2238 | } |
2239 | |
2240 | void tst_QContactManager::selfContactId() |
2241 | { |
2242 | QFETCH(QString, uri); |
2243 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
2244 | |
2245 | // early out if the manager doesn't support self contact id saving |
2246 | QContactId selfContact = cm->selfContactId(); |
2247 | |
2248 | // create a new "self" contact and retrieve its Id |
2249 | QVERIFY(cm->error() == QContactManager::NoError || cm->error() == QContactManager::DoesNotExistError); |
2250 | QContact self; |
2251 | QContactPhoneNumber selfPhn; |
2252 | selfPhn.setNumber("12345" ); |
2253 | self.saveDetail(detail: &selfPhn); |
2254 | if (!cm->saveContact(contact: &self)) { |
2255 | QSKIP("Unable to save the generated self contact" ); |
2256 | } |
2257 | QContactId newSelfContact = self.id(); |
2258 | |
2259 | // Setup signal spy |
2260 | qRegisterMetaType<QContactId>(typeName: "QContactId" ); |
2261 | QSignalSpy spy(cm.data(), SIGNAL(selfContactIdChanged(QContactId,QContactId))); |
2262 | QTestSignalSink sink(cm.data(), SIGNAL(selfContactIdChanged(QContactId,QContactId))); |
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<QContactId>(spy.at(0).at(0)) returns always zero |
2270 | // because the type is not recognized. Hence the ugly casting below. |
2271 | QVERIFY(*((const QContactId*) spy.at(0).at(0).constData()) == selfContact); |
2272 | QVERIFY(*((const QContactId*) spy.at(0).at(1).constData()) == newSelfContact); |
2273 | QVERIFY(cm->selfContactId() == newSelfContact); |
2274 | |
2275 | // Remove self contact |
2276 | if (!cm->removeContact(contactId: self.id())) { |
2277 | QSKIP("Unable to remove self contact" ); |
2278 | } |
2279 | QTRY_VERIFY(spy.count() == 2); |
2280 | QVERIFY(spy.at(1).count() == 2); |
2281 | QVERIFY(*((const QContactId*) spy.at(1).at(0).constData()) == newSelfContact); |
2282 | QVERIFY(*((const QContactId*) spy.at(1).at(1).constData()) == QContactId()); |
2283 | QVERIFY(cm->selfContactId() == QContactId()); // 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.type() != QContactType::Type && d.type() != QContactTimestamp::Type) { |
2294 | newlist << d; |
2295 | } |
2296 | } |
2297 | return newlist; |
2298 | } |
2299 | |
2300 | void tst_QContactManager::detailOrders() |
2301 | { |
2302 | QFETCH(QString, uri); |
2303 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
2304 | |
2305 | if (cm->managerName() == "memory" ) |
2306 | QSKIP("Skipping: This manager does not support detail ordering!" ); |
2307 | |
2308 | QContact a; |
2309 | //phone numbers |
2310 | |
2311 | QContactPhoneNumber number1, number2, number3; |
2312 | |
2313 | number1.setNumber("11111111" ); |
2314 | number1.setContexts(QContactPhoneNumber::ContextHome); |
2315 | |
2316 | number2.setNumber("22222222" ); |
2317 | number2.setContexts(QContactPhoneNumber::ContextWork); |
2318 | |
2319 | number3.setNumber("33333333" ); |
2320 | number3.setContexts(QContactPhoneNumber::ContextOther); |
2321 | |
2322 | a.saveDetail(detail: &number1); |
2323 | a.saveDetail(detail: &number2); |
2324 | a.saveDetail(detail: &number3); |
2325 | |
2326 | QVERIFY(cm->saveContact(&a)); |
2327 | a = cm->contact(contactId: a.id()); |
2328 | |
2329 | QList<QContactDetail> details = a.details(type: QContactPhoneNumber::Type); |
2330 | QVERIFY(details.count() == 3); |
2331 | QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome); |
2332 | QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextWork); |
2333 | QVERIFY(details.at(2).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextOther); |
2334 | |
2335 | number2 = details.at(i: 1); |
2336 | QVERIFY(a.removeDetail(&number2)); |
2337 | QVERIFY(cm->saveContact(&a)); |
2338 | a = cm->contact(contactId: a.id()); |
2339 | details = a.details(type: QContactPhoneNumber::Type); |
2340 | QVERIFY(details.count() == 2); |
2341 | QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome); |
2342 | QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextOther); |
2343 | |
2344 | a.saveDetail(detail: &number2); |
2345 | QVERIFY(cm->saveContact(&a)); |
2346 | a = cm->contact(contactId: a.id()); |
2347 | |
2348 | details = a.details(type: QContactPhoneNumber::Type); |
2349 | QVERIFY(details.count() == 3); |
2350 | QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome); |
2351 | QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextOther); |
2352 | QVERIFY(details.at(2).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextWork); |
2353 | |
2354 | //addresses |
2355 | QContactAddress address1, address2, address3; |
2356 | |
2357 | address1.setStreet("Brandl St" ); |
2358 | address1.setRegion("Brisbane" ); |
2359 | address3 = address2 = address1; |
2360 | |
2361 | address1.setContexts(QContactAddress::ContextHome); |
2362 | address2.setContexts(QContactAddress::ContextWork); |
2363 | address3.setContexts(QContactAddress::ContextOther); |
2364 | |
2365 | QVERIFY(a.saveDetail(&address1)); |
2366 | QVERIFY(a.saveDetail(&address2)); |
2367 | QVERIFY(a.saveDetail(&address3)); |
2368 | |
2369 | QVERIFY(cm->saveContact(&a)); |
2370 | a = cm->contact(contactId: a.id()); |
2371 | details = a.details(type: QContactAddress::Type); |
2372 | QCOMPARE(details.count(), 3); // 1 location - they're unique |
2373 | |
2374 | // Detail keys for the moment are not persistent through an contact save / fetch |
2375 | address3 = details.at(i: 0); |
2376 | |
2377 | QVERIFY(a.removeDetail(&address3)); // remove the most recent. |
2378 | address2 = details.at(i: 1); // It is necessary to re-load the detail to ensure that its key is correct |
2379 | QVERIFY(a.removeDetail(&address2)); |
2380 | QVERIFY(cm->saveContact(&a)); |
2381 | a = cm->contact(contactId: a.id()); |
2382 | details = a.details(type: QContactAddress::Type); |
2383 | QVERIFY(details.count() == 0); // unique, remove one means none left. |
2384 | |
2385 | a.saveDetail(detail: &address2); |
2386 | QVERIFY(cm->saveContact(&a)); |
2387 | a = cm->contact(contactId: a.id()); |
2388 | |
2389 | details = a.details(type: QContactAddress::Type); |
2390 | QVERIFY(details.count() == 1); // add one back. |
2391 | |
2392 | |
2393 | //emails |
2394 | QContactEmailAddress email1, email2, email3; |
2395 | |
2396 | email1.setEmailAddress("aaron@example.com" ); |
2397 | email3 = email2 = email1; |
2398 | email1.setContexts(QContactEmailAddress::ContextHome); |
2399 | email2.setContexts(QContactEmailAddress::ContextWork); |
2400 | email3.setContexts(QContactEmailAddress::ContextOther); |
2401 | |
2402 | a.saveDetail(detail: &email1); |
2403 | a.saveDetail(detail: &email2); |
2404 | a.saveDetail(detail: &email3); |
2405 | |
2406 | QVERIFY(cm->saveContact(&a)); |
2407 | a = cm->contact(contactId: a.id()); |
2408 | |
2409 | details = a.details(type: QContactEmailAddress::Type); |
2410 | QVERIFY(details.count() == 1); |
2411 | // Detail keys for the moment are not persistent through an contact save / fetch |
2412 | email3 = details.at(i: 0); |
2413 | |
2414 | QVERIFY(a.removeDetail(&email3)); // remove the most recent. |
2415 | email2 = details.at(i: 1); // It is necessary to re-load the detail to ensure that its key is correct |
2416 | QVERIFY(a.removeDetail(&email2)); |
2417 | QVERIFY(cm->saveContact(&a)); |
2418 | a = cm->contact(contactId: a.id()); |
2419 | details = a.details(type: QContactEmailAddress::Type); |
2420 | QVERIFY(details.count() == 0); // unique, remove one means none left. |
2421 | |
2422 | a.saveDetail(detail: &email2); |
2423 | QVERIFY(cm->saveContact(&a)); |
2424 | a = cm->contact(contactId: a.id()); |
2425 | |
2426 | details = a.details(type: QContactEmailAddress::Type); |
2427 | QVERIFY(details.count() == 1); // add one back. |
2428 | |
2429 | QVERIFY(cm->removeContact(a.id())); |
2430 | QVERIFY(cm->error() == QContactManager::NoError); |
2431 | } |
2432 | |
2433 | void tst_QContactManager::relationships() |
2434 | { |
2435 | QFETCH(QString, uri); |
2436 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
2437 | |
2438 | // save some contacts |
2439 | QContact source; |
2440 | QContact dest1, dest2, dest3, dest4; |
2441 | QContactPhoneNumber n1, n2, n3, n4; |
2442 | n1.setNumber("1" ); |
2443 | n2.setNumber("2" ); |
2444 | n3.setNumber("3" ); |
2445 | n4.setNumber("4" ); |
2446 | |
2447 | dest1.saveDetail(detail: &n1); |
2448 | dest2.saveDetail(detail: &n2); |
2449 | dest3.saveDetail(detail: &n3); |
2450 | dest4.saveDetail(detail: &n4); |
2451 | |
2452 | cm->saveContact(contact: &source); |
2453 | cm->saveContact(contact: &dest1); |
2454 | cm->saveContact(contact: &dest2); |
2455 | cm->saveContact(contact: &dest3); |
2456 | cm->saveContact(contact: &dest4); |
2457 | |
2458 | // check if manager supports relationships |
2459 | |
2460 | if (!cm->isRelationshipTypeSupported(relationshipType: QContactRelationship::HasManager())) { |
2461 | // ensure that the operations all fail as required. |
2462 | QContactRelationship r1, r2, r3; |
2463 | r1.setFirst(source.id()); |
2464 | r1.setSecond(dest1.id()); |
2465 | r1.setRelationshipType(QContactRelationship::HasManager()); |
2466 | r2.setFirst(source.id()); |
2467 | r2.setSecond(dest2.id()); |
2468 | r2.setRelationshipType(QContactRelationship::HasManager()); |
2469 | r3.setFirst(source.id()); |
2470 | r3.setSecond(dest3.id()); |
2471 | r3.setRelationshipType(QContactRelationship::HasManager()); |
2472 | |
2473 | QList<QContactRelationship> batchList; |
2474 | batchList << r2 << r3; |
2475 | |
2476 | // test save and remove |
2477 | QVERIFY(!cm->saveRelationship(&r1)); |
2478 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2479 | QVERIFY(!cm->removeRelationship(r1)); |
2480 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2481 | cm->saveRelationships(relationships: &batchList, NULL); |
2482 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2483 | |
2484 | // test retrieval |
2485 | QList<QContactRelationship> retrieveList; |
2486 | retrieveList = cm->relationships(participantId: source.id(), role: QContactRelationship::First); |
2487 | QVERIFY(retrieveList.isEmpty()); |
2488 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2489 | retrieveList = cm->relationships(participantId: source.id(), role: QContactRelationship::Second); |
2490 | QVERIFY(retrieveList.isEmpty()); |
2491 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2492 | retrieveList = cm->relationships(participantId: source.id(), role: QContactRelationship::Either); // Either |
2493 | QVERIFY(retrieveList.isEmpty()); |
2494 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2495 | |
2496 | |
2497 | retrieveList = cm->relationships(relationshipType: QContactRelationship::HasManager(), participantId: source.id(), role: QContactRelationship::First); |
2498 | QVERIFY(retrieveList.isEmpty()); |
2499 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2500 | retrieveList = cm->relationships(relationshipType: QContactRelationship::HasManager(), participantId: source.id(), role: QContactRelationship::Second); |
2501 | QVERIFY(retrieveList.isEmpty()); |
2502 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2503 | retrieveList = cm->relationships(relationshipType: QContactRelationship::HasManager(), participantId: source.id(), role: QContactRelationship::Either); |
2504 | QVERIFY(retrieveList.isEmpty()); |
2505 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2506 | retrieveList = cm->relationships(relationshipType: QContactRelationship::HasManager(), participantId: source.id()); |
2507 | QVERIFY(retrieveList.isEmpty()); |
2508 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2509 | retrieveList = cm->relationships(relationshipType: QContactRelationship::HasManager()); |
2510 | QVERIFY(retrieveList.isEmpty()); |
2511 | QVERIFY(cm->error() == QContactManager::NotSupportedError); |
2512 | return; |
2513 | } |
2514 | |
2515 | // Get supported relationship types |
2516 | QStringList availableRelationshipTypes; |
2517 | if (cm->isRelationshipTypeSupported(relationshipType: QContactRelationship::HasMember())) |
2518 | availableRelationshipTypes << QContactRelationship::HasMember(); |
2519 | if (cm->isRelationshipTypeSupported(relationshipType: QContactRelationship::HasAssistant())) |
2520 | availableRelationshipTypes << QContactRelationship::HasAssistant(); |
2521 | if (cm->isRelationshipTypeSupported(relationshipType: QContactRelationship::HasManager())) |
2522 | availableRelationshipTypes << QContactRelationship::HasManager(); |
2523 | if (cm->isRelationshipTypeSupported(relationshipType: QContactRelationship::HasSpouse())) |
2524 | availableRelationshipTypes << QContactRelationship::HasSpouse(); |
2525 | if (cm->isRelationshipTypeSupported(relationshipType: QContactRelationship::IsSameAs())) |
2526 | availableRelationshipTypes << QContactRelationship::IsSameAs(); |
2527 | |
2528 | // add some arbitrary type for testing |
2529 | if (availableRelationshipTypes.count()) |
2530 | availableRelationshipTypes.insert(i: 0, t: "test-arbitrary-relationship-type" ); |
2531 | else { |
2532 | availableRelationshipTypes.append(t: "test-arbitrary-relationship-type" ); |
2533 | availableRelationshipTypes.append(t: QContactRelationship::HasMember()); |
2534 | availableRelationshipTypes.append(t: QContactRelationship::HasAssistant()); |
2535 | } |
2536 | |
2537 | // Verify that we have relationship types. If there are none then the manager |
2538 | // is saying it supports relationships but does not actually implement any |
2539 | // relationship type. |
2540 | QVERIFY(!availableRelationshipTypes.isEmpty()); |
2541 | |
2542 | // Some backends (eg. symbian) require that when type is "HasMember" |
2543 | // then "first" contact must be a group. |
2544 | if (availableRelationshipTypes.at(i: 0) == QContactRelationship::HasMember()) { |
2545 | cm->removeContact(contactId: source.id()); |
2546 | source.setId(QContactId()); |
2547 | source.setType(QContactType::TypeGroup); |
2548 | cm->saveContact(contact: &source); |
2549 | } |
2550 | |
2551 | // build our relationship - source is the manager all of the dest contacts. |
2552 | QContactRelationship customRelationshipOne; |
2553 | customRelationshipOne.setFirst(source.id()); |
2554 | customRelationshipOne.setSecond(dest1.id()); |
2555 | customRelationshipOne.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2556 | QCOMPARE(customRelationshipOne.first(), source.id()); |
2557 | QCOMPARE(customRelationshipOne.second(), dest1.id()); |
2558 | QVERIFY(customRelationshipOne.relationshipType() == availableRelationshipTypes.at(0)); |
2559 | |
2560 | // save the relationship |
2561 | int managerRelationshipsCount = cm->relationships(relationshipType: availableRelationshipTypes.at(i: 0)).count(); |
2562 | QVERIFY(cm->saveRelationship(&customRelationshipOne)); |
2563 | |
2564 | // test our accessors. |
2565 | QCOMPARE(cm->relationships(availableRelationshipTypes.at(0)).count(), (managerRelationshipsCount + 1)); |
2566 | QVERIFY(cm->relationships(availableRelationshipTypes.at(0), source.id()).count() == 1); |
2567 | |
2568 | // remove the dest1 contact, relationship should be removed. |
2569 | cm->removeContact(contactId: dest1.id()); |
2570 | QCOMPARE(cm->relationships(availableRelationshipTypes.at(0), dest1.id(), QContactRelationship::Second).count(), 0); |
2571 | |
2572 | // modify and save the relationship |
2573 | customRelationshipOne.setSecond(dest2.id()); |
2574 | QVERIFY(cm->saveRelationship(&customRelationshipOne)); |
2575 | |
2576 | // attempt to save the relationship again. XXX TODO: what should the result be? currently succeeds (overwrites) |
2577 | int relationshipsCount = cm->relationships().count(); |
2578 | QVERIFY(cm->saveRelationship(&customRelationshipOne)); // succeeds, but just overwrites |
2579 | QCOMPARE(relationshipsCount, cm->relationships().count()); // shouldn't change; save should have overwritten. |
2580 | |
2581 | // removing the source contact should result in removal of the relationship. |
2582 | QVERIFY(cm->removeContact(source.id())); |
2583 | QCOMPARE(cm->relationships().count(), relationshipsCount - 1); // the relationship should have been removed. |
2584 | |
2585 | // now ensure that qcontact relationship caching works as required - perhaps this should be in tst_QContact? |
2586 | source.setId(QContactId()); // reset id so we can resave |
2587 | QVERIFY(cm->saveContact(&source)); // save source again. |
2588 | customRelationshipOne.setFirst(source.id()); |
2589 | customRelationshipOne.setSecond(dest2.id()); |
2590 | QVERIFY(cm->saveRelationship(&customRelationshipOne)); |
2591 | |
2592 | // Add a second relationship |
2593 | QContactRelationship customRelationshipTwo; |
2594 | customRelationshipTwo.setFirst(source.id()); |
2595 | if (availableRelationshipTypes.count() > 1) |
2596 | customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(i: 1)); |
2597 | else |
2598 | customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2599 | customRelationshipTwo.setSecond(dest3.id()); |
2600 | QVERIFY(cm->saveRelationship(&customRelationshipTwo)); |
2601 | |
2602 | // currently, the contacts are "stale" - no cached relationships |
2603 | QVERIFY(dest3.relatedContacts().isEmpty()); |
2604 | QVERIFY(dest3.relationships().isEmpty()); |
2605 | QVERIFY(dest2.relatedContacts().isEmpty()); |
2606 | QVERIFY(dest2.relationships().isEmpty()); |
2607 | |
2608 | // now refresh the contacts |
2609 | dest3 = cm->contact(contactId: dest3.id()); |
2610 | dest2 = cm->contact(contactId: dest2.id()); |
2611 | source = cm->contact(contactId: source.id()); |
2612 | |
2613 | // and test again. |
2614 | QVERIFY(source.relatedContacts(QString(), QContactRelationship::First).isEmpty()); // source is always the first, so this should be empty. |
2615 | QVERIFY(source.relatedContacts(QString(), QContactRelationship::Second).contains(dest2.id())); |
2616 | QVERIFY(source.relatedContacts(QString(), QContactRelationship::Either).contains(dest2.id())); |
2617 | QVERIFY(source.relatedContacts(QString(), QContactRelationship::Second).contains(dest3.id())); |
2618 | QVERIFY(source.relatedContacts(QString(), QContactRelationship::Either).contains(dest3.id())); |
2619 | QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).contains(dest2.id())); |
2620 | QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::First).isEmpty()); |
2621 | |
2622 | QVERIFY(dest2.relatedContacts().contains(source.id())); |
2623 | QVERIFY(dest2.relationships().contains(customRelationshipOne)); |
2624 | QVERIFY(!dest2.relationships().contains(customRelationshipTwo)); |
2625 | QVERIFY(dest2.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipOne)); |
2626 | QVERIFY(!dest2.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipTwo)); |
2627 | QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0)).contains(source.id())); |
2628 | QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::First).contains(source.id())); |
2629 | QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).isEmpty()); |
2630 | QVERIFY(!dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).contains(source.id())); |
2631 | |
2632 | QVERIFY(dest3.relatedContacts().contains(source.id())); |
2633 | QVERIFY(!dest3.relationships().contains(customRelationshipOne)); |
2634 | QVERIFY(dest3.relationships().contains(customRelationshipTwo)); |
2635 | QVERIFY(!dest3.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipOne)); |
2636 | |
2637 | // Test iteration |
2638 | QList<QContactRelationship> relats = source.relationships(); |
2639 | QList<QContactRelationship>::iterator it = relats.begin(); |
2640 | |
2641 | while (it != relats.end()) { |
2642 | QContactId firstContactId = it->first(); |
2643 | QVERIFY(firstContactId == source.id()); |
2644 | QVERIFY(it->second() == dest2.id() || it->second() == dest3.id()); |
2645 | it++; |
2646 | } |
2647 | |
2648 | if (availableRelationshipTypes.count() > 1) { |
2649 | QVERIFY(source.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::Second).contains(dest3.id())); |
2650 | QVERIFY(source.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::First).isEmpty()); |
2651 | |
2652 | QVERIFY(dest2.relationships(availableRelationshipTypes.at(1)).isEmpty()); |
2653 | |
2654 | QVERIFY(!dest3.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipTwo)); |
2655 | QVERIFY(dest3.relationships(availableRelationshipTypes.at(1)).contains(customRelationshipTwo)); |
2656 | QVERIFY(!dest3.relationships(availableRelationshipTypes.at(1)).contains(customRelationshipOne)); |
2657 | QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1)).contains(source.id())); |
2658 | QVERIFY(!dest3.relatedContacts(availableRelationshipTypes.at(0)).contains(source.id())); |
2659 | QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1)).contains(source.id())); // role = either |
2660 | QVERIFY(!dest3.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::Second).contains(source.id())); |
2661 | QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::First).contains(source.id())); |
2662 | QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(1)).isEmpty()); |
2663 | } else { |
2664 | QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).contains(dest3.id())); |
2665 | } |
2666 | |
2667 | // Cleanup a bit |
2668 | QMap<int, QContactManager::Error> errorMap; |
2669 | QList<QContactRelationship> moreRels; |
2670 | |
2671 | moreRels << customRelationshipOne << customRelationshipTwo; |
2672 | errorMap.insert(key: 5, value: QContactManager::BadArgumentError); |
2673 | QVERIFY(cm->removeRelationships(moreRels, &errorMap)); |
2674 | QVERIFY(errorMap.count() == 0); |
2675 | |
2676 | // test batch API and ordering in contacts |
2677 | QList<QContactRelationship> currentRelationships = cm->relationships(participantId: source.id(), role: QContactRelationship::First); |
2678 | QList<QContactRelationship> batchList; |
2679 | QContactRelationship br1, br2, br3; |
2680 | br1.setFirst(source.id()); |
2681 | br1.setSecond(dest2.id()); |
2682 | br1.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2683 | br2.setFirst(source.id()); |
2684 | br2.setSecond(dest3.id()); |
2685 | br2.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2686 | if (availableRelationshipTypes.count() > 1) { |
2687 | br3.setFirst(source.id()); |
2688 | br3.setSecond(dest3.id()); |
2689 | br3.setRelationshipType(availableRelationshipTypes.at(i: 1)); |
2690 | } else { |
2691 | br3.setFirst(source.id()); |
2692 | br3.setSecond(dest4.id()); |
2693 | br3.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2694 | } |
2695 | batchList << br1 << br2 << br3; |
2696 | |
2697 | // ensure that the batch save works properly |
2698 | cm->saveRelationships(relationships: &batchList, NULL); |
2699 | QCOMPARE(cm->error(), QContactManager::NoError); |
2700 | QList<QContactRelationship> batchRetrieve = cm->relationships(participantId: source.id(), role: QContactRelationship::First); |
2701 | QVERIFY(batchRetrieve.contains(br1)); |
2702 | QVERIFY(batchRetrieve.contains(br2)); |
2703 | QVERIFY(batchRetrieve.contains(br3)); |
2704 | |
2705 | // remove a single relationship |
2706 | QVERIFY(cm->removeRelationship(br3)); |
2707 | batchRetrieve = cm->relationships(participantId: source.id(), role: QContactRelationship::First); |
2708 | QVERIFY(batchRetrieve.contains(br1)); |
2709 | QVERIFY(batchRetrieve.contains(br2)); |
2710 | QVERIFY(!batchRetrieve.contains(br3)); // has already been removed. |
2711 | |
2712 | // now ensure that the batch remove works and we get returned to the original state. |
2713 | batchList.removeOne(t: br3); |
2714 | cm->removeRelationships(relationships: batchList, NULL); |
2715 | QVERIFY(cm->error() == QContactManager::NoError); |
2716 | QCOMPARE(cm->relationships(source.id(), QContactRelationship::First), currentRelationships); |
2717 | |
2718 | // attempt to save relationships between an existing source but non-existent destination |
2719 | QContact nonexistentDest; |
2720 | quint32 idSeed = 0x5544; |
2721 | QContactId nonexistentLocalId = QContactId::fromString(idString: QString::number(idSeed)); |
2722 | while (true) { |
2723 | nonexistentLocalId = cm->contact(contactId: nonexistentLocalId).id(); |
2724 | if (nonexistentLocalId == QContactId()) { |
2725 | // found a "spare" local id (no contact with that id) |
2726 | break; |
2727 | } |
2728 | |
2729 | // keep looking... |
2730 | idSeed += 1; |
2731 | nonexistentLocalId = QContactId::fromString(idString: QString::number(idSeed)); |
2732 | QVERIFY(nonexistentLocalId != QContactId()); // integer overflow check. |
2733 | } |
2734 | // nonexistentDest.id().setLocalId(nonexistentLocalId); |
2735 | |
2736 | QContactRelationship maliciousRel; |
2737 | maliciousRel.setFirst(source.id()); |
2738 | maliciousRel.setSecond(nonexistentDest.id()); |
2739 | maliciousRel.setRelationshipType("nokia-test-invalid-relationship-type" ); |
2740 | QVERIFY(!cm->saveRelationship(&maliciousRel)); |
2741 | |
2742 | // attempt to save a circular relationship - should fail! |
2743 | maliciousRel.setFirst(source.id()); |
2744 | maliciousRel.setSecond(source.id()); |
2745 | maliciousRel.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2746 | QVERIFY(!cm->saveRelationship(&maliciousRel)); |
2747 | |
2748 | // more negative testing, but force manager to recognise the empty URI |
2749 | QContact circularContact = source; |
2750 | maliciousRel.setFirst(circularContact.id()); |
2751 | maliciousRel.setSecond(circularContact.id()); |
2752 | maliciousRel.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2753 | QVERIFY(!cm->saveRelationship(&maliciousRel)); |
2754 | maliciousRel.setFirst(source.id()); |
2755 | maliciousRel.setSecond(circularContact.id()); |
2756 | maliciousRel.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2757 | QVERIFY(!cm->saveRelationship(&maliciousRel)); |
2758 | maliciousRel.setFirst(circularContact.id()); |
2759 | maliciousRel.setSecond(source.id()); |
2760 | maliciousRel.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2761 | QVERIFY(!cm->saveRelationship(&maliciousRel)); |
2762 | |
2763 | // attempt to save a relationship where the source contact comes from another manager |
2764 | QContactId invalidId; |
2765 | circularContact.setId(invalidId); |
2766 | maliciousRel.setFirst(circularContact.id()); // an invalid source contact |
2767 | maliciousRel.setSecond(dest2.id()); // a valid destination contact |
2768 | maliciousRel.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2769 | QVERIFY(!cm->saveRelationship(&maliciousRel)); |
2770 | |
2771 | // remove the nonexistent relationship |
2772 | relationshipsCount = cm->relationships().count(); |
2773 | QVERIFY(!cm->removeRelationship(maliciousRel)); // does not exist; fail remove. |
2774 | QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError); |
2775 | QCOMPARE(cm->relationships().count(), relationshipsCount); // should be unchanged. |
2776 | |
2777 | // now we want to ensure that a relationship is removed if one of the contacts is removed. |
2778 | customRelationshipOne.setFirst(source.id()); |
2779 | customRelationshipOne.setSecond(dest2.id()); |
2780 | customRelationshipOne.setRelationshipType(availableRelationshipTypes.at(i: 0)); |
2781 | |
2782 | // Test batch save with an error map |
2783 | moreRels.clear(); |
2784 | moreRels << customRelationshipOne; |
2785 | errorMap.insert(key: 0, value: QContactManager::BadArgumentError); |
2786 | QVERIFY(cm->saveRelationships(&moreRels, &errorMap)); |
2787 | QVERIFY(cm->error() == QContactManager::NoError); |
2788 | QVERIFY(errorMap.count() == 0); // should be reset |
2789 | source = cm->contact(contactId: source.id()); |
2790 | dest2 = cm->contact(contactId: dest2.id()); |
2791 | QVERIFY(cm->removeContact(dest2.id())); // remove dest2, the relationship should be removed |
2792 | QVERIFY(cm->relationships(availableRelationshipTypes.at(0), dest2.id(), QContactRelationship::Second).isEmpty()); |
2793 | source = cm->contact(contactId: source.id()); |
2794 | QVERIFY(!source.relatedContacts().contains(dest2.id())); // and it shouldn't appear in cache. |
2795 | |
2796 | // now clean up and remove our dests. |
2797 | QVERIFY(cm->removeContact(source.id())); |
2798 | QVERIFY(cm->removeContact(dest3.id())); |
2799 | |
2800 | // attempt to save relationships with nonexistent contacts |
2801 | QVERIFY(!cm->saveRelationship(&br1)); |
2802 | QVERIFY(cm->error() == QContactManager::InvalidRelationshipError); |
2803 | cm->saveRelationships(relationships: &batchList, NULL); |
2804 | QVERIFY(cm->error() == QContactManager::InvalidRelationshipError); |
2805 | QVERIFY(!cm->removeRelationship(br1)); |
2806 | QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError); |
2807 | cm->removeRelationships(relationships: batchList, NULL); |
2808 | QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError); |
2809 | } |
2810 | |
2811 | void tst_QContactManager::contactType() |
2812 | { |
2813 | QFETCH(QString, uri); |
2814 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
2815 | |
2816 | if (!cm->supportedContactTypes().contains(t: QContactType::TypeGroup)) |
2817 | QSKIP("Skipping: This manager does not support group contacts!" ); |
2818 | |
2819 | QContact g1, g2, c; |
2820 | |
2821 | g1.setType(QContactType::TypeGroup); |
2822 | g2.setType(QContactType::TypeGroup); |
2823 | |
2824 | QContactPhoneNumber g1p, g2p, cp; |
2825 | g1p.setNumber("22222" ); |
2826 | g2p.setNumber("11111" ); |
2827 | cp.setNumber("33333" ); |
2828 | |
2829 | g1.saveDetail(detail: &g1p); |
2830 | g2.saveDetail(detail: &g2p); |
2831 | c.saveDetail(detail: &cp); |
2832 | |
2833 | QVERIFY(cm->saveContact(&g1)); |
2834 | QVERIFY(cm->saveContact(&g2)); |
2835 | QVERIFY(cm->saveContact(&c)); |
2836 | |
2837 | // test that the accessing by type works properly |
2838 | QContactDetailFilter groupFilter; |
2839 | groupFilter.setDetailType(type: QContactType::Type, field: QContactType::FieldType); |
2840 | groupFilter.setValue(QContactType::TypeGroup); |
2841 | QVERIFY(cm->contactIds(groupFilter).contains(g1.id())); |
2842 | QVERIFY(cm->contactIds(groupFilter).contains(g2.id())); |
2843 | QVERIFY(!cm->contactIds(groupFilter).contains(c.id())); |
2844 | |
2845 | QList<QContactSortOrder> sortOrders; |
2846 | QContactSortOrder byPhoneNumber; |
2847 | byPhoneNumber.setDetailType(type: QContactPhoneNumber::Type, field: QContactPhoneNumber::FieldNumber); |
2848 | sortOrders.append(t: byPhoneNumber); |
2849 | |
2850 | // and ensure that sorting works properly with typed contacts also |
2851 | QList<QContactId> sortedIds = cm->contactIds(filter: groupFilter, sortOrders); |
2852 | QVERIFY(sortedIds.indexOf(g2.id()) < sortedIds.indexOf(g1.id())); |
2853 | |
2854 | cm->removeContact(contactId: g1.id()); |
2855 | cm->removeContact(contactId: g2.id()); |
2856 | cm->removeContact(contactId: c.id()); |
2857 | } |
2858 | |
2859 | #if defined(USE_VERSIT_PLZ) |
2860 | void tst_QContactManager::partialSave() |
2861 | { |
2862 | QFETCH(QString, uri); |
2863 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
2864 | |
2865 | QVersitContactImporter imp; |
2866 | QVersitReader reader(QByteArray( |
2867 | "BEGIN:VCARD\r\nFN:Alice\r\nN:Alice\r\nTEL:12345\r\nEND:VCARD\r\n" |
2868 | "BEGIN:VCARD\r\nFN:Bob\r\nN:Bob\r\nTEL:5678\r\nEND:VCARD\r\n" |
2869 | "BEGIN:VCARD\r\nFN:Carol\r\nN:Carol\r\nEMAIL:carol@example.com\r\nEND:VCARD\r\n" |
2870 | "BEGIN:VCARD\r\nFN:David\r\nN:David\r\nORG:DavidCorp\r\nEND:VCARD\r\n" )); |
2871 | reader.startReading(); |
2872 | reader.waitForFinished(); |
2873 | QCOMPARE(reader.error(), QVersitReader::NoError); |
2874 | |
2875 | QCOMPARE(reader.results().count(), 4); |
2876 | QVERIFY(imp.importDocuments(reader.results())); |
2877 | QCOMPARE(imp.contacts().count(), 4); |
2878 | QVERIFY(imp.contacts()[0].displayLabel() == QStringLiteral("Alice" )); |
2879 | QVERIFY(imp.contacts()[1].displayLabel() == QStringLiteral("Bob" )); |
2880 | QVERIFY(imp.contacts()[2].displayLabel() == QStringLiteral("Carol" )); |
2881 | QVERIFY(imp.contacts()[3].displayLabel() == QStringLiteral("David" )); |
2882 | |
2883 | QList<QContact> contacts = imp.contacts(); |
2884 | QMap<int, QContactManager::Error> errorMap; |
2885 | |
2886 | // First save these contacts |
2887 | QVERIFY(cm->saveContacts(&contacts, &errorMap)); |
2888 | QList<QContact> originalContacts = contacts; |
2889 | |
2890 | // Now try some partial save operations |
2891 | // 0) empty mask == full save |
2892 | // 1) Ignore an added phonenumber |
2893 | // 2) Only save a modified phonenumber, not a modified email |
2894 | // 3) Remove an email address & phone, mask out phone |
2895 | // 4) new contact, no details in the mask |
2896 | // 5) new contact, some details in the mask |
2897 | // 6) Have a bad manager uri in the middle |
2898 | // 7) Have a non existing contact in the middle |
2899 | // 8) A list entirely of new contacts |
2900 | |
2901 | QContactPhoneNumber pn; |
2902 | pn.setNumber("111111" ); |
2903 | contacts[0].saveDetail(&pn); |
2904 | |
2905 | // 0) empty mask |
2906 | QVERIFY(cm->saveContacts(&contacts, QStringList(), &errorMap)); |
2907 | |
2908 | // That should have updated everything |
2909 | QContact a = cm->contact(originalContacts[0].id()); |
2910 | QVERIFY(a.details<QContactPhoneNumber>().count() == 2); |
2911 | |
2912 | // 1) Add a phone number to b, mask it out |
2913 | contacts[1].saveDetail(&pn); |
2914 | QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap)); |
2915 | QVERIFY(errorMap.isEmpty()); |
2916 | |
2917 | QContact b = cm->contact(originalContacts[1].id()); |
2918 | QVERIFY(b.details<QContactPhoneNumber>().count() == 1); |
2919 | |
2920 | // 2) save a modified detail in the mask |
2921 | QContactEmailAddress e; |
2922 | e.setEmailAddress("example@example.com" ); |
2923 | contacts[1].saveDetail(&e); // contacts[1] should have both phone and email |
2924 | |
2925 | QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap)); |
2926 | QVERIFY(errorMap.isEmpty()); |
2927 | b = cm->contact(originalContacts[1].id()); |
2928 | QVERIFY(b.details<QContactPhoneNumber>().count() == 1); |
2929 | QVERIFY(b.details<QContactEmailAddress>().count() == 1); |
2930 | |
2931 | // 3) Remove an email address and a phone number |
2932 | QVERIFY(contacts[1].removeDetail(&e)); |
2933 | QVERIFY(contacts[1].removeDetail(&pn)); |
2934 | QVERIFY(contacts[1].details<QContactEmailAddress>().count() == 0); |
2935 | QVERIFY(contacts[1].details<QContactPhoneNumber>().count() == 1); |
2936 | QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap)); |
2937 | QVERIFY(errorMap.isEmpty()); |
2938 | b = cm->contact(originalContacts[1].id()); |
2939 | QVERIFY(b.details<QContactPhoneNumber>().count() == 1); |
2940 | QVERIFY(b.details<QContactEmailAddress>().count() == 0); |
2941 | |
2942 | // 4 - New contact, no details in the mask |
2943 | QContact newContact = originalContacts[3]; |
2944 | newContact.setId(QContactId()); |
2945 | |
2946 | contacts.append(newContact); |
2947 | QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap)); |
2948 | QVERIFY(errorMap.isEmpty()); |
2949 | QVERIFY(contacts[4].id() != 0); // Saved |
2950 | b = cm->contact(contacts[4].id()); |
2951 | QVERIFY(b.details<QContactOrganization>().count() == 0); // not saved |
2952 | QVERIFY(b.details<QContactName>().count() == 0); // not saved |
2953 | |
2954 | // 5 - New contact, some details in the mask |
2955 | newContact = originalContacts[2]; |
2956 | newContact.setId(QContactId()); |
2957 | contacts.append(newContact); |
2958 | QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap)); |
2959 | QVERIFY(errorMap.isEmpty()); |
2960 | QVERIFY(contacts[5].id() != 0); // Saved |
2961 | b = cm->contact(contacts[5].id()); |
2962 | QVERIFY(b.details<QContactEmailAddress>().count() == 1); |
2963 | QVERIFY(b.details<QContactName>().count() == 0); // not saved |
2964 | |
2965 | // 6) Have a bad manager uri in the middle followed by a save error |
2966 | QContactId id4(contacts[4].id()); |
2967 | QContactId badId(id4); |
2968 | badId.setManagerUri(QString()); |
2969 | contacts[4].setId(badId); |
2970 | QContactDetail badDetail("BadDetail" ); |
2971 | badDetail.setValue("BadField" , "BadValue" ); |
2972 | contacts[5].saveDetail(&badDetail); |
2973 | QVERIFY(!cm->saveContacts(&contacts, QStringList("BadDetail" ), &errorMap)); |
2974 | QCOMPARE(errorMap.count(), 2); |
2975 | QCOMPARE(errorMap[4], QContactManager::DoesNotExistError); |
2976 | QCOMPARE(errorMap[5], QContactManager::InvalidDetailError); |
2977 | |
2978 | // 7) Have a non existing contact in the middle followed by a save error |
2979 | badId = id4; |
2980 | badId.setLocalId("987234" ); // something nonexistent |
2981 | contacts[4].setId(badId); |
2982 | QVERIFY(!cm->saveContacts(&contacts, QStringList("BadDetail" ), &errorMap)); |
2983 | QCOMPARE(errorMap.count(), 2); |
2984 | QCOMPARE(errorMap[4], QContactManager::DoesNotExistError); |
2985 | QCOMPARE(errorMap[5], QContactManager::InvalidDetailError); |
2986 | |
2987 | // 8 - New contact, no details in the mask |
2988 | newContact = originalContacts[3]; |
2989 | QCOMPARE(newContact.details<QContactOrganization>().count(), 1); |
2990 | QCOMPARE(newContact.details<QContactName>().count(), 1); |
2991 | newContact.setId(QContactId()); |
2992 | QList<QContact> contacts2; |
2993 | contacts2.append(newContact); |
2994 | QVERIFY(cm->saveContacts(&contacts2, QStringList(QContactEmailAddress::Type), &errorMap)); |
2995 | QVERIFY(errorMap.isEmpty()); |
2996 | QVERIFY(contacts2[0].id() != 0); // Saved |
2997 | b = cm->contact(contacts2[0].id()); |
2998 | QVERIFY(b.details<QContactOrganization>().count() == 0); // not saved |
2999 | QVERIFY(b.details<QContactName>().count() == 0); // not saved |
3000 | |
3001 | // 9 - A list with only a new contact, with some details in the mask |
3002 | newContact = originalContacts[2]; |
3003 | newContact.setId(QContactId()); |
3004 | contacts2.clear(); |
3005 | contacts2.append(newContact); |
3006 | QVERIFY(cm->saveContacts(&contacts2, QStringList(QContactEmailAddress::Type), &errorMap)); |
3007 | QVERIFY(errorMap.isEmpty()); |
3008 | QVERIFY(contacts2[0].id() != 0); // Saved |
3009 | b = cm->contact(contacts2[0].id()); |
3010 | QVERIFY(b.details<QContactEmailAddress>().count() == 1); |
3011 | QVERIFY(b.details<QContactName>().count() == 0); // not saved |
3012 | |
3013 | // 10 - A list with new a contact for the wrong manager, followed by a new contact with an |
3014 | // invalid detail |
3015 | newContact = originalContacts[2]; |
3016 | newContact.setId(QContactId()); |
3017 | contacts2.clear(); |
3018 | contacts2.append(newContact); |
3019 | contacts2.append(newContact); |
3020 | contacts2[0].setId(badId); |
3021 | contacts2[1].saveDetail(&badDetail); |
3022 | QVERIFY(!cm->saveContacts(&contacts2, QStringList("BadDetail" ), &errorMap)); |
3023 | QCOMPARE(errorMap.count(), 2); |
3024 | QCOMPARE(errorMap[0], QContactManager::DoesNotExistError); |
3025 | QCOMPARE(errorMap[1], QContactManager::InvalidDetailError); |
3026 | } |
3027 | #endif |
3028 | |
3029 | void tst_QContactManager::lateDeletion() |
3030 | { |
3031 | // Create some engines, but make them get deleted at shutdown |
3032 | QFETCH(QString, uri); |
3033 | QContactManager* cm = QContactManager::fromUri(uri); |
3034 | |
3035 | cm->setParent(qApp); // now do nothing |
3036 | } |
3037 | |
3038 | void tst_QContactManager::lazyConnections() |
3039 | { |
3040 | QSKIP("Skipping: Lazy manager engine does not currently work with new plugin system!" ); |
3041 | //TODO: adapt lazy manager engine to new plugin system |
3042 | QMap<QString, QString> parameters; |
3043 | parameters["version" ] = QString("1" ); |
3044 | QContactManager lazy1("testlazy" , parameters); |
3045 | QContactManager lazy2("testlazy" ); |
3046 | |
3047 | QCOMPARE(lazy1.managerName(), QString("lazy" )); |
3048 | QCOMPARE(lazy2.managerName(), QString("lazy2" )); |
3049 | |
3050 | // Make sure the initial connection counts are empty |
3051 | QCOMPARE(QContactLazyEngine::connectionCounts.count(), 0); |
3052 | QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 0); |
3053 | |
3054 | // Lazy 1 first |
3055 | { |
3056 | QTestSignalSink casink(&lazy1, SIGNAL(contactsAdded(QList<QContactId>))); |
3057 | |
3058 | // See if we got one connection |
3059 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 1); |
3060 | QCOMPARE(QContactLazyEngine::connectionCounts.count(), 1); |
3061 | |
3062 | // Go out of scope, and see if disconnect is called |
3063 | } |
3064 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 0); |
3065 | QCOMPARE(QContactLazyEngine::connectionCounts.count(), 1); |
3066 | |
3067 | // Lazy2 second |
3068 | { |
3069 | QTestSignalSink casink(&lazy2, SIGNAL(contactsAdded(QList<QContactId>))); |
3070 | |
3071 | // See if we got one connection |
3072 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 1); |
3073 | QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 1); |
3074 | |
3075 | // Go out of scope, and see if disconnect is called |
3076 | } |
3077 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 0); |
3078 | QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 1); |
3079 | |
3080 | // Just make sure all the signals get connected correctly |
3081 | { |
3082 | QTestSignalSink casink(&lazy1, SIGNAL(contactsAdded(QList<QContactId>))); |
3083 | QTestSignalSink crsink(&lazy1, SIGNAL(contactsRemoved(QList<QContactId>))); |
3084 | QTestSignalSink cmsink(&lazy1, SIGNAL(contactsChanged(QList<QContactId>, QList<QContactDetail::DetailType>))); |
3085 | QTestSignalSink dcsink(&lazy1, SIGNAL(dataChanged())); |
3086 | QTestSignalSink rasink(&lazy1, SIGNAL(relationshipsAdded(QList<QContactId>))); |
3087 | QTestSignalSink rrsink(&lazy1, SIGNAL(relationshipsRemoved(QList<QContactId>))); |
3088 | QTestSignalSink scsink(&lazy1, SIGNAL(selfContactIdChanged(QContactId,QContactId))); |
3089 | |
3090 | // See if we got all the connections |
3091 | QCOMPARE(QContactLazyEngine::connectionCounts.count(), 7); |
3092 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 1); |
3093 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsChanged)), 1); |
3094 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsRemoved)), 1); |
3095 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::dataChanged)), 1); |
3096 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsAdded)), 1); |
3097 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsRemoved)), 1); |
3098 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::selfContactIdChanged)), 1); |
3099 | } |
3100 | QCOMPARE(QContactLazyEngine::connectionCounts.count(), 7); |
3101 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 0); |
3102 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsChanged)), 0); |
3103 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsRemoved)), 0); |
3104 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::dataChanged)), 0); |
3105 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsAdded)), 0); |
3106 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsRemoved)), 0); |
3107 | QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::selfContactIdChanged)), 0); |
3108 | |
3109 | // and for lazy2 |
3110 | { |
3111 | QTestSignalSink casink(&lazy2, SIGNAL(contactsAdded(QList<QContactId>))); |
3112 | QTestSignalSink crsink(&lazy2, SIGNAL(contactsRemoved(QList<QContactId>))); |
3113 | QTestSignalSink cmsink(&lazy2, SIGNAL(contactsChanged(QList<QContactId>, QList<QContactDetail::DetailType>))); |
3114 | QTestSignalSink dcsink(&lazy2, SIGNAL(dataChanged())); |
3115 | QTestSignalSink rasink(&lazy2, SIGNAL(relationshipsAdded(QList<QContactId>))); |
3116 | QTestSignalSink rrsink(&lazy2, SIGNAL(relationshipsRemoved(QList<QContactId>))); |
3117 | QTestSignalSink scsink(&lazy2, SIGNAL(selfContactIdChanged(QContactId,QContactId))); |
3118 | |
3119 | // See if we got all the connections |
3120 | QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 7); |
3121 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 1); |
3122 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsChanged)), 1); |
3123 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsRemoved)), 1); |
3124 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::dataChanged)), 1); |
3125 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsAdded)), 1); |
3126 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsRemoved)), 1); |
3127 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::selfContactIdChanged)), 1); |
3128 | } |
3129 | QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 7); |
3130 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 0); |
3131 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsChanged)), 0); |
3132 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsRemoved)), 0); |
3133 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::dataChanged)), 0); |
3134 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsAdded)), 0); |
3135 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsRemoved)), 0); |
3136 | QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::selfContactIdChanged)), 0); |
3137 | } |
3138 | |
3139 | void tst_QContactManager::compareVariant() |
3140 | { |
3141 | // Exercise this function a bit |
3142 | QFETCH(QVariant, a); |
3143 | QFETCH(QVariant, b); |
3144 | QFETCH(Qt::CaseSensitivity, cs); |
3145 | QFETCH(int, expected); |
3146 | |
3147 | int comparison = QContactManagerEngine::compareVariant(first: a, second: b, sensitivity: cs); |
3148 | // Since compareVariant is a little imprecise (just sign matters) |
3149 | // convert that here. |
3150 | if (comparison < 0) |
3151 | comparison = -1; |
3152 | else if (comparison > 0) |
3153 | comparison = 1; |
3154 | |
3155 | QCOMPARE(comparison, expected); |
3156 | |
3157 | comparison = QContactManagerEngine::compareVariant(first: b, second: a, sensitivity: cs); |
3158 | if (comparison < 0) |
3159 | comparison = -1; |
3160 | else if (comparison > 0) |
3161 | comparison = 1; |
3162 | |
3163 | // The sign should be flipped now |
3164 | QVERIFY((comparison + expected) == 0); |
3165 | } |
3166 | |
3167 | void tst_QContactManager::createCollection() |
3168 | { |
3169 | QFETCH(QString, uri); |
3170 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
3171 | |
3172 | qRegisterMetaType<QList<QContactCollectionId> >(typeName: "QList<QContactCollectionId>" ); |
3173 | QSignalSpy collectionsAddedSpy(cm.data(), SIGNAL(collectionsAdded(QList<QContactCollectionId>))); |
3174 | QByteArray collectionName = QUuid::createUuid().toByteArray(); |
3175 | |
3176 | // create collection |
3177 | { |
3178 | QContactCollection col; |
3179 | col.setMetaData(key: QContactCollection::KeyName, value: collectionName); |
3180 | QVERIFY(cm->saveCollection(&col)); |
3181 | } |
3182 | |
3183 | // check "collectionsAdded" signal |
3184 | QCOMPARE(collectionsAddedSpy.count(), 1); |
3185 | QList<QContactCollectionId> ids = collectionsAddedSpy.takeFirst().at(i: 0).value<QList<QContactCollectionId> >(); |
3186 | QCOMPARE(ids.count(), 1); |
3187 | |
3188 | // query for new collection |
3189 | { |
3190 | QContactCollection col = cm->collection(collectionId: ids.at(i: 0)); |
3191 | QVERIFY(!col.id().isNull()); |
3192 | QCOMPARE(col.id().toString(), ids.at(0).toString()); |
3193 | QCOMPARE(col.metaData(QContactCollection::KeyName).toByteArray(), collectionName); |
3194 | } |
3195 | } |
3196 | |
3197 | void tst_QContactManager::modifyCollection() |
3198 | { |
3199 | QFETCH(QString, uri); |
3200 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
3201 | |
3202 | qRegisterMetaType<QList<QContactCollectionId> >(typeName: "QList<QContactCollectionId>" ); |
3203 | QSignalSpy collectionsAddedSpy(cm.data(), SIGNAL(collectionsAdded(QList<QContactCollectionId>))); |
3204 | QSignalSpy collectionsChangedSpy(cm.data(), SIGNAL(collectionsChanged(QList<QContactCollectionId>))); |
3205 | |
3206 | QContactCollectionId colId; |
3207 | QByteArray collectionName = QUuid::createUuid().toByteArray(); |
3208 | |
3209 | // save a new collection |
3210 | { |
3211 | QContactCollection col; |
3212 | col.setMetaData(key: QContactCollection::KeyName, value: collectionName); |
3213 | QVERIFY(cm->saveCollection(&col)); |
3214 | QTRY_COMPARE(collectionsAddedSpy.count(), 1); |
3215 | colId = col.id(); |
3216 | QVERIFY(!colId.isNull()); |
3217 | } |
3218 | |
3219 | // edit collection |
3220 | { |
3221 | QCOMPARE(collectionsChangedSpy.count(), 0); |
3222 | QContactCollection col = cm->collection(collectionId: colId); |
3223 | QByteArray newCollectionName = QUuid::createUuid().toByteArray(); |
3224 | col.setMetaData(key: QContactCollection::KeyName, value: newCollectionName); |
3225 | QVERIFY(cm->saveCollection(&col)); |
3226 | |
3227 | // check signal "collectionsChanged" fired contains the collection id |
3228 | QTRY_COMPARE(collectionsChangedSpy.count(), 1); |
3229 | QList<QContactCollectionId> ids = collectionsChangedSpy.takeFirst().at(i: 0).value<QList<QContactCollectionId> >(); |
3230 | QCOMPARE(ids.at(0).toString(), colId.toString()); |
3231 | |
3232 | // check if the collection name was updated |
3233 | QContactCollection col2 = cm->collection(collectionId: colId); |
3234 | QCOMPARE(col2.metaData(QContactCollection::KeyName).toByteArray(), newCollectionName); |
3235 | } |
3236 | } |
3237 | |
3238 | void tst_QContactManager::removeCollection() |
3239 | { |
3240 | QFETCH(QString, uri); |
3241 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
3242 | |
3243 | qRegisterMetaType<QList<QContactCollectionId> >(typeName: "QList<QContactCollectionId>" ); |
3244 | QSignalSpy collectionsAddedSpy(cm.data(), SIGNAL(collectionsAdded(QList<QContactCollectionId>))); |
3245 | QSignalSpy collectionsRemovedSpy(cm.data(), SIGNAL(collectionsRemoved(QList<QContactCollectionId>))); |
3246 | |
3247 | QContactCollectionId colId; |
3248 | |
3249 | // save a new collection |
3250 | { |
3251 | QContactCollection col; |
3252 | QByteArray collectionName = QUuid::createUuid().toByteArray(); |
3253 | col.setMetaData(key: QContactCollection::KeyName, value: collectionName); |
3254 | QVERIFY(cm->saveCollection(&col)); |
3255 | QTRY_COMPARE(collectionsAddedSpy.count(), 1); |
3256 | colId = col.id(); |
3257 | } |
3258 | QList<QContactCollection> collections = cm->collections(); |
3259 | |
3260 | // remove collection |
3261 | cm->removeCollection(collectionId: colId); |
3262 | |
3263 | // check "collectionsRemoved" signal |
3264 | QTRY_COMPARE(collectionsRemovedSpy.count(), 1); |
3265 | QList<QContactCollectionId> ids = collectionsRemovedSpy.takeFirst().at(i: 0).value<QList<QContactCollectionId> >(); |
3266 | QCOMPARE(ids.at(0).toString(), colId.toString()); |
3267 | |
3268 | |
3269 | // check if the correct collection was removed |
3270 | QList<QContactCollection> collectionsAfterRemoval = cm->collections(); |
3271 | QCOMPARE(collections.count() - 1, collectionsAfterRemoval.count()); |
3272 | Q_FOREACH (const QContactCollection &col, collectionsAfterRemoval) { |
3273 | collections.removeAll(t: col); |
3274 | } |
3275 | QCOMPARE(collections.count(), 1); |
3276 | QCOMPARE(collections.at(0).id().toString(), colId.toString()); |
3277 | } |
3278 | |
3279 | void tst_QContactManager::saveContactIntoCollections() |
3280 | { |
3281 | QFETCH(QString, uri); |
3282 | QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri)); |
3283 | |
3284 | qRegisterMetaType<QList<QContactCollectionId> >(typeName: "QList<QContactCollectionId>" ); |
3285 | QSignalSpy collectionsAddedSpy(cm.data(), SIGNAL(collectionsAdded(QList<QContactCollectionId>))); |
3286 | QByteArray collectionName = QUuid::createUuid().toByteArray(); |
3287 | QContactCollectionId colId; |
3288 | QContactId cId; |
3289 | |
3290 | // create collection |
3291 | { |
3292 | QContactCollection col; |
3293 | col.setMetaData(key: QContactCollection::KeyName, value: collectionName); |
3294 | QVERIFY(cm->saveCollection(&col)); |
3295 | QTRY_COMPARE(collectionsAddedSpy.count(), 1); |
3296 | colId = col.id(); |
3297 | } |
3298 | |
3299 | // create contact |
3300 | { |
3301 | QContact c = createContact(firstName: "Alice" , lastName: "Last" , phoneNumber: "12345" ); |
3302 | c.setCollectionId(colId); |
3303 | cm->saveContact(contact: &c); |
3304 | cId = c.id(); |
3305 | } |
3306 | |
3307 | // query new contact and check for collection |
3308 | { |
3309 | QContact c = cm->contact(contactId: cId); |
3310 | QCOMPARE(c.collectionId().toString(), colId.toString()); |
3311 | } |
3312 | } |
3313 | |
3314 | void tst_QContactManager::compareVariant_data() |
3315 | { |
3316 | QTest::addColumn<QVariant>(name: "a" ); |
3317 | QTest::addColumn<QVariant>(name: "b" ); |
3318 | |
3319 | QTest::addColumn<Qt::CaseSensitivity>(name: "cs" ); |
3320 | QTest::addColumn<int>(name: "expected" ); |
3321 | |
3322 | // bool |
3323 | QTest::newRow(dataTag: "bool <" ) << QVariant(false) << QVariant(true) << Qt::CaseInsensitive << -1; |
3324 | QTest::newRow(dataTag: "bool =" ) << QVariant(false) << QVariant(false) << Qt::CaseInsensitive << -0; |
3325 | QTest::newRow(dataTag: "bool >" ) << QVariant(true) << QVariant(false) << Qt::CaseInsensitive << 1; |
3326 | |
3327 | // char (who uses these??) |
3328 | QTest::newRow(dataTag: "char <" ) << QVariant(QChar('a')) << QVariant(QChar('b')) << Qt::CaseInsensitive << -1; |
3329 | QTest::newRow(dataTag: "char < ci" ) << QVariant(QChar('A')) << QVariant(QChar('b')) << Qt::CaseInsensitive << -1; |
3330 | QTest::newRow(dataTag: "char < ci 2" ) << QVariant(QChar('a')) << QVariant(QChar('B')) << Qt::CaseInsensitive << -1; |
3331 | QTest::newRow(dataTag: "char < cs" ) << QVariant(QChar('a')) << QVariant(QChar('b')) << Qt::CaseSensitive << -1; |
3332 | QTest::newRow(dataTag: "char < cs" ) << QVariant(QChar('A')) << QVariant(QChar('b')) << Qt::CaseSensitive << -1; |
3333 | |
3334 | QTest::newRow(dataTag: "char = ci" ) << QVariant(QChar('a')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 0; |
3335 | QTest::newRow(dataTag: "char = ci 2" ) << QVariant(QChar('a')) << QVariant(QChar('A')) << Qt::CaseInsensitive << 0; |
3336 | QTest::newRow(dataTag: "char = ci 3" ) << QVariant(QChar('A')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 0; |
3337 | QTest::newRow(dataTag: "char = ci 4" ) << QVariant(QChar('A')) << QVariant(QChar('A')) << Qt::CaseInsensitive << 0; |
3338 | QTest::newRow(dataTag: "char = cs" ) << QVariant(QChar('a')) << QVariant(QChar('a')) << Qt::CaseSensitive << 0; |
3339 | QTest::newRow(dataTag: "char = cs 2" ) << QVariant(QChar('A')) << QVariant(QChar('A')) << Qt::CaseSensitive << 0; |
3340 | |
3341 | QTest::newRow(dataTag: "char >" ) << QVariant(QChar('b')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 1; |
3342 | QTest::newRow(dataTag: "char > ci" ) << QVariant(QChar('b')) << QVariant(QChar('A')) << Qt::CaseInsensitive << 1; |
3343 | QTest::newRow(dataTag: "char > ci 2" ) << QVariant(QChar('B')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 1; |
3344 | QTest::newRow(dataTag: "char > cs" ) << QVariant(QChar('b')) << QVariant(QChar('a')) << Qt::CaseSensitive << 1; |
3345 | QTest::newRow(dataTag: "char > cs" ) << QVariant(QChar('b')) << QVariant(QChar('A')) << Qt::CaseSensitive << 1; |
3346 | |
3347 | // Some numeric types |
3348 | // uint |
3349 | QTest::newRow(dataTag: "uint < boundary" ) << QVariant(uint(1)) << QVariant(uint(-1)) << Qt::CaseInsensitive << -1; |
3350 | QTest::newRow(dataTag: "uint <" ) << QVariant(uint(1)) << QVariant(uint(2)) << Qt::CaseInsensitive << -1; |
3351 | QTest::newRow(dataTag: "uint =" ) << QVariant(uint(2)) << QVariant(uint(2)) << Qt::CaseInsensitive << 0; |
3352 | QTest::newRow(dataTag: "uint = 0" ) << QVariant(uint(0)) << QVariant(uint(0)) << Qt::CaseInsensitive << 0; |
3353 | QTest::newRow(dataTag: "uint = boundary" ) << QVariant(uint(-1)) << QVariant(uint(-1)) << Qt::CaseInsensitive << 0; |
3354 | QTest::newRow(dataTag: "uint >" ) << QVariant(uint(5)) << QVariant(uint(2)) << Qt::CaseInsensitive << 1; |
3355 | QTest::newRow(dataTag: "uint > boundary" ) << QVariant(uint(-1)) << QVariant(uint(2)) << Qt::CaseInsensitive << 1; // boundary |
3356 | |
3357 | // int (hmm, signed 32 bit assumed) |
3358 | QTest::newRow(dataTag: "int < boundary" ) << QVariant(int(0x80000000)) << QVariant(int(0x7fffffff)) << Qt::CaseInsensitive << -1; |
3359 | QTest::newRow(dataTag: "int <" ) << QVariant(int(1)) << QVariant(int(2)) << Qt::CaseInsensitive << -1; |
3360 | QTest::newRow(dataTag: "int =" ) << QVariant(int(2)) << QVariant(int(2)) << Qt::CaseInsensitive << 0; |
3361 | QTest::newRow(dataTag: "int = 0" ) << QVariant(int(0)) << QVariant(int(0)) << Qt::CaseInsensitive << 0; |
3362 | QTest::newRow(dataTag: "int = boundary" ) << QVariant(int(0x80000000)) << QVariant(int(0x80000000)) << Qt::CaseInsensitive << 0; |
3363 | QTest::newRow(dataTag: "int >" ) << QVariant(int(5)) << QVariant(int(2)) << Qt::CaseInsensitive << 1; |
3364 | QTest::newRow(dataTag: "int > boundary" ) << QVariant(int(0x7fffffff)) << QVariant(int(0x80000000)) << Qt::CaseInsensitive << 1; // boundary |
3365 | |
3366 | // ulonglong |
3367 | QTest::newRow(dataTag: "ulonglong < boundary" ) << QVariant(qulonglong(1)) << QVariant(qulonglong(-1)) << Qt::CaseInsensitive << -1; |
3368 | QTest::newRow(dataTag: "ulonglong <" ) << QVariant(qulonglong(1)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << -1; |
3369 | QTest::newRow(dataTag: "ulonglong =" ) << QVariant(qulonglong(2)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << 0; |
3370 | QTest::newRow(dataTag: "ulonglong = 0" ) << QVariant(qulonglong(0)) << QVariant(qulonglong(0)) << Qt::CaseInsensitive << 0; |
3371 | QTest::newRow(dataTag: "ulonglong = boundary" ) << QVariant(qulonglong(-1)) << QVariant(qulonglong(-1)) << Qt::CaseInsensitive << 0; |
3372 | QTest::newRow(dataTag: "ulonglong >" ) << QVariant(qulonglong(5)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << 1; |
3373 | QTest::newRow(dataTag: "ulonglong > boundary" ) << QVariant(qulonglong(-1)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << 1; // boundary |
3374 | |
3375 | // longlong |
3376 | QTest::newRow(dataTag: "longlong < boundary" ) << QVariant(qlonglong(0x8000000000000000LL)) << QVariant(qlonglong(0x7fffffffffffffffLL)) << Qt::CaseInsensitive << -1; |
3377 | QTest::newRow(dataTag: "longlong <" ) << QVariant(qlonglong(1)) << QVariant(qlonglong(2)) << Qt::CaseInsensitive << -1; |
3378 | QTest::newRow(dataTag: "longlong =" ) << QVariant(qlonglong(2)) << QVariant(qlonglong(2)) << Qt::CaseInsensitive << 0; |
3379 | QTest::newRow(dataTag: "longlong = 0" ) << QVariant(qlonglong(0)) << QVariant(qlonglong(0)) << Qt::CaseInsensitive << 0; |
3380 | QTest::newRow(dataTag: "longlong = boundary" ) << QVariant(qlonglong(0x8000000000000000LL)) << QVariant(qlonglong(0x8000000000000000LL)) << Qt::CaseInsensitive << 0; |
3381 | QTest::newRow(dataTag: "longlong >" ) << QVariant(qlonglong(5)) << QVariant(qlonglong(2)) << Qt::CaseInsensitive << 1; |
3382 | QTest::newRow(dataTag: "longlong > boundary" ) << QVariant(qlonglong(0x7fffffffffffffffLL)) << QVariant(qlonglong(0x8000000000000000LL)) << Qt::CaseInsensitive << 1; // boundary |
3383 | |
3384 | // double (hmm, skips NaNs etc) |
3385 | QTest::newRow(dataTag: "double < inf 2" ) << QVariant(-qInf()) << QVariant(qInf()) << Qt::CaseInsensitive << -1; |
3386 | QTest::newRow(dataTag: "double < inf" ) << QVariant(1.0) << QVariant(qInf()) << Qt::CaseInsensitive << -1; |
3387 | QTest::newRow(dataTag: "double <" ) << QVariant(1.0) << QVariant(2.0) << Qt::CaseInsensitive << -1; |
3388 | QTest::newRow(dataTag: "double =" ) << QVariant(2.0) << QVariant(2.0) << Qt::CaseInsensitive << 0; |
3389 | QTest::newRow(dataTag: "double = 0" ) << QVariant(0.0) << QVariant(0.0) << Qt::CaseInsensitive << 0; |
3390 | QTest::newRow(dataTag: "double = inf" ) << QVariant(qInf()) << QVariant(qInf()) << Qt::CaseInsensitive << 0; |
3391 | QTest::newRow(dataTag: "double >" ) << QVariant(5.0) << QVariant(2.0) << Qt::CaseInsensitive << 1; |
3392 | QTest::newRow(dataTag: "double > inf" ) << QVariant(qInf()) << QVariant(5.0) << Qt::CaseInsensitive << 1; |
3393 | QTest::newRow(dataTag: "double > inf 2" ) << QVariant(0.0) << QVariant(-qInf()) << Qt::CaseInsensitive << 1; |
3394 | QTest::newRow(dataTag: "double > inf 3" ) << QVariant(qInf()) << QVariant(-qInf()) << Qt::CaseInsensitive << 1; |
3395 | |
3396 | // strings |
3397 | QTest::newRow(dataTag: "string <" ) << QVariant(QString("a" )) << QVariant(QString("b" )) << Qt::CaseInsensitive << -1; |
3398 | QTest::newRow(dataTag: "string <" ) << QVariant(QString("a" )) << QVariant(QString("B" )) << Qt::CaseInsensitive << -1; |
3399 | QTest::newRow(dataTag: "string <" ) << QVariant(QString("A" )) << QVariant(QString("b" )) << Qt::CaseInsensitive << -1; |
3400 | QTest::newRow(dataTag: "string <" ) << QVariant(QString("A" )) << QVariant(QString("B" )) << Qt::CaseInsensitive << -1; |
3401 | QTest::newRow(dataTag: "string < cs" ) << QVariant(QString("a" )) << QVariant(QString("b" )) << Qt::CaseSensitive << -1; |
3402 | QTest::newRow(dataTag: "string < cs 2" ) << QVariant(QString("A" )) << QVariant(QString("b" )) << Qt::CaseSensitive << -1; |
3403 | |
3404 | QTest::newRow(dataTag: "string < length" ) << QVariant(QString("a" )) << QVariant(QString("aa" )) << Qt::CaseInsensitive << -1; |
3405 | QTest::newRow(dataTag: "string < length cs" ) << QVariant(QString("a" )) << QVariant(QString("aa" )) << Qt::CaseSensitive << -1; |
3406 | QTest::newRow(dataTag: "string < length 2" ) << QVariant(QString("a" )) << QVariant(QString("ba" )) << Qt::CaseInsensitive << -1; |
3407 | QTest::newRow(dataTag: "string < length cs 2" ) << QVariant(QString("a" )) << QVariant(QString("ba" )) << Qt::CaseSensitive << -1; |
3408 | |
3409 | QTest::newRow(dataTag: "string aa < b" ) << QVariant(QString("aa" )) << QVariant(QString("b" )) << Qt::CaseInsensitive << -1; |
3410 | QTest::newRow(dataTag: "string aa < b cs" ) << QVariant(QString("aa" )) << QVariant(QString("b" )) << Qt::CaseSensitive << -1; |
3411 | |
3412 | QTest::newRow(dataTag: "string '' < a" ) << QVariant(QString("" )) << QVariant(QString("aa" )) << Qt::CaseInsensitive << -1; |
3413 | QTest::newRow(dataTag: "string '' < aa cs" ) << QVariant(QString("" )) << QVariant(QString("aa" )) << Qt::CaseSensitive << -1; |
3414 | QTest::newRow(dataTag: "string 0 < a" ) << QVariant(QString()) << QVariant(QString("aa" )) << Qt::CaseInsensitive << -1; |
3415 | QTest::newRow(dataTag: "string 0 < aa cs" ) << QVariant(QString()) << QVariant(QString("aa" )) << Qt::CaseSensitive << -1; |
3416 | |
3417 | QTest::newRow(dataTag: "string '' = ''" ) << QVariant(QString("" )) << QVariant(QString("" )) << Qt::CaseInsensitive << 0; |
3418 | QTest::newRow(dataTag: "string '' = '' cs" ) << QVariant(QString("" )) << QVariant(QString("" )) << Qt::CaseSensitive << 0; |
3419 | QTest::newRow(dataTag: "string 0 = 0" ) << QVariant(QString()) << QVariant(QString()) << Qt::CaseInsensitive << 0; |
3420 | QTest::newRow(dataTag: "string 0 = 0 cs" ) << QVariant(QString()) << QVariant(QString()) << Qt::CaseSensitive << 0; |
3421 | QTest::newRow(dataTag: "string a = a" ) << QVariant(QString("a" )) << QVariant(QString("a" )) << Qt::CaseInsensitive << 0; |
3422 | QTest::newRow(dataTag: "string a = a cs" ) << QVariant(QString("a" )) << QVariant(QString("a" )) << Qt::CaseSensitive << 0; |
3423 | |
3424 | // Stringlists |
3425 | // {} < {"a"} < {"aa"} < {"aa","bb"} < {"aa", "cc"} < {"bb"} |
3426 | |
3427 | QStringList empty; |
3428 | QStringList listA("a" ); |
3429 | QStringList listAA("aa" ); |
3430 | QStringList listAABB; |
3431 | listAABB << "aa" << "bb" ; |
3432 | QStringList listAACC; |
3433 | listAACC << "aa" << "cc" ; |
3434 | QStringList listBB; |
3435 | listBB << "bb" ; |
3436 | QStringList listCCAA; |
3437 | listCCAA << "cc" << "aa" ; |
3438 | QStringList listA2("A" ); |
3439 | QStringList listAA2("AA" ); |
3440 | |
3441 | QTest::newRow(dataTag: "stringlist {} < {a}" ) << QVariant(empty) << QVariant(listA) << Qt::CaseInsensitive << -1; |
3442 | QTest::newRow(dataTag: "stringlist {} < {a} cs" ) << QVariant(empty) << QVariant(listA) << Qt::CaseSensitive << -1; |
3443 | QTest::newRow(dataTag: "stringlist {} < {A}" ) << QVariant(empty) << QVariant(listA2) << Qt::CaseInsensitive << -1; |
3444 | QTest::newRow(dataTag: "stringlist {} < {A} cs" ) << QVariant(empty) << QVariant(listA2) << Qt::CaseSensitive << -1; |
3445 | |
3446 | QTest::newRow(dataTag: "stringlist {a} < {aa}" ) << QVariant(listA) << QVariant(listAA) << Qt::CaseInsensitive << -1; |
3447 | QTest::newRow(dataTag: "stringlist {a} < {aa} cs" ) << QVariant(listA) << QVariant(listAA) << Qt::CaseSensitive << -1; |
3448 | QTest::newRow(dataTag: "stringlist {a} < {AA}" ) << QVariant(listA) << QVariant(listAA2) << Qt::CaseInsensitive << -1; |
3449 | QTest::newRow(dataTag: "stringlist {a} < {AA} cs" ) << QVariant(listA) << QVariant(listAA2) << Qt::CaseSensitive << -1; |
3450 | |
3451 | QTest::newRow(dataTag: "stringlist {A} < {aa,bb}" ) << QVariant(listA2) << QVariant(listAABB) << Qt::CaseInsensitive << -1; |
3452 | QTest::newRow(dataTag: "stringlist {A} < {aa,bb} cs" ) << QVariant(listA2) << QVariant(listAABB) << Qt::CaseSensitive << -1; |
3453 | QTest::newRow(dataTag: "stringlist {aa} < {aa,bb}" ) << QVariant(listAA) << QVariant(listAABB) << Qt::CaseInsensitive << -1; |
3454 | QTest::newRow(dataTag: "stringlist {aa} < {aa,bb} cs" ) << QVariant(listAA) << QVariant(listAABB) << Qt::CaseSensitive << -1; |
3455 | |
3456 | QTest::newRow(dataTag: "stringlist {aa,bb} < {aa,cc}" ) << QVariant(listAABB) << QVariant(listAACC) << Qt::CaseInsensitive << -1; |
3457 | QTest::newRow(dataTag: "stringlist {aa,bb} < {aa,cc} cs" ) << QVariant(listAABB) << QVariant(listAACC) << Qt::CaseSensitive << -1; |
3458 | |
3459 | QTest::newRow(dataTag: "stringlist {aa,cc} < {bb}" ) << QVariant(listAACC) << QVariant(listBB) << Qt::CaseInsensitive << -1; |
3460 | QTest::newRow(dataTag: "stringlist {aa,cc} < {bb} cs" ) << QVariant(listAACC) << QVariant(listBB) << Qt::CaseSensitive << -1; |
3461 | |
3462 | // equality |
3463 | QTest::newRow(dataTag: "stringlist {} = {}" ) << QVariant(empty) << QVariant(empty) << Qt::CaseInsensitive << 0; |
3464 | QTest::newRow(dataTag: "stringlist {} = {} cs" ) << QVariant(empty) << QVariant(empty) << Qt::CaseSensitive << 0; |
3465 | QTest::newRow(dataTag: "stringlist {aa} = {aa}" ) << QVariant(listAA) << QVariant(listAA) << Qt::CaseInsensitive << 0; |
3466 | QTest::newRow(dataTag: "stringlist {aa} = {AA}" ) << QVariant(listAA) << QVariant(listAA2) << Qt::CaseInsensitive << 0; |
3467 | QTest::newRow(dataTag: "stringlist {aa} = {aa} cs" ) << QVariant(listAA) << QVariant(listAA) << Qt::CaseSensitive << 0; |
3468 | |
3469 | // Times |
3470 | QTime t0; |
3471 | QTime t1(0,0,0,0); |
3472 | QTime t2(0,59,0,0); |
3473 | QTime t3(1,0,0,0); |
3474 | QTime t4(23,59,59,999); |
3475 | |
3476 | QTest::newRow(dataTag: "times t0 < t1" ) << QVariant(t0) << QVariant(t1) << Qt::CaseInsensitive << -1; |
3477 | QTest::newRow(dataTag: "times t1 < t2" ) << QVariant(t1) << QVariant(t2) << Qt::CaseInsensitive << -1; |
3478 | QTest::newRow(dataTag: "times t2 < t3" ) << QVariant(t2) << QVariant(t3) << Qt::CaseInsensitive << -1; |
3479 | QTest::newRow(dataTag: "times t3 < t4" ) << QVariant(t3) << QVariant(t4) << Qt::CaseInsensitive << -1; |
3480 | QTest::newRow(dataTag: "times t0 = t0" ) << QVariant(t0) << QVariant(t0) << Qt::CaseInsensitive << 0; |
3481 | QTest::newRow(dataTag: "times t4 = t4" ) << QVariant(t4) << QVariant(t4) << Qt::CaseInsensitive << 0; |
3482 | |
3483 | // Dates |
3484 | QDate d0; |
3485 | QDate d1 = QDate::fromJulianDay(jd_: 1); |
3486 | QDate d2(1,1,1); |
3487 | QDate d3(2011,6,9); |
3488 | QDate d4 = QDate::fromJulianDay(jd_: 0x7fffffff); |
3489 | QDate d5 = QDate::fromJulianDay(jd_: 0x80000000); |
3490 | QDate d6 = QDate::fromJulianDay(jd_: 0xffffffff); |
3491 | |
3492 | QTest::newRow(dataTag: "dates d0 < d1" ) << QVariant(d0) << QVariant(d1) << Qt::CaseInsensitive << -1; |
3493 | QTest::newRow(dataTag: "dates d1 < d2" ) << QVariant(d1) << QVariant(d2) << Qt::CaseInsensitive << -1; |
3494 | QTest::newRow(dataTag: "dates d2 < d3" ) << QVariant(d2) << QVariant(d3) << Qt::CaseInsensitive << -1; |
3495 | QTest::newRow(dataTag: "dates d3 < d4" ) << QVariant(d3) << QVariant(d4) << Qt::CaseInsensitive << -1; |
3496 | QTest::newRow(dataTag: "dates d4 < d5" ) << QVariant(d4) << QVariant(d5) << Qt::CaseInsensitive << -1; |
3497 | QTest::newRow(dataTag: "dates d5 < d6" ) << QVariant(d5) << QVariant(d6) << Qt::CaseInsensitive << -1; |
3498 | QTest::newRow(dataTag: "dates d0 < d6" ) << QVariant(d0) << QVariant(d6) << Qt::CaseInsensitive << -1; |
3499 | QTest::newRow(dataTag: "dates d1 < d6" ) << QVariant(d1) << QVariant(d6) << Qt::CaseInsensitive << -1; |
3500 | QTest::newRow(dataTag: "dates d0 = d0" ) << QVariant(d0) << QVariant(d0) << Qt::CaseInsensitive << 0; |
3501 | QTest::newRow(dataTag: "dates d1 = d1" ) << QVariant(d1) << QVariant(d1) << Qt::CaseInsensitive << 0; |
3502 | QTest::newRow(dataTag: "dates d2 = d2" ) << QVariant(d2) << QVariant(d2) << Qt::CaseInsensitive << 0; |
3503 | QTest::newRow(dataTag: "dates d3 = d3" ) << QVariant(d3) << QVariant(d3) << Qt::CaseInsensitive << 0; |
3504 | QTest::newRow(dataTag: "dates d4 = d4" ) << QVariant(d4) << QVariant(d4) << Qt::CaseInsensitive << 0; |
3505 | QTest::newRow(dataTag: "dates d5 = d5" ) << QVariant(d5) << QVariant(d5) << Qt::CaseInsensitive << 0; |
3506 | QTest::newRow(dataTag: "dates d6 = d6" ) << QVariant(d6) << QVariant(d6) << Qt::CaseInsensitive << 0; |
3507 | |
3508 | // DateTimes |
3509 | // Somewhat limited testing here |
3510 | QDateTime dt0; |
3511 | QDateTime dt1(d1, t1); |
3512 | QDateTime dt2(d1, t2); |
3513 | QDateTime dt3(d4, t4); |
3514 | QDateTime dt4(d5, t1); |
3515 | QDateTime dt5(d6, t4); // end of the universe |
3516 | |
3517 | // Note: this test used to verify that null QDateTime compared less than a non-null date prior to 1AD |
3518 | // The current Qt behavior is to compare null as the UNIX epoch, so we will follow that |
3519 | QTest::newRow(dataTag: "datetimes dt0 > dt1" ) << QVariant(dt0) << QVariant(dt1) << Qt::CaseInsensitive << 1; |
3520 | QTest::newRow(dataTag: "datetimes dt1 < dt2" ) << QVariant(dt1) << QVariant(dt2) << Qt::CaseInsensitive << -1; |
3521 | QTest::newRow(dataTag: "datetimes dt2 < dt3" ) << QVariant(dt2) << QVariant(dt3) << Qt::CaseInsensitive << -1; |
3522 | QTest::newRow(dataTag: "datetimes dt3 < dt4" ) << QVariant(dt3) << QVariant(dt4) << Qt::CaseInsensitive << -1; |
3523 | QTest::newRow(dataTag: "datetimes dt4 < dt5" ) << QVariant(dt4) << QVariant(dt5) << Qt::CaseInsensitive << -1; |
3524 | QTest::newRow(dataTag: "datetimes dt0 < dt5" ) << QVariant(dt0) << QVariant(dt5) << Qt::CaseInsensitive << -1; |
3525 | QTest::newRow(dataTag: "datetimes dt1 < dt5" ) << QVariant(dt1) << QVariant(dt5) << Qt::CaseInsensitive << -1; |
3526 | QTest::newRow(dataTag: "datetimes dt0 = dt0" ) << QVariant(dt0) << QVariant(dt0) << Qt::CaseInsensitive << 0; |
3527 | QTest::newRow(dataTag: "datetimes dt1 = dt1" ) << QVariant(dt1) << QVariant(dt1) << Qt::CaseInsensitive << 0; |
3528 | QTest::newRow(dataTag: "datetimes dt2 = dt2" ) << QVariant(dt2) << QVariant(dt2) << Qt::CaseInsensitive << 0; |
3529 | QTest::newRow(dataTag: "datetimes dt3 = dt3" ) << QVariant(dt3) << QVariant(dt3) << Qt::CaseInsensitive << 0; |
3530 | QTest::newRow(dataTag: "datetimes dt4 = dt4" ) << QVariant(dt4) << QVariant(dt4) << Qt::CaseInsensitive << 0; |
3531 | QTest::newRow(dataTag: "datetimes dt5 = dt5" ) << QVariant(dt5) << QVariant(dt5) << Qt::CaseInsensitive << 0; |
3532 | } |
3533 | |
3534 | QTEST_MAIN(tst_QContactManager) |
3535 | #include "tst_qcontactmanager.moc" |
3536 | |