1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the test suite of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
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 Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
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 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#define QT_STATICPLUGIN
44
#include <QtTest/QtTest>
46
#include <QtCore/qnumeric.h>
49
#include "qcontactmanagerdataholder.h"
50
#include "jsondbprocess.h"
51
#include "qcontactidmock.h"
53
#if defined(USE_VERSIT_PLZ)
54
// This makes it easier to create specific QContacts
55
#include <QtVersit/qversitcontactimporter.h>
56
#include <QtVersit/qversitdocument.h>
57
#include <QtVersit/qversitreader.h>
58
QTVERSIT_USE_NAMESPACE
61
QTCONTACTS_USE_NAMESPACE
63
#define QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(params) params.remove(QString::fromLatin1(QTCONTACTS_VERSION_NAME)); \
64
params.remove(QString::fromLatin1(QTCONTACTS_IMPLEMENTATION_VERSION_NAME))
66
#define QTRY_COMPARE_SIGNALS_LOCALID_COUNT(__signalSpy, __expectedCount) \
68
int __spiedSigCount = 0; \
69
const int __step = 50; \
70
const int __timeout = 5000; \
71
for (int __i = 0; __i < __timeout; __i+=__step) { \
72
/* accumulate added from signals */ \
73
__spiedSigCount = 0; \
74
const QList<QList<QVariant> > __spiedSignals = __signalSpy; \
75
foreach (const QList<QVariant> &__arguments, __spiedSignals) { \
76
foreach (QContactId __localId, __arguments.first().value<QList<QContactId> >()) { \
77
QVERIFY(!(__localId.isNull())); \
81
if(__spiedSigCount == __expectedCount) { \
84
QTest::qWait(__step); \
86
QCOMPARE(__spiedSigCount, __expectedCount); \
89
//TESTED_COMPONENT=src/contacts
91
// to get QFETCH to work with the template expression...
92
typedef QMap<QString,QString> tst_QContactManager_QStringMap;
93
Q_DECLARE_METATYPE(tst_QContactManager_QStringMap)
94
Q_DECLARE_METATYPE(QList<QContactId>)
96
/* A class that no backend can support */
97
class UnsupportedMetatype {
100
Q_DECLARE_METATYPE(UnsupportedMetatype)
101
Q_DECLARE_METATYPE(QContact)
102
Q_DECLARE_METATYPE(QContactManager::Error)
103
Q_DECLARE_METATYPE(Qt::CaseSensitivity)
105
class tst_QContactManager : public QObject
110
tst_QContactManager();
111
virtual ~tst_QContactManager();
114
void dumpContactDifferences(const QContact& a, const QContact& b);
115
void dumpContact(const QContact &c);
116
void dumpContacts(QContactManager *cm);
117
bool isSuperset(const QContact& ca, const QContact& cb);
118
QList<QContactDetail> removeAllDefaultDetails(const QList<QContactDetail>& details);
119
void addManagers(); // add standard managers to the data
120
QContact createContact(QString firstName, QString lastName, QString phoneNumber);
121
void saveContactName(QContact *contact,QContactName *contactName, const QString &name) const;
123
JsonDbProcess m_jsondbProcess;
125
QScopedPointer<QContactManagerDataHolder> managerDataHolder;
129
void cleanupTestCase();
133
void doDump_data() {addManagers();}
135
/* Special test with special data */
137
void nameSynthesis();
139
/* Tests that are run on all managers */
141
void nullIdOperations();
147
void observerDeletion();
148
void signalEmission();
149
void actionPreferences();
150
void selfContactId();
152
void relationships();
155
void compareVariant();
157
#if defined(USE_VERSIT_PLZ)
159
void partialSave_data() {addManagers();}
162
/* Tests that take no data */
163
void errorStayingPut();
165
void invalidManager();
166
void memoryManager();
167
void overrideManager();
170
void lazyConnections();
171
void testInterSectionOfIdFilters();
172
void testInterSectionOfIdAndDetailFilters();
174
/* Special test with special data */
175
void uriParsing_data();
176
void nameSynthesis_data();
177
void compareVariant_data();
179
/* Tests that are run on all managers */
180
void metadata_data() {addManagers();}
181
void nullIdOperations_data() {addManagers();}
182
void add_data() {addManagers();}
183
void update_data() {addManagers();}
184
void remove_data() {addManagers();}
185
void addAndUpdate_data() {addManagers();}
186
void batch_data() {addManagers();}
187
void signalEmission_data() {addManagers();}
188
void actionPreferences_data() {addManagers();}
189
void selfContactId_data() {addManagers();}
190
void detailOrders_data() {addManagers();}
191
void relationships_data() {addManagers();}
192
void contactType_data() {addManagers();}
193
void lateDeletion_data() {addManagers();}
194
void testInterSectionOfIdFilters_data() {addManagers();}
195
void testInterSectionOfIdAndDetailFilters_data() {addManagers();}
198
// Helper class that connects to a signal on ctor, and disconnects on dtor
199
class QTestSignalSink : public QObject {
202
// signal and object must remain valid for the lifetime
203
QTestSignalSink(QObject *object, const char *signal)
204
: mObject(object), mSignal(signal)
206
connect(object, signal, this, SLOT(ignored()));
211
disconnect(mObject, mSignal, this, SLOT(ignored()));
219
const char * const mSignal;
223
static uint qHash(const QMetaMethod &m)
225
return qHash(m.methodIndex());
229
/* Two backends for testing lazy signal connections */
230
class QContactLazyEngine2 : public QContactManagerEngine
233
QContactLazyEngine2() {}
234
QString managerName() const {return "lazy2";}
237
int managerVersion() const {return 0;}
239
void connectNotify(const QMetaMethod &signal)
241
connectionCounts[signal]++;
243
void disconnectNotify(const QMetaMethod &signal)
245
connectionCounts[signal]--;
248
static QHash<QMetaMethod, int> connectionCounts; // signal to count
250
QHash<QMetaMethod, int> QContactLazyEngine2::connectionCounts;
252
class QContactLazyEngine : public QContactManagerEngine
255
QContactLazyEngine() {}
256
QString managerName() const {
260
int managerVersion() const {return 0;}
262
void connectNotify(const QMetaMethod &signal)
264
connectionCounts[signal]++;
266
void disconnectNotify(const QMetaMethod &signal)
268
connectionCounts[signal]--;
270
static QHash<QMetaMethod, int> connectionCounts; // signal to count
272
QHash<QMetaMethod, int> QContactLazyEngine::connectionCounts;
274
/* Static lazy engine factory */
275
class LazyEngineFactory : public QContactManagerEngineFactory
278
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QContactManagerEngineFactoryInterface" FILE "lazy.json")
280
QContactManagerEngine* engine(const QMap<QString, QString>& parameters, QContactManager::Error* error);
281
QContactEngineId* createContactEngineId(const QMap<QString, QString>& parameters, const QString& idString) const;
282
QString managerName() const {return "testlazy";}
285
QContactManagerEngine* LazyEngineFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
287
// Return one or the other
289
if (parameters.value("version") == QString("1"))
290
return new QContactLazyEngine();
292
return new QContactLazyEngine2();
295
QContactEngineId* LazyEngineFactory::createContactEngineId(const QMap<QString, QString>& parameters, const QString& idString) const
299
return new QContactIdMock("",1);
302
tst_QContactManager::tst_QContactManager()
306
tst_QContactManager::~tst_QContactManager()
310
void tst_QContactManager::initTestCase()
312
// Start JsonDb daemon if needed
313
if (QContactManager::availableManagers().contains("jsondb")) {
314
QString partitions_json = QFINDTESTDATA("partitions.json");
315
QVERIFY2(!partitions_json.isEmpty(), "partitions.json file is missing");
316
QVERIFY2(m_jsondbProcess.start(partitions_json), "Failed to start JsonDb process");
319
managerDataHolder.reset(new QContactManagerDataHolder());
321
/* Make sure these other test plugins are NOT loaded by default */
322
// These are now removed from the list of managers in addManagers()
323
//QVERIFY(!QContactManager::availableManagers().contains("testdummy"));
324
//QVERIFY(!QContactManager::availableManagers().contains("teststaticdummy"));
325
//QVERIFY(!QContactManager::availableManagers().contains("maliciousplugin"));
328
void tst_QContactManager::cleanupTestCase()
330
managerDataHolder.reset(0);
332
if (QContactManager::availableManagers().contains("jsondb"))
333
m_jsondbProcess.terminate();
336
void tst_QContactManager::dumpContactDifferences(const QContact& ca, const QContact& cb)
338
// Try to narrow down the differences
342
QContactName n1 = a.detail(QContactName::Type);
343
QContactName n2 = b.detail(QContactName::Type);
345
// Check the name components in more detail
346
QCOMPARE(n1.firstName(), n2.firstName());
347
QCOMPARE(n1.middleName(), n2.middleName());
348
QCOMPARE(n1.lastName(), n2.lastName());
349
QCOMPARE(n1.prefix(), n2.prefix());
350
QCOMPARE(n1.suffix(), n2.suffix());
352
// Now look at the rest
353
QList<QContactDetail> aDetails = a.details();
354
QList<QContactDetail> bDetails = b.details();
356
// They can be in any order, so loop
357
// First remove any matches
358
foreach(QContactDetail d, aDetails) {
359
foreach(QContactDetail d2, bDetails) {
368
// Now dump the extra details that were unmatched in A (note that Type is always present).
369
// We ignore timestamp since it can get autogenerated too
370
aDetails = a.details();
371
bDetails = b.details();
372
foreach(QContactDetail d, aDetails) {
373
if (d.type() != QContactType::Type && d.type() != QContactTimestamp::Type)
374
qDebug() << "A contact had extra detail:" << d.type() << d.values();
377
foreach(QContactDetail d, bDetails) {
378
if (d.type() != QContactType::Type && d.type() != QContactTimestamp::Type)
379
qDebug() << "B contact had extra detail:" << d.type() << d.values();
382
if (a.type() != b.type()) {
383
qDebug() << "A contact type =" << a.type();
384
qDebug() << "B contact type =" << b.type();
388
bool tst_QContactManager::isSuperset(const QContact& ca, const QContact& cb)
390
// returns true if contact ca is a superset of contact cb
391
// we use this test instead of equality because dynamic information
392
// such as presence/location, and synthesized information such as (possibly) type,
393
// may differ between a contact in memory and the contact in the managed store.
397
QList<QContactDetail> aDetails = a.details();
398
QList<QContactDetail> bDetails = b.details();
400
// They can be in any order, so loop
401
// First remove any matches
402
foreach(QContactDetail d, aDetails) {
403
foreach(QContactDetail d2, bDetails) {
412
// Second remove any superset matches (eg, backend adds a field)
413
aDetails = a.details();
414
bDetails = b.details();
415
foreach (QContactDetail d, aDetails) {
416
foreach (QContactDetail d2, bDetails) {
417
if (d.type() == d2.type()) {
418
bool canRemove = true;
419
QMap<int, QVariant> d2map = d2.values();
420
foreach (int key, d2map.keys()) {
421
if (d.value(key) != d2.value(key)) {
422
// d can have _more_ keys than d2,
423
// but not _less_; and it cannot
430
// if we get to here, we can remove the details.
439
QList<QContactType::TypeValues> validTypes;
440
validTypes << QContactType::TypeContact << QContactType::TypeGroup;
441
// check for contact type updates
442
if (validTypes.contains(a.type()))
443
if (validTypes.contains(b.type()))
444
if (a.type() != b.type())
445
return false; // nonempty type is different.
447
// Now check to see if b has any details remaining; if so, a is not a superset.
448
// Note Type can never be removed.
449
if (b.details().size() > 1
450
|| (b.details().size() == 1 && (b.details().value(0).type() != QContactType::Type)))
455
void tst_QContactManager::dumpContact(const QContact& contact)
458
qDebug() << "Contact: " << contact.id();
459
QList<QContactDetail> details = contact.details();
460
foreach(QContactDetail d, details) {
461
qDebug() << " " << d.type() << ":";
462
qDebug() << " Vals:" << d.values();
466
void tst_QContactManager::dumpContacts(QContactManager *cm)
468
QList<QContactId> ids = cm->contactIds();
470
qDebug() << "There are" << ids.count() << "contacts in" << cm->managerUri();
472
foreach (QContactId id, ids) {
473
QContact c = cm->contact(id);
478
void tst_QContactManager::uriParsing_data()
480
QTest::addColumn<QString>("uri");
481
QTest::addColumn<bool>("good"); // is this a good uri or not
482
QTest::addColumn<QString>("manager");
483
QTest::addColumn<QMap<QString, QString> >("parameters");
485
QMap<QString, QString> inparameters;
486
inparameters.insert("foo", "bar");
487
inparameters.insert("bazflag", QString());
488
inparameters.insert("bar", "glob");
490
QMap<QString, QString> inparameters2;
491
inparameters2.insert("this has spaces", QString());
492
inparameters2.insert("and& an", " &");
493
inparameters2.insert("and an ", "=quals");
495
QTest::newRow("built") << QContactManager::buildUri("manager", inparameters) << true << "manager" << inparameters;
496
QTest::newRow("built with escaped parameters") << QContactManager::buildUri("manager", inparameters2) << true << "manager" << inparameters2;
497
QTest::newRow("no scheme") << "this should not split" << false << QString() << tst_QContactManager_QStringMap();
498
QTest::newRow("wrong scheme") << "invalidscheme:foo bar" << false << QString() << tst_QContactManager_QStringMap();
499
QTest::newRow("right scheme, no colon") << "qtcontacts" << false << QString() << tst_QContactManager_QStringMap();
500
QTest::newRow("no manager, colon, no params") << "qtcontacts::" << false << "manager" << tst_QContactManager_QStringMap();
501
QTest::newRow("yes manager, no colon, no params") << "qtcontacts:manager" << true << "manager" << tst_QContactManager_QStringMap();
502
QTest::newRow("yes manager, yes colon, no params") << "qtcontacts:manager:" << true << "manager"<< tst_QContactManager_QStringMap();
503
QTest::newRow("yes params") << "qtcontacts:manager:foo=bar&bazflag=&bar=glob" << true << "manager" << inparameters;
504
QTest::newRow("yes params but misformed") << "qtcontacts:manager:foo=bar&=gloo&bar=glob" << false << "manager" << inparameters;
505
QTest::newRow("yes params but misformed 2") << "qtcontacts:manager:=&=gloo&bar=glob" << false << "manager" << inparameters;
506
QTest::newRow("yes params but misformed 3") << "qtcontacts:manager:==" << false << "manager" << inparameters;
507
QTest::newRow("yes params but misformed 4") << "qtcontacts:manager:&&" << false << "manager" << inparameters;
508
QTest::newRow("yes params but misformed 5") << "qtcontacts:manager:&goo=bar" << false << "manager" << inparameters;
509
QTest::newRow("yes params but misformed 6") << "qtcontacts:manager:goo&bar" << false << "manager" << inparameters;
510
QTest::newRow("yes params but misformed 7") << "qtcontacts:manager:goo&bar&gob" << false << "manager" << inparameters;
511
QTest::newRow("yes params but misformed 8") << "qtcontacts:manager:==&&==&goo=bar" << false << "manager" << inparameters;
512
QTest::newRow("yes params but misformed 9") << "qtcontacts:manager:foo=bar=baz" << false << "manager" << inparameters;
513
QTest::newRow("yes params but misformed 10") << "qtcontacts:manager:foo=bar=baz=glob" << false << "manager" << inparameters;
514
QTest::newRow("no manager but yes params") << "qtcontacts::foo=bar&bazflag=&bar=glob" << false << QString() << inparameters;
515
QTest::newRow("no manager or params") << "qtcontacts::" << false << QString() << inparameters;
516
QTest::newRow("no manager or params or colon") << "qtcontacts:" << false << QString() << inparameters;
519
void tst_QContactManager::addManagers()
521
QTest::addColumn<QString>("uri");
523
QStringList managers = QContactManager::availableManagers();
525
/* Known one that will not pass */
526
managers.removeAll("invalid");
527
managers.removeAll("testdummy");
528
managers.removeAll("teststaticdummy");
529
managers.removeAll("maliciousplugin");
530
managers.removeAll("testlazy");
532
// "internal" engines
533
managers.removeAll("social");
534
managers.removeAll("simcard");
535
managers.removeAll("com.nokia.messaging.contacts.engines.mail.contactslookup");
538
foreach(QString mgr, managers) {
539
QMap<QString, QString> params;
540
QTest::newRow(QString("mgr='%1'").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params);
541
if (mgr == "memory") {
542
params.insert("id", "tst_QContactManager");
543
QTest::newRow(QString("mgr='%1', params").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params);
549
* Helper method for creating a QContact instance with name and phone number
552
QContact tst_QContactManager::createContact(
560
if (!firstName.isEmpty()) {
561
n.setFirstName(firstName);
563
if (!lastName.isEmpty()) {
564
n.setLastName(lastName);
567
contact.saveDetail(&n);
570
if (!phoneNumber.isEmpty()) {
571
QContactPhoneNumber ph;
572
ph.setNumber(phoneNumber);
573
contact.saveDetail(&ph);
579
void tst_QContactManager::saveContactName(QContact *contact, QContactName *contactName, const QString &name) const
581
contactName->setFirstName(name);
582
contactName->setLastName(name);
583
contact->saveDetail(contactName);
586
void tst_QContactManager::metadata()
588
// ensure that the backend is publishing its metadata (name / parameters / uri) correctly
589
QFETCH(QString, uri);
590
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
591
QVERIFY(QContactManager::buildUri(cm->managerName(), cm->managerParameters()) == cm->managerUri());
595
void tst_QContactManager::nullIdOperations()
597
QFETCH(QString, uri);
598
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
599
QVERIFY(!cm->removeContact(QContactId()));
600
QVERIFY(cm->error() == QContactManager::DoesNotExistError);
603
QContact c = cm->contact(QContactId());
604
QVERIFY(c.id() == QContactId());
605
QVERIFY(c.isEmpty());
606
QVERIFY(cm->error() == QContactManager::DoesNotExistError);
609
void tst_QContactManager::uriParsing()
611
QFETCH(QString, uri);
613
QFETCH(QString, manager);
614
QFETCH(tst_QContactManager_QStringMap, parameters);
617
QMap<QString, QString> outparameters;
622
QVERIFY(QContactManager::parseUri(uri, 0, 0)); // no out parms
625
QVERIFY(QContactManager::parseUri(uri, &outmanager, 0));
626
QCOMPARE(manager, outmanager);
627
QVERIFY(QContactManager::parseUri(uri, 0, &outparameters));
629
QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters);
631
QCOMPARE(parameters, outparameters);
634
outparameters.clear();
635
QVERIFY(QContactManager::parseUri(uri, &outmanager, &outparameters));
637
QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters);
639
QCOMPARE(manager, outmanager);
640
QCOMPARE(parameters, outparameters);
644
outparameters.clear();
645
QVERIFY(QContactManager::parseUri(uri, 0, 0) == false);
646
QVERIFY(QContactManager::parseUri(uri, &outmanager, 0) == false);
647
QVERIFY(outmanager.isEmpty());
648
QVERIFY(QContactManager::parseUri(uri, 0, &outparameters) == false);
649
QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters);
650
QVERIFY(outparameters.isEmpty());
652
/* make sure the in parameters don't change with a bad split */
653
outmanager = manager;
654
outparameters = parameters;
655
QVERIFY(QContactManager::parseUri(uri, &outmanager, 0) == false);
656
QCOMPARE(manager, outmanager);
657
QVERIFY(QContactManager::parseUri(uri, 0, &outparameters) == false);
658
QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters);
659
QCOMPARE(parameters, outparameters);
663
void tst_QContactManager::ctors()
665
/* test the different ctors to make sure we end up with the same uri */
666
QVERIFY(QContactManager::availableManagers().count() >= 1); // invalid + something else
667
QVERIFY(QContactManager::availableManagers().contains("invalid"));
668
QString defaultStore = QContactManager::availableManagers().value(0);
670
qDebug() << "Available managers:" << QContactManager::availableManagers();
672
QMap<QString, QString> randomParameters;
673
randomParameters.insert("something", "old");
674
randomParameters.insert("something...", "new");
675
randomParameters.insert("something ", "borrowed");
676
randomParameters.insert(" something", "blue");
680
QContactManager cm; // default
681
QContactManager cm2(defaultStore);
682
QContactManager cm3(defaultStore, QMap<QString, QString>());
684
QContactManager cm9b(0); // QObject* ctor, should be same as cm2 etc
685
QContactManager cm9c(&parent); // same as cm2 etc.
687
QScopedPointer<QContactManager> cm5(QContactManager::fromUri(QContactManager::buildUri(defaultStore, QMap<QString, QString>())));
688
QScopedPointer<QContactManager> cm6(QContactManager::fromUri(cm.managerUri())); // uri is not a name; should fail.
689
QScopedPointer<QContactManager> cm9(QContactManager::fromUri(QString(), &parent));
691
QVERIFY(cm9->parent() == &parent);
692
QVERIFY(cm9b.parent() == 0);
693
QVERIFY(cm9c.parent() == &parent);
696
/* OLD TEST WAS THIS: */
697
//QCOMPARE(cm.managerUri(), cm2.managerUri());
698
//QCOMPARE(cm.managerUri(), cm3.managerUri());
699
//QCOMPARE(cm.managerUri(), cm5->managerUri());
700
//QCOMPARE(cm.managerUri(), cm6->managerUri());
701
//QCOMPARE(cm.managerUri(), cm9->managerUri());
702
/* NEW TEST IS THIS: Test that the names of the managers are the same */
703
QCOMPARE(cm.managerName(), cm2.managerName());
704
QCOMPARE(cm.managerName(), cm3.managerName());
705
QCOMPARE(cm.managerName(), cm5->managerName());
706
QCOMPARE(cm.managerName(), cm6->managerName());
707
QCOMPARE(cm.managerName(), cm9->managerName());
708
QCOMPARE(cm.managerName(), cm9b.managerName());
709
QCOMPARE(cm.managerName(), cm9c.managerName());
711
/* Test that we get invalid stores when we do silly things */
712
QContactManager em("non existent");
713
QContactManager em2("non existent", QMap<QString, QString>());
714
QContactManager em3("memory", randomParameters);
716
/* Also invalid, since we don't have one of these anyway */
717
QScopedPointer<QContactManager> em4(QContactManager::fromUri("invalid uri"));
718
QScopedPointer<QContactManager> em5(QContactManager::fromUri(QContactManager::buildUri("nonexistent", QMap<QString, QString>())));
719
QScopedPointer<QContactManager> em6(QContactManager::fromUri(em3.managerUri()));
723
* Sets of stores that should be equivalent:
728
/* First some URI testing for equivalent stores */
729
QVERIFY(em.managerUri() == em2.managerUri());
730
QVERIFY(em.managerUri() == em5->managerUri());
731
QVERIFY(em.managerUri() == em4->managerUri());
732
QVERIFY(em2.managerUri() == em4->managerUri());
733
QVERIFY(em2.managerUri() == em5->managerUri());
734
QVERIFY(em4->managerUri() == em5->managerUri());
736
QVERIFY(em3.managerUri() == em6->managerUri());
738
/* Test the stores that should not be the same */
739
QVERIFY(em.managerUri() != em3.managerUri());
740
QVERIFY(em.managerUri() != em6->managerUri());
742
/* now the components */
743
QCOMPARE(em.managerName(), QString("invalid"));
744
QCOMPARE(em2.managerName(), QString("invalid"));
745
QCOMPARE(em3.managerName(), QString("memory"));
746
QCOMPARE(em4->managerName(), QString("invalid"));
747
QCOMPARE(em5->managerName(), QString("invalid"));
748
QCOMPARE(em6->managerName(), QString("memory"));
749
QCOMPARE(em.managerParameters(), tst_QContactManager_QStringMap());
750
QCOMPARE(em2.managerParameters(), tst_QContactManager_QStringMap());
751
QCOMPARE(em4->managerParameters(), tst_QContactManager_QStringMap());
752
QCOMPARE(em5->managerParameters(), tst_QContactManager_QStringMap());
753
QCOMPARE(em3.managerParameters(), em6->managerParameters()); // memory engine discards the given params, replaces with id.
756
// Finally test the platform specific engines are actually the defaults
757
#if defined(QT_JSONDB_ENABLED)
758
QCOMPARE(defaultStore, QString("jsondb"));
759
#elif !defined(QT_NO_JSONDB)
760
QCOMPARE(defaultStore, QString::fromLatin1("jsondb"));
762
QCOMPARE(defaultStore, QString("invalid"));
766
void tst_QContactManager::doDump()
768
// Only do this if it has been explicitly selected
769
if (QCoreApplication::arguments().contains("doDump")) {
770
QFETCH(QString, uri);
771
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
773
dumpContacts(cm.data());
777
Q_DECLARE_METATYPE(QVariant)
780
void tst_QContactManager::add()
782
QFETCH(QString, uri);
783
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
785
QContact alice = createContact("Alice", "inWonderland", "1234567");
786
int currCount = cm->contactIds().count();
787
QVERIFY(cm->saveContact(&alice));
788
QVERIFY(cm->error() == QContactManager::NoError);
790
QVERIFY(!alice.id().managerUri().isEmpty());
791
QVERIFY(!(alice.id().isNull()));
792
QCOMPARE(cm->contactIds().count(), currCount+1);
794
QContact added = cm->contact(alice.id());
795
QVERIFY(added.id() == alice.id());
797
if (!isSuperset(added, alice)) {
798
dumpContacts(cm.data());
799
dumpContactDifferences(added, alice);
800
QCOMPARE(added, alice);
803
// now a contact with many details of a particular definition
804
// if the detail is not unique it should then support minimum of two of the same kind
805
const int nrOfdetails = 2;
806
QContact veryContactable = createContact("Very", "Contactable", "");
807
for (int i = 0; i < nrOfdetails; i++) {
808
QString phnStr = QString::number(i);
809
QContactPhoneNumber vcphn;
810
vcphn.setNumber(phnStr);
811
QVERIFY(veryContactable.saveDetail(&vcphn));
814
// check that all the numbers were added successfully
815
QVERIFY(veryContactable.details(QContactPhoneNumber::Type).size() == nrOfdetails);
817
// check if it can be saved
818
QVERIFY(cm->saveContact(&veryContactable));
821
QContact retrievedContactable = cm->contact(veryContactable.id());
822
if (!isSuperset(retrievedContactable, veryContactable)) {
823
dumpContactDifferences(veryContactable, retrievedContactable);
824
QCOMPARE(veryContactable, retrievedContactable);
828
void tst_QContactManager::testInterSectionOfIdAndDetailFilters()
830
QFETCH(QString, uri);
831
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
833
//prepare filter data
834
QContact alice = createContact("Alice", "inWonderland", "1234567");
835
QVERIFY(cm->saveContact(&alice));
837
QContact john = createContact("John", "inFinland", "2345678");
838
QVERIFY(cm->saveContact(&john));
840
QContactIdFilter idFilter1;
841
QList<QContactId> contactIdList;
842
contactIdList.append(alice.id());
843
idFilter1.setIds(contactIdList);
845
QContactDetailFilter df;
846
df.setDetailType(QContactName::Type,QContactName::FieldFirstName);
847
df.setValue("Alice");
849
contactIdList.clear();
851
QContactIntersectionFilter isf;
852
isf.append(idFilter1);
855
//Intersection filter of a matching Idfilter and detailfilter
856
QList<QContact> contactList = cm->contacts(isf);
857
QCOMPARE(contactList.size(), 1);
859
contactIdList.clear();
861
//Intersection filter of a non matching Idfilter and detailfilter
866
contactList = cm->contacts(isf);
867
QCOMPARE(contactList.size(), 0);
870
void tst_QContactManager::testInterSectionOfIdFilters()
872
QFETCH(QString, uri);
873
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
875
//prepare filter data
876
QContact alice = createContact("Alice", "inWonderland", "1234567");
877
QVERIFY(cm->saveContact(&alice));
879
QContact john = createContact("John", "inFinland", "2345678");
880
QVERIFY(cm->saveContact(&john));
882
QContactIdFilter idFilter1;
883
QList<QContactId> contactIdList;
884
contactIdList.append(alice.id());
885
idFilter1.setIds(contactIdList);
887
QContactIdFilter idFilter2;
888
contactIdList.clear();
889
contactIdList.append(john.id());
890
idFilter2.setIds(contactIdList);
892
contactIdList.clear();
894
//Test intersection filter with two different idFilters
895
QContactIntersectionFilter isf;
896
isf.append(idFilter1);
897
isf.append(idFilter2);
899
QList<QContact> contactList = cm->contacts(idFilter1);
900
QCOMPARE(contactList.size(), 1);
901
QCOMPARE(contactList.at(0).id(), alice.id());
903
contactIdList.clear();
905
//When we intersect with two idFilters each having different
906
//contact Ids the result should be zero
907
contactList = cm->contacts(isf);
908
QCOMPARE(contactList.size(), 0);
911
//Test intersection filter with two idFilters
912
//each having same contactid as other the result should be 1
913
isf.remove(idFilter2);
914
contactIdList.append(alice.id());
915
idFilter2.setIds(contactIdList);
917
contactIdList.clear();
919
isf.append(idFilter2);
920
contactList = cm->contacts(isf);
921
QCOMPARE(contactList.size(), 1);
923
contactIdList.clear();
925
// Test intersection filter with two idFilters
926
// idFilter1 has alice's contactId
927
// And idfilter2 has alice's and John's contactId
928
// The result should be one and its alice
930
contactIdList << alice.id() << john.id();
931
idFilter2.setIds(contactIdList);
932
isf.append(idFilter2);
934
contactIdList.clear();
936
contactList = cm->contacts(isf);
937
QCOMPARE(contactList.size(), 1);
938
QCOMPARE(contactList.at(0).id(), alice.id());
940
//clean up filters and the contactIdList
941
isf.remove(idFilter2);
942
isf.remove(idFilter1);
943
contactIdList.clear();
945
//Test with null contactId filter: idFilter1 has one contact and idFilter2 has null id
946
//idFilters with null id should not return any thing so result should be zero
947
contactIdList.append(alice.id());
948
idFilter1.setIds(contactIdList);
949
contactIdList.clear();
950
contactIdList.append(QContactId());
951
idFilter2.setIds(contactIdList);
952
isf.append(idFilter1);
953
isf.append(idFilter2);
954
QCOMPARE(isf.filters().size(), 2);
955
contactList = cm->contacts(isf);
956
QCOMPARE(contactList.size(), 0);
958
//clean up filters and the contactIdList
959
isf.remove(idFilter2);
960
isf.remove(idFilter1);
961
contactIdList.clear();
963
//Three filters: intersection of two IdFilters each having the same contact id
964
//as the other with an IdFilter having one different contactId the result should be zero
965
contactIdList.append(alice.id());
966
idFilter1.setIds(contactIdList);
967
contactIdList.clear();
969
contactIdList.append(john.id());
970
idFilter2.setIds(contactIdList);
971
contactIdList.clear();
973
QContactIdFilter idFilter3;
974
contactIdList.append(john.id());
975
idFilter3.setIds(contactIdList);
976
contactIdList.clear();
978
isf.append(idFilter1);
979
isf.append(idFilter2);
980
isf.append(idFilter3);
982
QCOMPARE(isf.filters().size(), 3);
983
contactList = cm->contacts(isf);
984
QCOMPARE(contactList.size(), 0);
986
//clean up filters and the contactIdList
987
isf.remove(idFilter1);
988
isf.remove(idFilter2);
989
isf.remove(idFilter3);
990
contactIdList.clear();
993
void tst_QContactManager::update()
995
QFETCH(QString, uri);
996
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
998
/* Save a new contact first */
999
int contactCount = cm->contacts().size();
1000
QContact alice = createContact("Alice", "inWonderland", "1234567");
1001
QVERIFY(cm->saveContact(&alice));
1002
QVERIFY(cm->error() == QContactManager::NoError);
1003
contactCount += 1; // added a new contact.
1004
QCOMPARE(cm->contacts().size(), contactCount);
1007
QContactName name = alice.detail(QContactName::Type);
1008
saveContactName(&alice, &name, "updated");
1009
QVERIFY(cm->saveContact(&alice));
1010
QVERIFY(cm->error() == QContactManager::NoError);
1011
saveContactName(&alice, &name, "updated2");
1012
QVERIFY(cm->saveContact(&alice));
1013
QVERIFY(cm->error() == QContactManager::NoError);
1014
alice = cm->contact(alice.id()); // force reload of (persisted) alice
1015
QContact updated = cm->contact(alice.id());
1016
QContactName updatedName = updated.detail(QContactName::Type);
1017
updatedName.setFirstName("updated2"); // Necessary to ensure that updatedName and name are actually the same
1018
QCOMPARE(updatedName, name);
1019
QCOMPARE(cm->contacts().size(), contactCount); // contact count should be the same, no new contacts
1021
/* Test that adding a new detail doesn't cause unwanted side effects */
1022
int detailCount = alice.details().size();
1023
QContactEmailAddress email;
1024
email.setEmailAddress("test@example.com");
1025
alice.saveDetail(&email);
1026
QVERIFY(cm->saveContact(&alice));
1027
QCOMPARE(cm->contacts().size(), contactCount); // contact count shoudl be the same, no new contacts
1029
// This test is dangerous, since backends can add timestamps etc...
1031
QCOMPARE(detailCount, alice.details().size()); // adding a detail should cause the detail count to increase by one.
1032
/* Test that removal of fields in a detail works */
1033
QContactPhoneNumber phn = alice.detail<QContactPhoneNumber>();
1034
phn.setNumber("1234567");
1035
phn.setContexts(QContactDetail::ContextHome);
1036
alice.saveDetail(&phn);
1037
QVERIFY(cm->saveContact(&alice));
1038
alice = cm->contact(alice.id()); // force reload of (persisted) alice
1039
QVERIFY(alice.detail<QContactPhoneNumber>().contexts().contains(QContactDetail::ContextHome)); // check context saved.
1040
phn = alice.detail<QContactPhoneNumber>(); // reload the detail, since it's key could have changed
1041
phn.setContexts(QList<int> ()); // remove context field.
1042
alice.saveDetail(&phn);
1043
QVERIFY(cm->saveContact(&alice));
1044
alice = cm->contact(alice.id()); // force reload of (persisted) alice
1045
QVERIFY(alice.detail<QContactPhoneNumber>().contexts().isEmpty()); // check context removed.
1046
QCOMPARE(cm->contacts().size(), contactCount); // removal of a field of a detail shouldn't affect the contact count
1048
// This test is dangerous, since backends can add timestamps etc...
1049
QCOMPARE(detailCount, alice.details().size()); // removing a field from a detail should affect the detail count
1051
/* Test that removal of details works */
1052
phn = alice.detail<QContactPhoneNumber>(); // reload the detail, since it's key could have changed
1053
alice.removeDetail(&phn);
1054
QVERIFY(cm->saveContact(&alice));
1055
alice = cm->contact(alice.id()); // force reload of (persisted) alice
1056
QVERIFY(alice.details<QContactPhoneNumber>().isEmpty()); // no such detail.
1057
QCOMPARE(cm->contacts().size(), contactCount); // removal of a detail shouldn't affect the contact count
1059
// This test is dangerous, since backends can add timestamps etc...
1061
//QCOMPARE(detailCount, alice.details().size()); // removing a detail should cause the detail count to decrease by one.
1063
if (cm->supportedContactTypes().contains(QContactType::TypeGroup)) {
1064
// Try changing types - not allowed
1065
// from contact -> group
1066
alice.setType(QContactType::TypeGroup);
1067
QContactName na = alice.detail(QContactName::Type);
1068
alice.removeDetail(&na);
1069
QVERIFY(!cm->saveContact(&alice));
1070
QVERIFY(cm->error() == QContactManager::AlreadyExistsError);
1072
// from group -> contact
1073
QContact jabberwock = createContact("", "", "1234567890");
1074
jabberwock.setType(QContactType::TypeGroup);
1075
QVERIFY(cm->saveContact(&jabberwock));
1076
jabberwock.setType(QContactType::TypeContact);
1077
QVERIFY(!cm->saveContact(&jabberwock));
1078
QVERIFY(cm->error() == QContactManager::AlreadyExistsError);
1082
void tst_QContactManager::remove()
1084
QFETCH(QString, uri);
1085
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
1087
/* Save a new contact first */
1088
QContact alice = createContact("Alice", "inWonderland", "1234567");
1089
QVERIFY(cm->saveContact(&alice));
1090
QVERIFY(cm->error() == QContactManager::NoError);
1091
QVERIFY(alice.id() != QContactId());
1093
/* Remove the created contact */
1094
const int contactCount = cm->contactIds().count();
1095
QVERIFY(cm->removeContact(alice.id()));
1096
QCOMPARE(cm->contactIds().count(), contactCount - 1);
1097
QVERIFY(cm->contact(alice.id()).isEmpty());
1098
QCOMPARE(cm->error(), QContactManager::DoesNotExistError);
1101
void tst_QContactManager::addAndUpdate()
1103
QFETCH(QString, uri);
1104
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
1105
int originalCount = cm->contactIds().size();
1106
// save a few new contacts
1107
QList<QContact> saveList;
1108
QContactName nameDetail;
1109
for (int i=0; i<20; i++) {
1110
QContact testContact;
1111
nameDetail.setFirstName(QStringLiteral("Test Contact ") + QString::number(i));
1112
testContact.saveDetail(&nameDetail);
1113
saveList << testContact;
1115
QMap<int, QContactManager::Error> errorMap;
1116
cm->saveContacts(&saveList, &errorMap);
1117
QCOMPARE(cm->contactIds().size(), originalCount + saveList.size());
1118
QCOMPARE(errorMap.size(), 0);
1119
// update previously saved contacts
1120
for (int i=0; i<saveList.size(); i++) {
1121
QContactPhoneNumber phn;
1122
phn.setNumber(QString::number(i));
1123
saveList[i].saveDetail(&phn);
1125
// add new contacts in front of the saveList list
1126
for (int i=20; i<40; i++) {
1127
QContact testContact;
1128
QContactName nameDetail;
1129
nameDetail.setFirstName(QStringLiteral("Test Contact ") + QString::number(i));
1130
testContact.saveDetail(&nameDetail);
1131
saveList.insert(0, testContact);
1133
cm->saveContacts(&saveList, &errorMap);
1134
QCOMPARE(cm->contactIds().size(), originalCount + saveList.size());
1135
QCOMPARE(errorMap.size(), 0);
1136
foreach (const QContact contact, saveList) {
1137
QVERIFY(cm->removeContact(contact.id()));
1141
void tst_QContactManager::batch()
1143
QFETCH(QString, uri);
1144
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
1146
/* First test null pointer operations */
1147
QVERIFY(!cm->saveContacts(NULL, NULL));
1148
QVERIFY(cm->error() == QContactManager::BadArgumentError);
1150
QVERIFY(!cm->removeContacts(QList<QContactId>(), NULL));
1151
QVERIFY(cm->error() == QContactManager::BadArgumentError);
1153
// Get supported name field
1154
int nameField = QContactName::FieldFirstName;
1156
/* Now add 3 contacts, all valid */
1159
na.setValue(nameField, "XXXXXX Albert");
1164
nb.setValue(nameField, "XXXXXX Bob");
1169
nc.setValue(nameField, "XXXXXX Carol");
1172
QList<QContact> contacts;
1173
contacts << a << b << c;
1175
QMap<int, QContactManager::Error> errorMap;
1176
// Add one dummy error to test if the errors are reset
1177
errorMap.insert(0, QContactManager::NoError);
1178
QVERIFY(cm->saveContacts(&contacts, &errorMap));
1179
QVERIFY(cm->error() == QContactManager::NoError);
1180
QVERIFY(errorMap.count() == 0);
1182
/* Make sure our contacts got updated too */
1183
QVERIFY(contacts.count() == 3);
1184
QVERIFY(contacts.at(0).id() != QContactId());
1185
QVERIFY(contacts.at(1).id() != QContactId());
1186
QVERIFY(contacts.at(2).id() != QContactId());
1188
QVERIFY(contacts.at(0).detail(QContactName::Type) == na);
1189
QVERIFY(contacts.at(1).detail(QContactName::Type) == nb);
1190
QVERIFY(contacts.at(2).detail(QContactName::Type) == nc);
1192
/* Retrieve again */
1193
a = cm->contact(contacts.at(0).id());
1194
b = cm->contact(contacts.at(1).id());
1195
c = cm->contact(contacts.at(2).id());
1196
QVERIFY(contacts.at(0).detail(QContactName::Type) == na);
1197
QVERIFY(contacts.at(1).detail(QContactName::Type) == nb);
1198
QVERIFY(contacts.at(2).detail(QContactName::Type) == nc);
1200
/* Save again, with a null error map */
1201
QVERIFY(cm->saveContacts(&contacts, NULL));
1202
QVERIFY(cm->error() == QContactManager::NoError);
1204
/* Now make an update to them all */
1205
QContactPhoneNumber number;
1206
number.setNumber("1234567");
1208
QVERIFY(contacts[0].saveDetail(&number));
1209
number.setNumber("234567");
1210
QVERIFY(contacts[1].saveDetail(&number));
1211
number.setNumber("34567");
1212
QVERIFY(contacts[2].saveDetail(&number));
1214
QVERIFY(cm->saveContacts(&contacts, &errorMap));
1215
QVERIFY(cm->error() == QContactManager::NoError);
1216
QVERIFY(errorMap.count() == 0);
1218
/* Retrieve them and check them again */
1219
a = cm->contact(contacts.at(0).id());
1220
b = cm->contact(contacts.at(1).id());
1221
c = cm->contact(contacts.at(2).id());
1222
QVERIFY(contacts.at(0).detail(QContactName::Type) == na);
1223
QVERIFY(contacts.at(1).detail(QContactName::Type) == nb);
1224
QVERIFY(contacts.at(2).detail(QContactName::Type) == nc);
1226
QVERIFY(a.details<QContactPhoneNumber>().count() == 1);
1227
QVERIFY(b.details<QContactPhoneNumber>().count() == 1);
1228
QVERIFY(c.details<QContactPhoneNumber>().count() == 1);
1230
QVERIFY(a.details<QContactPhoneNumber>().at(0).number() == "1234567");
1231
QVERIFY(b.details<QContactPhoneNumber>().at(0).number() == "234567");
1232
QVERIFY(c.details<QContactPhoneNumber>().at(0).number() == "34567");
1234
/* Retrieve them with the batch ID fetch API */
1235
QList<QContactId> batchIds;
1236
batchIds << a.id() << b.id() << c.id();
1238
// Null error map first (doesn't crash)
1239
QList<QContact> batchFetch = cm->contacts(batchIds, QContactFetchHint(), 0);
1240
QVERIFY(cm->error() == QContactManager::NoError);
1241
QVERIFY(batchFetch.count() == 3);
1242
QVERIFY(batchFetch.at(0).detail(QContactName::Type) == na);
1243
QVERIFY(batchFetch.at(1).detail(QContactName::Type) == nb);
1244
QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nc);
1247
batchFetch = cm->contacts(batchIds, QContactFetchHint(), &errorMap);
1248
QVERIFY(cm->error() == QContactManager::NoError);
1249
QVERIFY(errorMap.count() == 0);
1250
QVERIFY(batchFetch.count() == 3);
1251
QVERIFY(batchFetch.at(0).detail(QContactName::Type) == na);
1252
QVERIFY(batchFetch.at(1).detail(QContactName::Type) == nb);
1253
QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nc);
1255
/* Now an empty id */
1257
batchIds << QContactId() << a.id() << b.id() << c.id();
1258
batchFetch = cm->contacts(batchIds, QContactFetchHint(), 0);
1259
QVERIFY(cm->error() != QContactManager::NoError);
1260
QVERIFY(batchFetch.count() == 4);
1261
QVERIFY(batchFetch.at(0).detail(QContactName::Type) == QContactDetail());
1262
QVERIFY(batchFetch.at(1).detail(QContactName::Type) == na);
1263
QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nb);
1264
QVERIFY(batchFetch.at(3).detail(QContactName::Type) == nc);
1266
batchFetch = cm->contacts(batchIds, QContactFetchHint(), &errorMap);
1267
QVERIFY(cm->error() != QContactManager::NoError);
1268
QVERIFY(batchFetch.count() == 4);
1269
QVERIFY(errorMap.count() == 1);
1270
QVERIFY(errorMap[0] == QContactManager::DoesNotExistError);
1271
QVERIFY(batchFetch.at(0).detail(QContactName::Type) == QContactDetail());
1272
QVERIFY(batchFetch.at(1).detail(QContactName::Type) == na);
1273
QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nb);
1274
QVERIFY(batchFetch.at(3).detail(QContactName::Type) == nc);
1276
/* Now multiple of the same contact */
1278
batchIds << c.id() << b.id() << c.id() << a.id() << a.id();
1279
batchFetch = cm->contacts(batchIds, QContactFetchHint(), &errorMap);
1280
QVERIFY(cm->error() == QContactManager::NoError);
1281
QVERIFY(batchFetch.count() == 5);
1282
QVERIFY(errorMap.count() == 0);
1283
QVERIFY(batchFetch.at(0).detail(QContactName::Type) == nc);
1284
QVERIFY(batchFetch.at(1).detail(QContactName::Type) == nb);
1285
QVERIFY(batchFetch.at(2).detail(QContactName::Type) == nc);
1286
QVERIFY(batchFetch.at(3).detail(QContactName::Type) == na);
1287
QVERIFY(batchFetch.at(4).detail(QContactName::Type) == na);
1289
/* Now delete them all */
1290
QList<QContactId> ids;
1291
ids << a.id() << b.id() << c.id();
1292
QVERIFY(cm->removeContacts(ids, &errorMap));
1293
QVERIFY(errorMap.count() == 0);
1294
QVERIFY(cm->error() == QContactManager::NoError);
1296
/* Make sure the contacts really don't exist any more */
1297
QVERIFY(cm->contact(a.id()).id() == QContactId());
1298
QVERIFY(cm->contact(a.id()).isEmpty());
1299
QVERIFY(cm->error() == QContactManager::DoesNotExistError);
1300
QVERIFY(cm->contact(b.id()).id() == QContactId());
1301
QVERIFY(cm->contact(b.id()).isEmpty());
1302
QVERIFY(cm->error() == QContactManager::DoesNotExistError);
1303
QVERIFY(cm->contact(c.id()).id() == QContactId());
1304
QVERIFY(cm->contact(c.id()).isEmpty());
1305
QVERIFY(cm->error() == QContactManager::DoesNotExistError);
1307
/* Now try removing with all invalid ids (e.g. the ones we just removed) */
1309
ids << a.id() << b.id() << c.id();
1310
QVERIFY(!cm->removeContacts(ids, &errorMap));
1311
QVERIFY(cm->error() == QContactManager::DoesNotExistError);
1312
QVERIFY(errorMap.count() == 3);
1313
QVERIFY(errorMap.values().at(0) == QContactManager::DoesNotExistError);
1314
QVERIFY(errorMap.values().at(1) == QContactManager::DoesNotExistError);
1315
QVERIFY(errorMap.values().at(2) == QContactManager::DoesNotExistError);
1317
/* And again with a null error map */
1318
QVERIFY(!cm->removeContacts(ids, NULL));
1319
QVERIFY(cm->error() == QContactManager::DoesNotExistError);
1321
/* Try adding some new ones again, this time one with an error */
1323
a.setId(QContactId());
1324
b.setId(QContactId());
1325
c.setId(QContactId());
1327
/* Make B the bad guy */
1328
QContactDetail bad(static_cast<QContactDetail::DetailType>(123456));//does not exist and will break if you add it
1329
bad.setValue(12345, "Very bad");
1332
contacts << a << b << c;
1334
/* Fix up B and re save it */
1335
QVERIFY(contacts[1].removeDetail(&bad));
1336
QVERIFY(cm->saveContacts(&contacts, &errorMap));
1337
QVERIFY(errorMap.count() == 0);
1338
QVERIFY(cm->error() == QContactManager::NoError);
1340
// Save and remove a fourth contact. Store the id.
1341
a.setId(QContactId());
1342
QVERIFY(cm->saveContact(&a));
1343
QContactId removedId = a.id();
1344
QVERIFY(cm->removeContact(removedId));
1346
/* Now delete 3 items, but with one bad argument */
1348
ids << contacts.at(0).id();
1350
ids << contacts.at(2).id();
1352
QVERIFY(!cm->removeContacts(ids, &errorMap));
1353
QVERIFY(cm->error() != QContactManager::NoError);
1355
/* Again, the backend has the choice of either removing the successful ones, or not */
1356
QVERIFY(errorMap.count() > 0);
1357
QVERIFY(errorMap.count() <= 3);
1359
// A might have gone through
1360
if (errorMap.keys().contains(0)) {
1361
QVERIFY(errorMap.value(0) != QContactManager::NoError);
1362
QVERIFY(contacts.at(0).id() == QContactId());
1364
QVERIFY(contacts.at(0).id() != QContactId());
1367
/* B should definitely have failed */
1368
QVERIFY(errorMap.value(1) == QContactManager::DoesNotExistError);
1369
QVERIFY(ids.at(1) == removedId);
1371
// A might have gone through
1372
if (errorMap.keys().contains(2)) {
1373
QVERIFY(errorMap.value(2) != QContactManager::NoError);
1374
QVERIFY(contacts.at(2).id() == QContactId());
1376
QVERIFY(contacts.at(2).id() != QContactId());
1380
void tst_QContactManager::invalidManager()
1382
/* Create an invalid manager */
1383
QContactManager manager("this should never work");
1384
QVERIFY(manager.managerName() == "invalid");
1385
QVERIFY(manager.managerVersion() == 0);
1387
/* also, test the other ctor behaviour is sane also */
1388
QContactManager anotherManager("this should never work", 15);
1389
QVERIFY(anotherManager.managerName() == "invalid");
1390
QVERIFY(anotherManager.managerVersion() == 0);
1392
/* Now test that all the operations fail */
1393
QVERIFY(manager.contactIds().count() == 0);
1394
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1398
nf.setLastName("Lastname");
1399
foo.saveDetail(&nf);
1401
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1403
QVERIFY(manager.saveContact(&foo) == false);
1404
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1405
QVERIFY(foo.id() == QContactId());
1406
QVERIFY(manager.contactIds().count() == 0);
1408
QVERIFY(manager.contact(foo.id()).id() == QContactId());
1409
QVERIFY(manager.contact(foo.id()).isEmpty());
1410
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1412
QVERIFY(manager.removeContact(foo.id()) == false);
1413
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1415
QMap<int, QContactManager::Error> errorMap;
1416
errorMap.insert(0, QContactManager::NoError);
1417
QVERIFY(!manager.saveContacts(0, &errorMap));
1418
QVERIFY(manager.errorMap().count() == 0);
1419
QVERIFY(errorMap.count() == 0);
1420
QVERIFY(manager.error() == QContactManager::BadArgumentError);
1423
QContactFilter f; // matches everything
1424
QContactDetailFilter df;
1425
df.setDetailType(QContactDisplayLabel::Type, QContactDisplayLabel::FieldLabel);
1426
QVERIFY(manager.contactIds(QContactFilter()).count() == 0);
1427
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1428
QVERIFY(manager.contactIds(df).count() == 0);
1429
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1430
QVERIFY(manager.contactIds(f | f).count() == 0);
1431
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1432
QVERIFY(manager.contactIds(df | df).count() == 0);
1433
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1435
QVERIFY(manager.isFilterSupported(f) == false);
1436
QVERIFY(manager.isFilterSupported(df) == false);
1438
QList<QContact> list;
1441
QVERIFY(!manager.saveContacts(&list, &errorMap));
1442
QVERIFY(errorMap.count() == 0);
1443
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1445
QVERIFY(!manager.removeContacts(QList<QContactId>(), &errorMap));
1446
QVERIFY(errorMap.count() == 0);
1447
QVERIFY(manager.error() == QContactManager::BadArgumentError);
1449
QList<QContactId> idlist;
1451
QVERIFY(!manager.removeContacts(idlist, &errorMap));
1452
QVERIFY(errorMap.count() == 0);
1453
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1455
/* Self contact id */
1456
QVERIFY(!manager.setSelfContactId(QContactId()));
1457
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1458
QVERIFY(manager.selfContactId() == QContactId());
1459
QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::DoesNotExistError);
1463
QContactRelationship invalidRel;
1464
invalidRel.setFirst(one);
1465
invalidRel.setSecond(two);
1466
QList<QContactRelationship> invalidRelList;
1467
invalidRelList << invalidRel;
1468
QVERIFY(!manager.saveRelationship(&invalidRel));
1469
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1470
QVERIFY(manager.relationships().isEmpty());
1471
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1472
manager.saveRelationships(&invalidRelList, NULL);
1473
QVERIFY(manager.error() == QContactManager::NotSupportedError);
1474
manager.removeRelationships(invalidRelList, NULL);
1475
QVERIFY(manager.error() == QContactManager::NotSupportedError || manager.error() == QContactManager::DoesNotExistError);
1478
QVERIFY(manager.supportedDataTypes().count() == 0);
1481
void tst_QContactManager::memoryManager()
1483
QMap<QString, QString> params;
1484
QContactManager m1("memory");
1485
params.insert("random", "shouldNotBeUsed");
1486
QContactManager m2("memory", params);
1487
params.insert("id", "shouldBeUsed");
1488
QContactManager m3("memory", params);
1489
QContactManager m4("memory", params);
1490
params.insert("id", QString(""));
1491
QContactManager m5("memory", params); // should be another anonymous
1493
// add a contact to each of m1, m2, m3
1496
nc.setFirstName("John");
1497
nc.setLastName("Civilian");
1500
c.setId(QContactId());
1502
QContactName nc2 = c2.detail(QContactName::Type);
1504
nc2.setMiddleName("Public");
1505
c2.saveDetail(&nc2);
1506
m2.saveContact(&c2); // save c2 first; c will be given a higher id
1507
m2.saveContact(&c); // save c to m2
1508
c.setId(QContactId());
1513
/* test that m1 != m2 != m3 and that m3 == m4 */
1515
// check the counts are correct - especially note m4 and m3.
1516
QCOMPARE(m1.contactIds().count(), 1);
1517
QCOMPARE(m2.contactIds().count(), 2);
1518
QCOMPARE(m3.contactIds().count(), 1);
1519
QCOMPARE(m4.contactIds().count(), 1);
1520
QCOMPARE(m5.contactIds().count(), 0);
1522
// remove c2 from m2 - ensure that this doesn't affect any other manager.
1523
m2.removeContact(c2.id());
1524
QCOMPARE(m1.contactIds().count(), 1);
1525
QCOMPARE(m2.contactIds().count(), 1);
1526
QCOMPARE(m3.contactIds().count(), 1);
1527
QCOMPARE(m4.contactIds().count(), 1);
1528
QCOMPARE(m5.contactIds().count(), 0);
1530
// check that the contacts contained within are different.
1531
// note that in the m1->m2 case, only the id will be different!
1532
QVERIFY(m1.contact(m1.contactIds().at(0)) != m2.contact(m2.contactIds().at(0)));
1533
QVERIFY(m1.contact(m1.contactIds().at(0)) != m3.contact(m3.contactIds().at(0)));
1534
QVERIFY(m2.contact(m2.contactIds().at(0)) != m3.contact(m3.contactIds().at(0)));
1535
QVERIFY(m3.contact(m3.contactIds().at(0)) == m4.contact(m4.contactIds().at(0)));
1537
// now, we should be able to remove from m4, and have m3 empty
1538
QVERIFY(m4.removeContact(c.id()));
1539
QCOMPARE(m3.contactIds().count(), 0);
1540
QCOMPARE(m4.contactIds().count(), 0);
1541
QCOMPARE(m5.contactIds().count(), 0);
1544
void tst_QContactManager::overrideManager()
1546
QString defaultStore = QContactManager::availableManagers().value(0);
1548
// preserve existing environment override
1549
QString overrideManager = qgetenv("QTCONTACTS_MANAGER_OVERRIDE");
1551
// override with specific managers
1552
qputenv("QTCONTACTS_MANAGER_OVERRIDE", "memory");
1554
QCOMPARE(m1.managerName(), QString::fromLatin1("memory"));
1556
qputenv("QTCONTACTS_MANAGER_OVERRIDE", "invalid");
1558
QCOMPARE(m2.managerName(), QString::fromLatin1("invalid"));
1560
qputenv("QTCONTACTS_MANAGER_OVERRIDE", "");
1562
QCOMPARE(m3.managerName(), defaultStore);
1564
qputenv("QTCONTACTS_MANAGER_OVERRIDE", overrideManager.toLatin1());
1567
#if defined(SYMBIAN_BACKEND_S60_VERSION_31) || defined(SYMBIAN_BACKEND_S60_VERSION_32) || defined(SYMBIAN_BACKEND_S60_VERSION_50)
1568
/* Some symbian-specific unit tests. */
1569
void tst_QContactManager::symbianManager()
1571
QFETCH(QString, uri);
1572
QString managerName;
1573
QMap<QString, QString> managerParameters;
1574
QContactManager::parseUri(uri, &managerName, &managerParameters);
1575
if (managerName != QString("symbian"))
1578
/* Firstly, a test for invalid storage type crash - QTMOBILITY-470 */
1579
// open the contact database, and create a new contact
1580
CContactDatabase* cntdb = CContactDatabase::OpenL();
1581
CleanupStack::PushL(cntdb);
1582
CContactItem* testItem = CContactCard::NewLC();
1584
// create a new thumbnail field with (invalid) storage type KStorageTypeText instead of KStorageTypeStore
1585
CContactItemField* thumbnailField;
1586
thumbnailField = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldPicture);
1587
thumbnailField->SetMapping(KUidContactFieldVCardMapPHOTO);
1588
thumbnailField->AddFieldTypeL(KUidContactFieldVCardMapBMP);
1589
thumbnailField->ResetStore();
1591
// set the thumbnail data in the thumbnail field, and add it to the contact
1592
_LIT8(KThumbnailDataString, "Dummy Thumbnail Data String");
1593
thumbnailField->StoreStorage()->SetThingL(KThumbnailDataString);
1594
testItem->AddFieldL(*thumbnailField);
1595
CleanupStack::Pop(thumbnailField);
1597
// save the updated contact.
1598
cntdb->CommitContactL(*testItem);
1599
cntdb->CloseContactL(testItem->Id());
1600
CleanupStack::PopAndDestroy(2); // testItem, cntdb
1602
// force database to read thumbnail with invalid storage type. crash if not handled properly.
1603
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
1604
QList<QContact> allContacts = cm->contacts();
1608
void tst_QContactManager::nameSynthesis_data()
1610
QTest::addColumn<QString>("expected");
1612
QTest::addColumn<bool>("addname");
1613
QTest::addColumn<QString>("prefix");
1614
QTest::addColumn<QString>("first");
1615
QTest::addColumn<QString>("middle");
1616
QTest::addColumn<QString>("last");
1617
QTest::addColumn<QString>("suffix");
1619
QTest::addColumn<bool>("addcompany");
1620
QTest::addColumn<QString>("company");
1622
QTest::addColumn<bool>("addname2");
1623
QTest::addColumn<QString>("secondprefix");
1624
QTest::addColumn<QString>("secondfirst");
1625
QTest::addColumn<QString>("secondmiddle");
1626
QTest::addColumn<QString>("secondlast");
1627
QTest::addColumn<QString>("secondsuffix");
1629
QTest::addColumn<bool>("addcompany2");
1630
QTest::addColumn<QString>("secondcompany");
1632
QString e; // empty string.. gets a work out
1634
/* Various empty ones */
1635
QTest::newRow("empty contact") << e
1636
<< false << e << e << e << e << e
1638
<< false << e << e << e << e << e
1640
QTest::newRow("empty name") << e
1641
<< true << e << e << e << e << e
1643
<< false << e << e << e << e << e
1645
QTest::newRow("empty names") << e
1646
<< true << e << e << e << e << e
1648
<< true << e << e << e << e << e
1650
QTest::newRow("empty org") << e
1651
<< false << e << e << e << e << e
1653
<< false << e << e << e << e << e
1655
QTest::newRow("empty orgs") << e
1656
<< false << e << e << e << e << e
1658
<< false << e << e << e << e << e
1660
QTest::newRow("empty orgs and names") << e
1661
<< true << e << e << e << e << e
1663
<< true << e << e << e << e << e
1667
QTest::newRow("prefix") << "Prefix"
1668
<< true << "Prefix" << e << e << e << e
1670
<< false << e << e << e << e << e
1672
QTest::newRow("first") << "First"
1673
<< true << e << "First" << e << e << e
1675
<< false << e << e << e << e << e
1677
QTest::newRow("middle") << "Middle"
1678
<< true << e << e << "Middle" << e << e
1680
<< false << e << e << e << e << e
1682
QTest::newRow("last") << "Last"
1683
<< true << e << e << e << "Last" << e
1685
<< false << e << e << e << e << e
1687
QTest::newRow("suffix") << "Suffix"
1688
<< true << e << e << e << e << "Suffix"
1690
<< false << e << e << e << e << e
1693
/* Single values in the second name */
1694
QTest::newRow("prefix in second") << "Prefix"
1695
<< false << "Prefix" << e << e << e << e
1697
<< true << "Prefix" << e << e << e << e
1699
QTest::newRow("first in second") << "First"
1700
<< false << e << "First" << e << e << e
1702
<< true << e << "First" << e << e << e
1704
QTest::newRow("middle in second") << "Middle"
1705
<< false << e << e << "Middle" << e << e
1707
<< true << e << e << "Middle" << e << e
1709
QTest::newRow("last in second") << "Last"
1710
<< false << e << e << e << "Last" << e
1712
<< true << e << e << e << "Last" << e
1714
QTest::newRow("suffix in second") << "Suffix"
1715
<< false << e << e << e << e << "Suffix"
1717
<< true << e << e << e << e << "Suffix"
1720
/* Multiple name values */
1721
QTest::newRow("prefix first") << "Prefix First"
1722
<< true << "Prefix" << "First" << e << e << e
1724
<< false << e << e << e << e << e
1726
QTest::newRow("prefix middle") << "Prefix Middle"
1727
<< true << "Prefix" << e << "Middle" << e << e
1729
<< false << e << e << e << e << e
1731
QTest::newRow("prefix last") << "Prefix Last"
1732
<< true << "Prefix" << e << e << "Last" << e
1734
<< false << e << e << e << e << e
1736
QTest::newRow("prefix suffix") << "Prefix Suffix"
1737
<< true << "Prefix" << e << e << e << "Suffix"
1739
<< false << e << e << e << e << e
1741
QTest::newRow("first middle") << "First Middle"
1742
<< true << e << "First" << "Middle" << e << e
1744
<< false << e << e << e << e << e
1746
QTest::newRow("first last") << "First Last"
1747
<< true << e << "First" << e << "Last" << e
1749
<< false << e << e << e << e << e
1751
QTest::newRow("first suffix") << "First Suffix"
1752
<< true << e << "First" << e << e << "Suffix"
1754
<< false << e << e << e << e << e
1756
QTest::newRow("middle last") << "Middle Last"
1757
<< true << e << e << "Middle" << "Last" << e
1759
<< false << e << e << e << e << e
1761
QTest::newRow("middle suffix") << "Middle Suffix"
1762
<< true << e << e << "Middle" << e << "Suffix"
1764
<< false << e << e << e << e << e
1766
QTest::newRow("last suffix") << "Last Suffix"
1767
<< true << e << e << e << "Last" << "Suffix"
1769
<< false << e << e << e << e << e
1773
QTest::newRow("all name") << "Prefix First Middle Last Suffix"
1774
<< true << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
1776
<< false << e << e << e << e << e
1778
QTest::newRow("all name second") << "Prefix First Middle Last Suffix"
1779
<< false << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
1781
<< true << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
1785
QTest::newRow("org") << "Company"
1786
<< false << e << e << e << e << e
1787
<< true << "Company"
1788
<< false << e << e << e << e << e
1790
QTest::newRow("second org") << "Company"
1791
<< false << e << e << e << e << e
1793
<< false << e << e << e << e << e
1794
<< true << "Company";
1797
QTest::newRow("org and empty name") << "Company"
1798
<< true << e << e << e << e << e
1799
<< true << "Company"
1800
<< false << e << e << e << e << e
1803
QTest::newRow("name and empty org") << "Prefix First Middle Last Suffix"
1804
<< true << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
1806
<< false << e << e << e << e << e
1809
/* names are preferred to orgs */
1810
QTest::newRow("name and org") << "Prefix First Middle Last Suffix"
1811
<< true << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
1812
<< true << "Company"
1813
<< false << e << e << e << e << e
1818
void tst_QContactManager::nameSynthesis()
1820
QContactManager cm("memory");
1822
QFETCH(QString, expected);
1824
QFETCH(QString, prefix);
1825
QFETCH(QString, first);
1826
QFETCH(QString, middle);
1827
QFETCH(QString, last);
1828
QFETCH(QString, suffix);
1829
QFETCH(QString, company);
1831
QFETCH(QString, secondprefix);
1832
QFETCH(QString, secondfirst);
1833
QFETCH(QString, secondmiddle);
1834
QFETCH(QString, secondlast);
1835
QFETCH(QString, secondsuffix);
1836
QFETCH(QString, secondcompany);
1838
QFETCH(bool, addname);
1839
QFETCH(bool, addname2);
1840
QFETCH(bool, addcompany);
1841
QFETCH(bool, addcompany2);
1843
/* Test the default name synthesis code */
1846
QContactName name, name2;
1847
QContactOrganization org, org2;
1849
name.setPrefix(prefix);
1850
name.setFirstName(first);
1851
name.setMiddleName(middle);
1852
name.setLastName(last);
1853
name.setSuffix(suffix);
1855
name2.setPrefix(secondprefix);
1856
name2.setFirstName(secondfirst);
1857
name2.setMiddleName(secondmiddle);
1858
name2.setLastName(secondlast);
1859
name2.setSuffix(secondsuffix);
1861
org.setName(company);
1862
org2.setName(secondcompany);
1865
c.saveDetail(&name);
1867
c.saveDetail(&name2);
1871
c.saveDetail(&org2);
1874
void tst_QContactManager::observerDeletion()
1876
QContactManager *manager = new QContactManager("memory");
1878
QVERIFY(manager->saveContact(&c));
1879
QContactId id = c.id();
1880
QContactObserver *observer = new QContactObserver(manager, id);
1884
// Test for bug MOBILITY-2566 - that QContactObserver doesn't crash when it is
1885
// destroyed after the associated QContactManager
1888
void tst_QContactManager::signalEmission()
1890
QTest::qWait(500); // clear the signal queue
1891
QFETCH(QString, uri);
1892
QScopedPointer<QContactManager> m1(QContactManager::fromUri(uri));
1894
qRegisterMetaType<QContactId>("QContactId");
1895
qRegisterMetaType<QList<QContactId> >("QList<QContactId>");
1896
QSignalSpy spyCA(m1.data(), SIGNAL(contactsAdded(QList<QContactId>)));
1897
QSignalSpy spyCM(m1.data(), SIGNAL(contactsChanged(QList<QContactId>)));
1898
QSignalSpy spyCR(m1.data(), SIGNAL(contactsRemoved(QList<QContactId>)));
1900
QTestSignalSink casink(m1.data(), SIGNAL(contactsAdded(QList<QContactId>)));
1901
QTestSignalSink cmsink(m1.data(), SIGNAL(contactsChanged(QList<QContactId>)));
1902
QTestSignalSink crsink(m1.data(), SIGNAL(contactsRemoved(QList<QContactId>)));
1904
QList<QVariant> args;
1905
QList<QContactId> arg;
1907
QList<QContact> batchAdd;
1908
QList<QContactId> batchRemove;
1909
int addSigCount = 0; // the expected signal counts.
1910
int modSigCount = 0;
1911
int remSigCount = 0;
1913
// verify add emits signal added
1915
saveContactName(&c, &nc, "John");
1916
QVERIFY(m1->saveContact(&c));
1917
QContactId cid = c.id();
1919
QTRY_COMPARE(spyCA.count(), addSigCount);
1920
args = spyCA.takeFirst();
1922
arg = args.first().value<QList<QContactId> >();
1923
QVERIFY(arg.count() == 1);
1924
QCOMPARE(QContactId(arg.at(0)), cid);
1926
QScopedPointer<QContactObserver> c1Observer(new QContactObserver(m1.data(), cid));
1927
QScopedPointer<QSignalSpy> spyCOM1(new QSignalSpy(c1Observer.data(), SIGNAL(contactChanged())));
1928
QScopedPointer<QSignalSpy> spyCOR1(new QSignalSpy(c1Observer.data(), SIGNAL(contactRemoved())));
1930
// verify save modified emits signal changed
1931
saveContactName(&c, &nc, "Citizen");
1932
QVERIFY(m1->saveContact(&c));
1934
QTRY_COMPARE(spyCM.count(), modSigCount);
1935
QTRY_COMPARE(spyCOM1->count(), 1);
1936
args = spyCM.takeFirst();
1938
arg = args.first().value<QList<QContactId> >();
1939
QVERIFY(arg.count() == 1);
1940
QCOMPARE(QContactId(arg.at(0)), cid);
1942
// verify remove emits signal removed
1943
m1->removeContact(c.id());
1945
QTRY_COMPARE(spyCR.count(), remSigCount);
1946
QTRY_COMPARE(spyCOR1->count(), 1);
1947
args = spyCR.takeFirst();
1949
arg = args.first().value<QList<QContactId> >();
1950
QVERIFY(arg.count() == 1);
1951
QCOMPARE(QContactId(arg.at(0)), cid);
1953
// verify multiple adds works as advertised
1955
QContactName nc2, nc3;
1956
saveContactName(&c2, &nc2, "Mark");
1957
saveContactName(&c3, &nc3, "Garry");
1958
QVERIFY(m1->saveContact(&c2));
1959
QVERIFY(m1->saveContact(&c3));
1960
QTRY_COMPARE(spyCM.count(), modSigCount);
1961
QTRY_VERIFY(spyCA.count() > addSigCount);
1962
addSigCount = spyCA.count();
1966
QScopedPointer<QContactObserver> c2Observer(new QContactObserver(m1.data(), c2.id()));
1967
QScopedPointer<QContactObserver> c3Observer(new QContactObserver(m1.data(), c3.id()));
1968
QScopedPointer<QSignalSpy> spyCOM2(new QSignalSpy(c2Observer.data(), SIGNAL(contactChanged())));
1969
QScopedPointer<QSignalSpy> spyCOM3(new QSignalSpy(c3Observer.data(), SIGNAL(contactChanged())));
1970
QScopedPointer<QSignalSpy> spyCOR2(new QSignalSpy(c2Observer.data(), SIGNAL(contactRemoved())));
1971
QScopedPointer<QSignalSpy> spyCOR3(new QSignalSpy(c3Observer.data(), SIGNAL(contactRemoved())));
1973
// verify multiple modifies works as advertised
1974
saveContactName(&c2, &nc2, "M.");
1975
QVERIFY(m1->saveContact(&c2));
1976
saveContactName(&c2, &nc2, "Mark");
1977
saveContactName(&c3, &nc3, "G.");
1978
QVERIFY(m1->saveContact(&c2));
1979
QVERIFY(m1->saveContact(&c3));
1980
QTRY_VERIFY(spyCM.count() > modSigCount);
1981
modSigCount = spyCM.count();
1982
QTRY_VERIFY(spyCOM2->count() > 0);
1983
QTRY_VERIFY(spyCOM3->count() > 0);
1984
QCOMPARE(spyCOM1->count(), 0);
1986
// verify multiple removes works as advertised
1987
m1->removeContact(c3.id());
1989
m1->removeContact(c2.id());
1991
QTRY_VERIFY(spyCOR2->count() > 0);
1992
QTRY_VERIFY(spyCOR3->count() > 0);
1993
QCOMPARE(spyCOR1->count(), 0);
1995
/* Now test the batch equivalents */
2000
/* Batch adds - set ids to zero so add succeeds. */
2001
c.setId(QContactId());
2002
c2.setId(QContactId());
2003
c3.setId(QContactId());
2004
batchAdd << c << c2 << c3;
2005
QMap<int, QContactManager::Error> errorMap;
2006
QVERIFY(m1->saveContacts(&batchAdd, &errorMap));
2008
QVERIFY(batchAdd.count() == 3);
2010
c2 = batchAdd.at(1);
2011
c3 = batchAdd.at(2);
2013
// We want to see one contactsAdded signal listing id's for all three contacts.
2014
QTRY_COMPARE(spyCA.count(), 1);
2016
QList<QContactId> sigids = spyCA.takeFirst().at(0).value<QList<QContactId> >();
2017
QVERIFY(sigids.contains(c.id()));
2018
QVERIFY(sigids.contains(c2.id()));
2019
QVERIFY(sigids.contains(c3.id()));
2022
QTRY_COMPARE(spyCM.count(), 0);
2024
c1Observer.reset(new QContactObserver(m1.data(), c.id()));
2025
c2Observer.reset(new QContactObserver(m1.data(), c2.id()));
2026
c3Observer.reset(new QContactObserver(m1.data(), c3.id()));
2027
spyCOM1.reset(new QSignalSpy(c1Observer.data(), SIGNAL(contactChanged())));
2028
spyCOM2.reset(new QSignalSpy(c2Observer.data(), SIGNAL(contactChanged())));
2029
spyCOM3.reset(new QSignalSpy(c3Observer.data(), SIGNAL(contactChanged())));
2030
spyCOR1.reset(new QSignalSpy(c1Observer.data(), SIGNAL(contactRemoved())));
2031
spyCOR2.reset(new QSignalSpy(c2Observer.data(), SIGNAL(contactRemoved())));
2032
spyCOR3.reset(new QSignalSpy(c3Observer.data(), SIGNAL(contactRemoved())));
2033
QTRY_COMPARE(spyCR.count(), 0);
2035
/* Batch modifies */
2036
QContactName modifiedName = c.detail(QContactName::Type);
2037
saveContactName(&c, &modifiedName, "Modified number 1");
2038
modifiedName = c2.detail(QContactName::Type);
2039
saveContactName(&c2, &modifiedName, "Modified number 2");
2040
modifiedName = c3.detail(QContactName::Type);
2041
saveContactName(&c3, &modifiedName, "Modified number 3");
2044
batchAdd << c << c2 << c3;
2045
QVERIFY(m1->saveContacts(&batchAdd, &errorMap));
2047
// We want to see one contactsChanged signal listing id's for all three contacts.
2048
QTRY_COMPARE(spyCM.count(), 1);
2050
QList<QContactId> sigids = spyCM.takeFirst().at(0).value<QList<QContactId> >();
2051
QVERIFY(sigids.contains(c.id()));
2052
QVERIFY(sigids.contains(c2.id()));
2053
QVERIFY(sigids.contains(c3.id()));
2055
QTRY_COMPARE(spyCOM1->count(), 1);
2056
QTRY_COMPARE(spyCOM2->count(), 1);
2057
QTRY_COMPARE(spyCOM3->count(), 1);
2060
batchRemove << c.id() << c2.id() << c3.id();
2061
QVERIFY(m1->removeContacts(batchRemove, &errorMap));
2063
// We want to see one contactsRemoved signal listing id's for all three contacts.
2064
QTRY_COMPARE(spyCR.count(), 1);
2066
QList<QContactId> sigids = spyCR.takeFirst().at(0).value<QList<QContactId> >();
2067
QVERIFY(sigids.contains(c.id()));
2068
QVERIFY(sigids.contains(c2.id()));
2069
QVERIFY(sigids.contains(c3.id()));
2071
QTRY_COMPARE(spyCOR1->count(), 1);
2072
QTRY_COMPARE(spyCOR2->count(), 1);
2073
QTRY_COMPARE(spyCOR3->count(), 1);
2075
QTRY_COMPARE(spyCA.count(), 0);
2076
QTRY_COMPARE(spyCM.count(), 0);
2078
QScopedPointer<QContactManager> m2(QContactManager::fromUri(uri));
2080
// During construction SIM backend (m2) will try writing contacts with
2081
// nickname, email and additional number to find out if the SIM card
2082
// will support these fields. The other backend (m1) will then receive
2083
// signals about that. These need to be caught so they don't interfere
2084
// with the tests. (This trial and error method is used because existing
2085
// API for checking the availability of these fields is not public.)
2086
// NOTE: This applies only to pre 10.1 platforms (S60 3.1, 3.2, ect.)
2087
if (uri.contains("symbiansim")) {
2096
void tst_QContactManager::errorStayingPut()
2098
/* Make sure that when we clone a manager, we don't clone the error */
2099
QMap<QString, QString> params;
2100
params.insert("id", "error isolation test");
2101
QContactManager m1("memory",params);
2103
QVERIFY(m1.error() == QContactManager::NoError);
2105
/* Remove an invalid contact to get an error */
2106
QVERIFY(m1.removeContact(QContactId()) == false);
2107
QVERIFY(m1.error() == QContactManager::DoesNotExistError);
2109
/* Create a new manager with hopefully the same backend */
2110
QContactManager m2("memory", params);
2112
QVERIFY(m1.error() == QContactManager::DoesNotExistError);
2113
QVERIFY(m2.error() == QContactManager::NoError);
2115
/* Cause an error on the other ones and check the first is not affected */
2116
m2.saveContacts(0, 0);
2117
QVERIFY(m1.error() == QContactManager::DoesNotExistError);
2118
QVERIFY(m2.error() == QContactManager::BadArgumentError);
2121
int unknown = 12345;
2122
QContactDetail::DetailType unknownType = static_cast<QContactDetail::DetailType>(unknown);
2123
QContactDetail d(unknownType);
2124
d.setValue(unknown, 5);
2127
QVERIFY(m1.saveContact(&c) == false);
2128
QVERIFY(m1.error() == QContactManager::InvalidDetailError);
2129
QVERIFY(m2.error() == QContactManager::BadArgumentError);
2132
void tst_QContactManager::actionPreferences()
2134
QFETCH(QString, uri);
2135
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
2137
// early out if the manager doesn't support action preference saving.
2138
if (cm->managerName() == "jsondb") {
2139
QSKIP("Manager does not support action preferences");
2142
// create a sample contact
2144
a.setImageUrl(QUrl("test.png"));
2145
QContactPhoneNumber p1;
2146
p1.setNumber("12345");
2147
QContactPhoneNumber p2;
2148
p2.setNumber("34567");
2149
QContactPhoneNumber p3;
2150
p3.setNumber("56789");
2152
u.setUrl("http://test.nokia.com");
2155
saveContactName(&c, &n, "TestContact");
2162
// set a preference for dialing a particular saved phonenumber.
2163
c.setPreferredDetail("Dial", p2);
2165
QVERIFY(cm->saveContact(&c)); // save the contact
2166
QContact loaded = cm->contact(c.id()); // reload the contact
2168
// test that the preference was saved correctly.
2169
QContactDetail pref = loaded.preferredDetail("Dial");
2170
QVERIFY(pref == p2);
2172
cm->removeContact(c.id());
2175
void tst_QContactManager::changeSet()
2177
QContactId id = QContactIdMock::createId("a", 1);
2178
QContactChangeSet changeSet;
2179
QVERIFY(changeSet.addedContacts().isEmpty());
2180
QVERIFY(changeSet.changedContacts().isEmpty());
2181
QVERIFY(changeSet.removedContacts().isEmpty());
2183
changeSet.insertAddedContact(id);
2184
QVERIFY(!changeSet.addedContacts().isEmpty());
2185
QVERIFY(changeSet.changedContacts().isEmpty());
2186
QVERIFY(changeSet.removedContacts().isEmpty());
2187
QVERIFY(changeSet.addedContacts().contains(id));
2189
changeSet.insertChangedContact(id);
2190
changeSet.insertChangedContacts(QList<QContactId>() << id);
2191
QVERIFY(changeSet.changedContacts().size() == 1); // set, should only be added once.
2192
QVERIFY(!changeSet.addedContacts().isEmpty());
2193
QVERIFY(!changeSet.changedContacts().isEmpty());
2194
QVERIFY(changeSet.removedContacts().isEmpty());
2195
QVERIFY(changeSet.changedContacts().contains(id));
2196
changeSet.clearChangedContacts();
2197
QVERIFY(changeSet.changedContacts().isEmpty());
2199
changeSet.insertRemovedContacts(QList<QContactId>() << id);
2200
QVERIFY(changeSet.removedContacts().contains(id));
2201
changeSet.clearRemovedContacts();
2202
QVERIFY(changeSet.removedContacts().isEmpty());
2204
QVERIFY(changeSet.dataChanged() == false);
2205
QContactChangeSet changeSet2;
2206
changeSet2 = changeSet;
2207
QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts());
2208
changeSet.emitSignals(0);
2210
changeSet2.clearAddedContacts();
2211
QVERIFY(changeSet2.addedContacts().isEmpty());
2212
changeSet2.insertAddedContacts(changeSet.addedContacts().toList());
2213
QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts());
2215
changeSet2.clearAll();
2216
QVERIFY(changeSet.addedContacts() != changeSet2.addedContacts());
2218
QContactChangeSet changeSet3(changeSet2);
2219
QVERIFY(changeSet.addedContacts() != changeSet3.addedContacts());
2220
QVERIFY(changeSet2.addedContacts() == changeSet3.addedContacts());
2222
changeSet.setDataChanged(true);
2223
QVERIFY(changeSet.dataChanged() == true);
2224
QVERIFY(changeSet.dataChanged() != changeSet2.dataChanged());
2225
QVERIFY(changeSet.dataChanged() != changeSet3.dataChanged());
2226
changeSet.emitSignals(0);
2228
changeSet.addedRelationshipsContacts().insert(id);
2229
changeSet.insertAddedRelationshipsContacts(QList<QContactId>() << id);
2230
QVERIFY(changeSet.addedRelationshipsContacts().contains(id));
2231
changeSet.clearAddedRelationshipsContacts();
2232
QVERIFY(changeSet.addedRelationshipsContacts().isEmpty());
2233
changeSet.insertRemovedRelationshipsContacts(QList<QContactId>() << id);
2234
QVERIFY(changeSet.removedRelationshipsContacts().contains(id));
2235
changeSet.clearRemovedRelationshipsContacts();
2236
QVERIFY(changeSet.removedRelationshipsContacts().isEmpty());
2237
changeSet.emitSignals(0);
2238
changeSet.removedRelationshipsContacts().insert(id);
2239
changeSet.emitSignals(0);
2241
changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(QContactId(), id));
2242
changeSet2 = changeSet;
2243
QVERIFY(changeSet2.addedRelationshipsContacts() == changeSet.addedRelationshipsContacts());
2244
QVERIFY(changeSet2.removedRelationshipsContacts() == changeSet.removedRelationshipsContacts());
2245
QVERIFY(changeSet2.oldAndNewSelfContactId() == changeSet.oldAndNewSelfContactId());
2246
changeSet.emitSignals(0);
2247
changeSet.setOldAndNewSelfContactId(QPair<QContactId, QContactId>(id, QContactId()));
2248
QVERIFY(changeSet2.oldAndNewSelfContactId() != changeSet.oldAndNewSelfContactId());
2249
changeSet.setDataChanged(true);
2250
changeSet.emitSignals(0);
2253
void tst_QContactManager::fetchHint()
2255
// This just tests the accessors and mutators (API).
2256
// See tst_qcontactmanagerfiltering for the "backend support" test.
2257
QContactFetchHint hint;
2258
hint.setOptimizationHints(QContactFetchHint::NoBinaryBlobs);
2259
QCOMPARE(hint.optimizationHints(), QContactFetchHint::NoBinaryBlobs);
2261
rels << QContactRelationship::HasMember();
2262
hint.setRelationshipTypesHint(rels);
2263
QCOMPARE(hint.relationshipTypesHint(), rels);
2264
QList<QContactDetail::DetailType> types;
2265
types << QContactName::Type
2266
<< QContactPhoneNumber::Type;
2267
hint.setDetailTypesHint(types);
2268
QCOMPARE(hint.detailTypesHint(), types);
2269
QSize prefImageSize(33, 33);
2270
hint.setPreferredImageSize(prefImageSize);
2271
QCOMPARE(hint.preferredImageSize(), prefImageSize);
2273
hint.setMaxCountHint(limit);
2274
QCOMPARE(hint.maxCountHint(), limit);
2277
void tst_QContactManager::selfContactId()
2279
QFETCH(QString, uri);
2280
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
2282
// early out if the manager doesn't support self contact id saving
2283
QContactId selfContact = cm->selfContactId();
2284
if (cm->managerName() == "jsondb")
2285
QSKIP("JSONDB backend does not support selfContact at the moment, skipping...");
2288
// create a new "self" contact and retrieve its Id
2289
QVERIFY(cm->error() == QContactManager::NoError || cm->error() == QContactManager::DoesNotExistError);
2291
QContactPhoneNumber selfPhn;
2292
selfPhn.setNumber("12345");
2293
self.saveDetail(&selfPhn);
2294
if (!cm->saveContact(&self)) {
2295
QSKIP("Unable to save the generated self contact");
2297
QContactId newSelfContact = self.id();
2300
qRegisterMetaType<QContactId>("QContactId");
2301
QSignalSpy spy(cm.data(), SIGNAL(selfContactIdChanged(QContactId,QContactId)));
2302
QTestSignalSink sink(cm.data(), SIGNAL(selfContactIdChanged(QContactId,QContactId)));
2304
// Set new self contact
2305
QVERIFY(cm->setSelfContactId(newSelfContact));
2306
QVERIFY(cm->error() == QContactManager::NoError);
2307
QTRY_VERIFY(spy.count() == 1);
2308
QVERIFY(spy.at(0).count() == 2);
2309
// note: for some reason qvariant_cast<QContactId>(spy.at(0).at(0)) returns always zero
2310
// because the type is not recognized. Hence the ugly casting below.
2311
QVERIFY(*((const QContactId*) spy.at(0).at(0).constData()) == selfContact);
2312
QVERIFY(*((const QContactId*) spy.at(0).at(1).constData()) == newSelfContact);
2313
QVERIFY(cm->selfContactId() == newSelfContact);
2315
// Remove self contact
2316
if (!cm->removeContact(self.id())) {
2317
QSKIP("Unable to remove self contact");
2319
QTRY_VERIFY(spy.count() == 2);
2320
QVERIFY(spy.at(1).count() == 2);
2321
QVERIFY(*((const QContactId*) spy.at(1).at(0).constData()) == newSelfContact);
2322
QVERIFY(*((const QContactId*) spy.at(1).at(1).constData()) == QContactId());
2323
QVERIFY(cm->selfContactId() == QContactId()); // ensure reset after removed.
2325
// reset to original state.
2326
cm->setSelfContactId(selfContact);
2329
QList<QContactDetail> tst_QContactManager::removeAllDefaultDetails(const QList<QContactDetail>& details)
2331
QList<QContactDetail> newlist;
2332
foreach (const QContactDetail d, details) {
2333
if (d.type() != QContactType::Type && d.type() != QContactTimestamp::Type) {
2340
void tst_QContactManager::detailOrders()
2342
QFETCH(QString, uri);
2343
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
2345
if (cm->managerName() == "jsondb" || cm->managerName() == "memory")
2346
QSKIP("Skipping: This manager does not support detail ordering!");
2351
QContactPhoneNumber number1, number2, number3;
2353
number1.setNumber("11111111");
2354
number1.setContexts(QContactPhoneNumber::ContextHome);
2356
number2.setNumber("22222222");
2357
number2.setContexts(QContactPhoneNumber::ContextWork);
2359
number3.setNumber("33333333");
2360
number3.setContexts(QContactPhoneNumber::ContextOther);
2362
a.saveDetail(&number1);
2363
a.saveDetail(&number2);
2364
a.saveDetail(&number3);
2366
QVERIFY(cm->saveContact(&a));
2367
a = cm->contact(a.id());
2369
QList<QContactDetail> details = a.details(QContactPhoneNumber::Type);
2370
QVERIFY(details.count() == 3);
2371
QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome);
2372
QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextWork);
2373
QVERIFY(details.at(2).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextOther);
2375
number2 = details.at(1);
2376
QVERIFY(a.removeDetail(&number2));
2377
QVERIFY(cm->saveContact(&a));
2378
a = cm->contact(a.id());
2379
details = a.details(QContactPhoneNumber::Type);
2380
QVERIFY(details.count() == 2);
2381
QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome);
2382
QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextOther);
2384
a.saveDetail(&number2);
2385
QVERIFY(cm->saveContact(&a));
2386
a = cm->contact(a.id());
2388
details = a.details(QContactPhoneNumber::Type);
2389
QVERIFY(details.count() == 3);
2390
QVERIFY(details.at(0).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextHome);
2391
QVERIFY(details.at(1).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextOther);
2392
QVERIFY(details.at(2).value(QContactPhoneNumber::FieldContext) == QContactPhoneNumber::ContextWork);
2395
QContactAddress address1, address2, address3;
2397
address1.setStreet("Brandl St");
2398
address1.setRegion("Brisbane");
2399
address3 = address2 = address1;
2401
address1.setContexts(QContactAddress::ContextHome);
2402
address2.setContexts(QContactAddress::ContextWork);
2403
address3.setContexts(QContactAddress::ContextOther);
2405
QVERIFY(a.saveDetail(&address1));
2406
QVERIFY(a.saveDetail(&address2));
2407
QVERIFY(a.saveDetail(&address3));
2409
QVERIFY(cm->saveContact(&a));
2410
a = cm->contact(a.id());
2411
details = a.details(QContactAddress::Type);
2412
QCOMPARE(details.count(), 3); // 1 location - they're unique
2414
// Detail keys for the moment are not persistent through an contact save / fetch
2415
address3 = details.at(0);
2417
QVERIFY(a.removeDetail(&address3)); // remove the most recent.
2418
address2 = details.at(1); // It is necessary to re-load the detail to ensure that its key is correct
2419
QVERIFY(a.removeDetail(&address2));
2420
QVERIFY(cm->saveContact(&a));
2421
a = cm->contact(a.id());
2422
details = a.details(QContactAddress::Type);
2423
QVERIFY(details.count() == 0); // unique, remove one means none left.
2425
a.saveDetail(&address2);
2426
QVERIFY(cm->saveContact(&a));
2427
a = cm->contact(a.id());
2429
details = a.details(QContactAddress::Type);
2430
QVERIFY(details.count() == 1); // add one back.
2434
QContactEmailAddress email1, email2, email3;
2436
email1.setEmailAddress("aaron@example.com");
2437
email3 = email2 = email1;
2438
email1.setContexts(QContactEmailAddress::ContextHome);
2439
email2.setContexts(QContactEmailAddress::ContextWork);
2440
email3.setContexts(QContactEmailAddress::ContextOther);
2442
a.saveDetail(&email1);
2443
a.saveDetail(&email2);
2444
a.saveDetail(&email3);
2446
QVERIFY(cm->saveContact(&a));
2447
a = cm->contact(a.id());
2449
details = a.details(QContactEmailAddress::Type);
2450
QVERIFY(details.count() == 1);
2451
// Detail keys for the moment are not persistent through an contact save / fetch
2452
email3 = details.at(0);
2454
QVERIFY(a.removeDetail(&email3)); // remove the most recent.
2455
email2 = details.at(1); // It is necessary to re-load the detail to ensure that its key is correct
2456
QVERIFY(a.removeDetail(&email2));
2457
QVERIFY(cm->saveContact(&a));
2458
a = cm->contact(a.id());
2459
details = a.details(QContactEmailAddress::Type);
2460
QVERIFY(details.count() == 0); // unique, remove one means none left.
2462
a.saveDetail(&email2);
2463
QVERIFY(cm->saveContact(&a));
2464
a = cm->contact(a.id());
2466
details = a.details(QContactEmailAddress::Type);
2467
QVERIFY(details.count() == 1); // add one back.
2469
QVERIFY(cm->removeContact(a.id()));
2470
QVERIFY(cm->error() == QContactManager::NoError);
2473
void tst_QContactManager::relationships()
2475
QFETCH(QString, uri);
2476
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
2478
if (cm->managerName() == "jsondb")
2479
QSKIP("Jsondb doesnt support relationships");
2482
// save some contacts
2484
QContact dest1, dest2, dest3, dest4;
2485
QContactPhoneNumber n1, n2, n3, n4;
2491
dest1.saveDetail(&n1);
2492
dest2.saveDetail(&n2);
2493
dest3.saveDetail(&n3);
2494
dest4.saveDetail(&n4);
2496
cm->saveContact(&source);
2497
cm->saveContact(&dest1);
2498
cm->saveContact(&dest2);
2499
cm->saveContact(&dest3);
2500
cm->saveContact(&dest4);
2502
// check if manager supports relationships
2504
if (cm->managerName() == "jsondb") {
2505
// ensure that the operations all fail as required.
2506
QContactRelationship r1, r2, r3;
2507
r1.setFirst(source);
2508
r1.setSecond(dest1);
2509
r1.setRelationshipType(QContactRelationship::HasManager());
2510
r2.setFirst(source);
2511
r2.setSecond(dest2);
2512
r2.setRelationshipType(QContactRelationship::HasManager());
2513
r3.setFirst(source);
2514
r3.setSecond(dest3);
2515
r3.setRelationshipType(QContactRelationship::HasManager());
2517
QList<QContactRelationship> batchList;
2518
batchList << r2 << r3;
2520
// test save and remove
2521
QVERIFY(!cm->saveRelationship(&r1));
2522
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2523
QVERIFY(!cm->removeRelationship(r1));
2524
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2525
cm->saveRelationships(&batchList, NULL);
2526
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2529
QList<QContactRelationship> retrieveList;
2530
retrieveList = cm->relationships(source, QContactRelationship::First);
2531
QVERIFY(retrieveList.isEmpty());
2532
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2533
retrieveList = cm->relationships(source, QContactRelationship::Second);
2534
QVERIFY(retrieveList.isEmpty());
2535
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2536
retrieveList = cm->relationships(source, QContactRelationship::Either); // Either
2537
QVERIFY(retrieveList.isEmpty());
2538
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2541
retrieveList = cm->relationships(QContactRelationship::HasManager(), source, QContactRelationship::First);
2542
QVERIFY(retrieveList.isEmpty());
2543
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2544
retrieveList = cm->relationships(QContactRelationship::HasManager(), source, QContactRelationship::Second);
2545
QVERIFY(retrieveList.isEmpty());
2546
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2547
retrieveList = cm->relationships(QContactRelationship::HasManager(), source, QContactRelationship::Either);
2548
QVERIFY(retrieveList.isEmpty());
2549
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2550
retrieveList = cm->relationships(QContactRelationship::HasManager(), source);
2551
QVERIFY(retrieveList.isEmpty());
2552
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2553
retrieveList = cm->relationships(QContactRelationship::HasManager());
2554
QVERIFY(retrieveList.isEmpty());
2555
QVERIFY(cm->error() == QContactManager::NotSupportedError);
2559
// Get supported relationship types
2560
QStringList availableRelationshipTypes;
2561
if (cm->isRelationshipTypeSupported(QContactRelationship::HasMember()))
2562
availableRelationshipTypes << QContactRelationship::HasMember();
2563
if (cm->isRelationshipTypeSupported(QContactRelationship::HasAssistant()))
2564
availableRelationshipTypes << QContactRelationship::HasAssistant();
2565
if (cm->isRelationshipTypeSupported(QContactRelationship::HasManager()))
2566
availableRelationshipTypes << QContactRelationship::HasManager();
2567
if (cm->isRelationshipTypeSupported(QContactRelationship::HasSpouse()))
2568
availableRelationshipTypes << QContactRelationship::HasSpouse();
2569
if (cm->isRelationshipTypeSupported(QContactRelationship::IsSameAs()))
2570
availableRelationshipTypes << QContactRelationship::IsSameAs();
2572
// add some arbitrary type for testing
2573
if (availableRelationshipTypes.count())
2574
availableRelationshipTypes.insert(0, "test-arbitrary-relationship-type");
2576
availableRelationshipTypes.append("test-arbitrary-relationship-type");
2577
availableRelationshipTypes.append(QContactRelationship::HasMember());
2578
availableRelationshipTypes.append(QContactRelationship::HasAssistant());
2581
// Verify that we have relationship types. If there are none then the manager
2582
// is saying it supports relationships but does not actually implement any
2583
// relationship type.
2584
QVERIFY(!availableRelationshipTypes.isEmpty());
2586
// Some backends (eg. symbian) require that when type is "HasMember"
2587
// then "first" contact must be a group.
2588
if (availableRelationshipTypes.at(0) == QContactRelationship::HasMember()) {
2589
cm->removeContact(source.id());
2590
source.setId(QContactId());
2591
source.setType(QContactType::TypeGroup);
2592
cm->saveContact(&source);
2595
// build our relationship - source is the manager all of the dest contacts.
2596
QContactRelationship customRelationshipOne;
2597
customRelationshipOne.setFirst(source);
2598
customRelationshipOne.setSecond(dest1);
2599
customRelationshipOne.setRelationshipType(availableRelationshipTypes.at(0));
2600
QCOMPARE(customRelationshipOne.first(), source);
2601
QCOMPARE(customRelationshipOne.second(), dest1);
2602
QVERIFY(customRelationshipOne.relationshipType() == availableRelationshipTypes.at(0));
2604
// save the relationship
2605
int managerRelationshipsCount = cm->relationships(availableRelationshipTypes.at(0)).count();
2606
QVERIFY(cm->saveRelationship(&customRelationshipOne));
2608
// test our accessors.
2609
QCOMPARE(cm->relationships(availableRelationshipTypes.at(0)).count(), (managerRelationshipsCount + 1));
2610
QVERIFY(cm->relationships(availableRelationshipTypes.at(0), source).count() == 1);
2612
// remove the dest1 contact, relationship should be removed.
2613
cm->removeContact(dest1.id());
2614
QCOMPARE(cm->relationships(availableRelationshipTypes.at(0), dest1, QContactRelationship::Second).count(), 0);
2616
// modify and save the relationship
2617
customRelationshipOne.setSecond(dest2);
2618
QVERIFY(cm->saveRelationship(&customRelationshipOne));
2620
// attempt to save the relationship again. XXX TODO: what should the result be? currently succeeds (overwrites)
2621
int relationshipsCount = cm->relationships().count();
2622
QVERIFY(cm->saveRelationship(&customRelationshipOne)); // succeeds, but just overwrites
2623
QCOMPARE(relationshipsCount, cm->relationships().count()); // shouldn't change; save should have overwritten.
2625
// removing the source contact should result in removal of the relationship.
2626
QVERIFY(cm->removeContact(source.id()));
2627
QCOMPARE(cm->relationships().count(), relationshipsCount - 1); // the relationship should have been removed.
2629
// now ensure that qcontact relationship caching works as required - perhaps this should be in tst_QContact?
2630
source.setId(QContactId()); // reset id so we can resave
2631
QVERIFY(cm->saveContact(&source)); // save source again.
2632
customRelationshipOne.setFirst(source);
2633
customRelationshipOne.setSecond(dest2);
2634
QVERIFY(cm->saveRelationship(&customRelationshipOne));
2636
// Add a second relationship
2637
QContactRelationship customRelationshipTwo;
2638
customRelationshipTwo.setFirst(source);
2639
if (availableRelationshipTypes.count() > 1)
2640
customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(1));
2642
customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(0));
2643
customRelationshipTwo.setSecond(dest3);
2644
QVERIFY(cm->saveRelationship(&customRelationshipTwo));
2646
// currently, the contacts are "stale" - no cached relationships
2647
QVERIFY(dest3.relatedContacts().isEmpty());
2648
QVERIFY(dest3.relationships().isEmpty());
2649
QVERIFY(dest2.relatedContacts().isEmpty());
2650
QVERIFY(dest2.relationships().isEmpty());
2652
// now refresh the contacts
2653
dest3 = cm->contact(dest3.id());
2654
dest2 = cm->contact(dest2.id());
2655
source = cm->contact(source.id());
2658
QVERIFY(source.relatedContacts(QString(), QContactRelationship::First).isEmpty()); // source is always the first, so this should be empty.
2659
QVERIFY(source.relatedContacts(QString(), QContactRelationship::Second).contains(dest2));
2660
QVERIFY(source.relatedContacts(QString(), QContactRelationship::Either).contains(dest2));
2661
QVERIFY(source.relatedContacts(QString(), QContactRelationship::Second).contains(dest3));
2662
QVERIFY(source.relatedContacts(QString(), QContactRelationship::Either).contains(dest3));
2663
QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).contains(dest2));
2664
QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::First).isEmpty());
2666
QVERIFY(dest2.relatedContacts().contains(source));
2667
QVERIFY(dest2.relationships().contains(customRelationshipOne));
2668
QVERIFY(!dest2.relationships().contains(customRelationshipTwo));
2669
QVERIFY(dest2.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipOne));
2670
QVERIFY(!dest2.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipTwo));
2671
QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0)).contains(source));
2672
QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::First).contains(source));
2673
QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).isEmpty());
2674
QVERIFY(!dest2.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).contains(source));
2676
QVERIFY(dest3.relatedContacts().contains(source));
2677
QVERIFY(!dest3.relationships().contains(customRelationshipOne));
2678
QVERIFY(dest3.relationships().contains(customRelationshipTwo));
2679
QVERIFY(!dest3.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipOne));
2682
QList<QContactRelationship> relats = source.relationships();
2683
QList<QContactRelationship>::iterator it = relats.begin();
2685
while (it != relats.end()) {
2686
QContact firstContact = it->first();
2687
QVERIFY(firstContact == source);
2688
QVERIFY(it->second() == dest2 || it->second() == dest3);
2692
if (availableRelationshipTypes.count() > 1) {
2693
QVERIFY(source.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::Second).contains(dest3));
2694
QVERIFY(source.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::First).isEmpty());
2696
QVERIFY(dest2.relationships(availableRelationshipTypes.at(1)).isEmpty());
2698
QVERIFY(!dest3.relationships(availableRelationshipTypes.at(0)).contains(customRelationshipTwo));
2699
QVERIFY(dest3.relationships(availableRelationshipTypes.at(1)).contains(customRelationshipTwo));
2700
QVERIFY(!dest3.relationships(availableRelationshipTypes.at(1)).contains(customRelationshipOne));
2701
QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1)).contains(source));
2702
QVERIFY(!dest3.relatedContacts(availableRelationshipTypes.at(0)).contains(source));
2703
QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1)).contains(source)); // role = either
2704
QVERIFY(!dest3.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::Second).contains(source));
2705
QVERIFY(dest3.relatedContacts(availableRelationshipTypes.at(1), QContactRelationship::First).contains(source));
2706
QVERIFY(dest2.relatedContacts(availableRelationshipTypes.at(1)).isEmpty());
2708
QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).contains(dest3));
2712
QMap<int, QContactManager::Error> errorMap;
2713
QList<QContactRelationship> moreRels;
2715
moreRels << customRelationshipOne << customRelationshipTwo;
2716
errorMap.insert(5, QContactManager::BadArgumentError);
2717
QVERIFY(cm->removeRelationships(moreRels, &errorMap));
2718
QVERIFY(errorMap.count() == 0);
2720
// test batch API and ordering in contacts
2721
QList<QContactRelationship> currentRelationships = cm->relationships(source, QContactRelationship::First);
2722
QList<QContactRelationship> batchList;
2723
QContactRelationship br1, br2, br3;
2724
br1.setFirst(source);
2725
br1.setSecond(dest2);
2726
br1.setRelationshipType(availableRelationshipTypes.at(0));
2727
br2.setFirst(source);
2728
br2.setSecond(dest3);
2729
br2.setRelationshipType(availableRelationshipTypes.at(0));
2730
if (availableRelationshipTypes.count() > 1) {
2731
br3.setFirst(source);
2732
br3.setSecond(dest3);
2733
br3.setRelationshipType(availableRelationshipTypes.at(1));
2735
br3.setFirst(source);
2736
br3.setSecond(dest4);
2737
br3.setRelationshipType(availableRelationshipTypes.at(0));
2739
batchList << br1 << br2 << br3;
2741
// ensure that the batch save works properly
2742
cm->saveRelationships(&batchList, NULL);
2743
QCOMPARE(cm->error(), QContactManager::NoError);
2744
QList<QContactRelationship> batchRetrieve = cm->relationships(source, QContactRelationship::First);
2745
QVERIFY(batchRetrieve.contains(br1));
2746
QVERIFY(batchRetrieve.contains(br2));
2747
QVERIFY(batchRetrieve.contains(br3));
2749
// remove a single relationship
2750
QVERIFY(cm->removeRelationship(br3));
2751
batchRetrieve = cm->relationships(source, QContactRelationship::First);
2752
QVERIFY(batchRetrieve.contains(br1));
2753
QVERIFY(batchRetrieve.contains(br2));
2754
QVERIFY(!batchRetrieve.contains(br3)); // has already been removed.
2756
// now ensure that the batch remove works and we get returned to the original state.
2757
batchList.removeOne(br3);
2758
cm->removeRelationships(batchList, NULL);
2759
QVERIFY(cm->error() == QContactManager::NoError);
2760
QCOMPARE(cm->relationships(source, QContactRelationship::First), currentRelationships);
2762
// attempt to save relationships between an existing source but non-existent destination
2763
QContact nonexistentDest;
2764
quint32 idSeed = 0x5544;
2765
QContactId nonexistentLocalId = QContactId::fromString(QString::number(idSeed));
2767
nonexistentLocalId = cm->contact(nonexistentLocalId).id();
2768
if (nonexistentLocalId == QContactId()) {
2769
// found a "spare" local id (no contact with that id)
2775
nonexistentLocalId = QContactId::fromString(QString::number(idSeed));
2776
QVERIFY(nonexistentLocalId != QContactId()); // integer overflow check.
2778
// nonexistentDest.id().setLocalId(nonexistentLocalId);
2780
QContactRelationship maliciousRel;
2781
maliciousRel.setFirst(source);
2782
maliciousRel.setSecond(nonexistentDest);
2783
maliciousRel.setRelationshipType("nokia-test-invalid-relationship-type");
2784
QVERIFY(!cm->saveRelationship(&maliciousRel));
2786
// attempt to save a circular relationship - should fail!
2787
maliciousRel.setFirst(source);
2788
maliciousRel.setSecond(source);
2789
maliciousRel.setRelationshipType(availableRelationshipTypes.at(0));
2790
QVERIFY(!cm->saveRelationship(&maliciousRel));
2792
// more negative testing, but force manager to recognise the empty URI
2793
QContact circularContact = source;
2794
maliciousRel.setFirst(circularContact);
2795
maliciousRel.setSecond(circularContact);
2796
maliciousRel.setRelationshipType(availableRelationshipTypes.at(0));
2797
QVERIFY(!cm->saveRelationship(&maliciousRel));
2798
maliciousRel.setFirst(source);
2799
maliciousRel.setSecond(circularContact);
2800
maliciousRel.setRelationshipType(availableRelationshipTypes.at(0));
2801
QVERIFY(!cm->saveRelationship(&maliciousRel));
2802
maliciousRel.setFirst(circularContact);
2803
maliciousRel.setSecond(source);
2804
maliciousRel.setRelationshipType(availableRelationshipTypes.at(0));
2805
QVERIFY(!cm->saveRelationship(&maliciousRel));
2807
// attempt to save a relationship where the source contact comes from another manager
2808
QContactId invalidId;
2809
circularContact.setId(invalidId);
2810
maliciousRel.setFirst(circularContact); // an invalid source contact
2811
maliciousRel.setSecond(dest2); // a valid destination contact
2812
maliciousRel.setRelationshipType(availableRelationshipTypes.at(0));
2813
QVERIFY(!cm->saveRelationship(&maliciousRel));
2815
// remove the nonexistent relationship
2816
relationshipsCount = cm->relationships().count();
2817
QVERIFY(!cm->removeRelationship(maliciousRel)); // does not exist; fail remove.
2818
QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError);
2819
QCOMPARE(cm->relationships().count(), relationshipsCount); // should be unchanged.
2821
// now we want to ensure that a relationship is removed if one of the contacts is removed.
2822
customRelationshipOne.setFirst(source);
2823
customRelationshipOne.setSecond(dest2);
2824
customRelationshipOne.setRelationshipType(availableRelationshipTypes.at(0));
2826
// Test batch save with an error map
2828
moreRels << customRelationshipOne;
2829
errorMap.insert(0, QContactManager::BadArgumentError);
2830
QVERIFY(cm->saveRelationships(&moreRels, &errorMap));
2831
QVERIFY(cm->error() == QContactManager::NoError);
2832
QVERIFY(errorMap.count() == 0); // should be reset
2833
source = cm->contact(source.id());
2834
dest2 = cm->contact(dest2.id());
2835
QVERIFY(cm->removeContact(dest2.id())); // remove dest2, the relationship should be removed
2836
QVERIFY(cm->relationships(availableRelationshipTypes.at(0), dest2, QContactRelationship::Second).isEmpty());
2837
source = cm->contact(source.id());
2838
QVERIFY(!source.relatedContacts().contains(dest2)); // and it shouldn't appear in cache.
2840
// now clean up and remove our dests.
2841
QVERIFY(cm->removeContact(source.id()));
2842
QVERIFY(cm->removeContact(dest3.id()));
2844
// attempt to save relationships with nonexistent contacts
2845
QVERIFY(!cm->saveRelationship(&br1));
2846
QVERIFY(cm->error() == QContactManager::InvalidRelationshipError);
2847
cm->saveRelationships(&batchList, NULL);
2848
QVERIFY(cm->error() == QContactManager::InvalidRelationshipError);
2849
QVERIFY(!cm->removeRelationship(br1));
2850
QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError);
2851
cm->removeRelationships(batchList, NULL);
2852
QVERIFY(cm->error() == QContactManager::DoesNotExistError || cm->error() == QContactManager::InvalidRelationshipError);
2855
void tst_QContactManager::contactType()
2857
QFETCH(QString, uri);
2858
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
2860
if (!cm->supportedContactTypes().contains(QContactType::TypeGroup))
2861
QSKIP("Skipping: This manager does not support group contacts!");
2865
g1.setType(QContactType::TypeGroup);
2866
g2.setType(QContactType::TypeGroup);
2868
QContactPhoneNumber g1p, g2p, cp;
2869
g1p.setNumber("22222");
2870
g2p.setNumber("11111");
2871
cp.setNumber("33333");
2873
g1.saveDetail(&g1p);
2874
g2.saveDetail(&g2p);
2877
QVERIFY(cm->saveContact(&g1));
2878
QVERIFY(cm->saveContact(&g2));
2879
QVERIFY(cm->saveContact(&c));
2881
// test that the accessing by type works properly
2882
QContactDetailFilter groupFilter;
2883
groupFilter.setDetailType(QContactType::Type, QContactType::FieldType);
2884
groupFilter.setValue(QContactType::TypeGroup);
2885
QVERIFY(cm->contactIds(groupFilter).contains(g1.id()));
2886
QVERIFY(cm->contactIds(groupFilter).contains(g2.id()));
2887
QVERIFY(!cm->contactIds(groupFilter).contains(c.id()));
2889
QList<QContactSortOrder> sortOrders;
2890
QContactSortOrder byPhoneNumber;
2891
byPhoneNumber.setDetailType(QContactPhoneNumber::Type, QContactPhoneNumber::FieldNumber);
2892
sortOrders.append(byPhoneNumber);
2894
// and ensure that sorting works properly with typed contacts also
2895
QList<QContactId> sortedIds = cm->contactIds(groupFilter, sortOrders);
2896
QVERIFY(sortedIds.indexOf(g2.id()) < sortedIds.indexOf(g1.id()));
2898
cm->removeContact(g1.id());
2899
cm->removeContact(g2.id());
2900
cm->removeContact(c.id());
2903
#if defined(USE_VERSIT_PLZ)
2904
void tst_QContactManager::partialSave()
2906
QFETCH(QString, uri);
2907
QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
2909
QVersitContactImporter imp;
2910
QVersitReader reader(QByteArray(
2911
"BEGIN:VCARD\r\nFN:Alice\r\nN:Alice\r\nTEL:12345\r\nEND:VCARD\r\n"
2912
"BEGIN:VCARD\r\nFN:Bob\r\nN:Bob\r\nTEL:5678\r\nEND:VCARD\r\n"
2913
"BEGIN:VCARD\r\nFN:Carol\r\nN:Carol\r\nEMAIL:carol@example.com\r\nEND:VCARD\r\n"
2914
"BEGIN:VCARD\r\nFN:David\r\nN:David\r\nORG:DavidCorp\r\nEND:VCARD\r\n"));
2915
reader.startReading();
2916
reader.waitForFinished();
2917
QCOMPARE(reader.error(), QVersitReader::NoError);
2919
QCOMPARE(reader.results().count(), 4);
2920
QVERIFY(imp.importDocuments(reader.results()));
2921
QCOMPARE(imp.contacts().count(), 4);
2922
QVERIFY(imp.contacts()[0].displayLabel() == QStringLiteral("Alice"));
2923
QVERIFY(imp.contacts()[1].displayLabel() == QStringLiteral("Bob"));
2924
QVERIFY(imp.contacts()[2].displayLabel() == QStringLiteral("Carol"));
2925
QVERIFY(imp.contacts()[3].displayLabel() == QStringLiteral("David"));
2927
QList<QContact> contacts = imp.contacts();
2928
QMap<int, QContactManager::Error> errorMap;
2930
// First save these contacts
2931
QVERIFY(cm->saveContacts(&contacts, &errorMap));
2932
QList<QContact> originalContacts = contacts;
2934
// Now try some partial save operations
2935
// 0) empty mask == full save
2936
// 1) Ignore an added phonenumber
2937
// 2) Only save a modified phonenumber, not a modified email
2938
// 3) Remove an email address & phone, mask out phone
2939
// 4) new contact, no details in the mask
2940
// 5) new contact, some details in the mask
2941
// 6) Have a bad manager uri in the middle
2942
// 7) Have a non existing contact in the middle
2943
// 8) A list entirely of new contacts
2945
QContactPhoneNumber pn;
2946
pn.setNumber("111111");
2947
contacts[0].saveDetail(&pn);
2950
QVERIFY(cm->saveContacts(&contacts, QStringList(), &errorMap));
2952
// That should have updated everything
2953
QContact a = cm->contact(originalContacts[0].id());
2954
QVERIFY(a.details<QContactPhoneNumber>().count() == 2);
2956
// 1) Add a phone number to b, mask it out
2957
contacts[1].saveDetail(&pn);
2958
QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap));
2959
QVERIFY(errorMap.isEmpty());
2961
QContact b = cm->contact(originalContacts[1].id());
2962
QVERIFY(b.details<QContactPhoneNumber>().count() == 1);
2964
// 2) save a modified detail in the mask
2965
QContactEmailAddress e;
2966
e.setEmailAddress("example@example.com");
2967
contacts[1].saveDetail(&e); // contacts[1] should have both phone and email
2969
QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap));
2970
QVERIFY(errorMap.isEmpty());
2971
b = cm->contact(originalContacts[1].id());
2972
QVERIFY(b.details<QContactPhoneNumber>().count() == 1);
2973
QVERIFY(b.details<QContactEmailAddress>().count() == 1);
2975
// 3) Remove an email address and a phone number
2976
QVERIFY(contacts[1].removeDetail(&e));
2977
QVERIFY(contacts[1].removeDetail(&pn));
2978
QVERIFY(contacts[1].details<QContactEmailAddress>().count() == 0);
2979
QVERIFY(contacts[1].details<QContactPhoneNumber>().count() == 1);
2980
QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap));
2981
QVERIFY(errorMap.isEmpty());
2982
b = cm->contact(originalContacts[1].id());
2983
QVERIFY(b.details<QContactPhoneNumber>().count() == 1);
2984
QVERIFY(b.details<QContactEmailAddress>().count() == 0);
2986
// 4 - New contact, no details in the mask
2987
QContact newContact = originalContacts[3];
2988
newContact.setId(QContactId());
2990
contacts.append(newContact);
2991
QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap));
2992
QVERIFY(errorMap.isEmpty());
2993
QVERIFY(contacts[4].id() != 0); // Saved
2994
b = cm->contact(contacts[4].id());
2995
QVERIFY(b.details<QContactOrganization>().count() == 0); // not saved
2996
QVERIFY(b.details<QContactName>().count() == 0); // not saved
2998
// 5 - New contact, some details in the mask
2999
newContact = originalContacts[2];
3000
newContact.setId(QContactId());
3001
contacts.append(newContact);
3002
QVERIFY(cm->saveContacts(&contacts, QStringList(QContactEmailAddress::Type), &errorMap));
3003
QVERIFY(errorMap.isEmpty());
3004
QVERIFY(contacts[5].id() != 0); // Saved
3005
b = cm->contact(contacts[5].id());
3006
QVERIFY(b.details<QContactEmailAddress>().count() == 1);
3007
QVERIFY(b.details<QContactName>().count() == 0); // not saved
3009
// 6) Have a bad manager uri in the middle followed by a save error
3010
QContactId id4(contacts[4].id());
3011
QContactId badId(id4);
3012
badId.setManagerUri(QString());
3013
contacts[4].setId(badId);
3014
QContactDetail badDetail("BadDetail");
3015
badDetail.setValue("BadField", "BadValue");
3016
contacts[5].saveDetail(&badDetail);
3017
QVERIFY(!cm->saveContacts(&contacts, QStringList("BadDetail"), &errorMap));
3018
QCOMPARE(errorMap.count(), 2);
3019
QCOMPARE(errorMap[4], QContactManager::DoesNotExistError);
3020
QCOMPARE(errorMap[5], QContactManager::InvalidDetailError);
3022
// 7) Have a non existing contact in the middle followed by a save error
3024
badId.setLocalId("987234"); // something nonexistent
3025
contacts[4].setId(badId);
3026
QVERIFY(!cm->saveContacts(&contacts, QStringList("BadDetail"), &errorMap));
3027
QCOMPARE(errorMap.count(), 2);
3028
QCOMPARE(errorMap[4], QContactManager::DoesNotExistError);
3029
QCOMPARE(errorMap[5], QContactManager::InvalidDetailError);
3031
// 8 - New contact, no details in the mask
3032
newContact = originalContacts[3];
3033
QCOMPARE(newContact.details<QContactOrganization>().count(), 1);
3034
QCOMPARE(newContact.details<QContactName>().count(), 1);
3035
newContact.setId(QContactId());
3036
QList<QContact> contacts2;
3037
contacts2.append(newContact);
3038
QVERIFY(cm->saveContacts(&contacts2, QStringList(QContactEmailAddress::Type), &errorMap));
3039
QVERIFY(errorMap.isEmpty());
3040
QVERIFY(contacts2[0].id() != 0); // Saved
3041
b = cm->contact(contacts2[0].id());
3042
QVERIFY(b.details<QContactOrganization>().count() == 0); // not saved
3043
QVERIFY(b.details<QContactName>().count() == 0); // not saved
3045
// 9 - A list with only a new contact, with some details in the mask
3046
newContact = originalContacts[2];
3047
newContact.setId(QContactId());
3049
contacts2.append(newContact);
3050
QVERIFY(cm->saveContacts(&contacts2, QStringList(QContactEmailAddress::Type), &errorMap));
3051
QVERIFY(errorMap.isEmpty());
3052
QVERIFY(contacts2[0].id() != 0); // Saved
3053
b = cm->contact(contacts2[0].id());
3054
QVERIFY(b.details<QContactEmailAddress>().count() == 1);
3055
QVERIFY(b.details<QContactName>().count() == 0); // not saved
3057
// 10 - A list with new a contact for the wrong manager, followed by a new contact with an
3059
newContact = originalContacts[2];
3060
newContact.setId(QContactId());
3062
contacts2.append(newContact);
3063
contacts2.append(newContact);
3064
contacts2[0].setId(badId);
3065
contacts2[1].saveDetail(&badDetail);
3066
QVERIFY(!cm->saveContacts(&contacts2, QStringList("BadDetail"), &errorMap));
3067
QCOMPARE(errorMap.count(), 2);
3068
QCOMPARE(errorMap[0], QContactManager::DoesNotExistError);
3069
QCOMPARE(errorMap[1], QContactManager::InvalidDetailError);
3073
void tst_QContactManager::lateDeletion()
3075
// Create some engines, but make them get deleted at shutdown
3076
QFETCH(QString, uri);
3077
QContactManager* cm = QContactManager::fromUri(uri);
3079
cm->setParent(qApp); // now do nothing
3082
void tst_QContactManager::lazyConnections()
3084
QSKIP("Skipping: Lazy manager engine does not currently work with new plugin system!");
3085
//TODO: adapt lazy manager engine to new plugin system
3086
QMap<QString, QString> parameters;
3087
parameters["version"] = QString("1");
3088
QContactManager lazy1("testlazy", parameters);
3089
QContactManager lazy2("testlazy");
3091
QCOMPARE(lazy1.managerName(), QString("lazy"));
3092
QCOMPARE(lazy2.managerName(), QString("lazy2"));
3094
// Make sure the initial connection counts are empty
3095
QCOMPARE(QContactLazyEngine::connectionCounts.count(), 0);
3096
QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 0);
3100
QTestSignalSink casink(&lazy1, SIGNAL(contactsAdded(QList<QContactId>)));
3102
// See if we got one connection
3103
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 1);
3104
QCOMPARE(QContactLazyEngine::connectionCounts.count(), 1);
3106
// Go out of scope, and see if disconnect is called
3108
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 0);
3109
QCOMPARE(QContactLazyEngine::connectionCounts.count(), 1);
3113
QTestSignalSink casink(&lazy2, SIGNAL(contactsAdded(QList<QContactId>)));
3115
// See if we got one connection
3116
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 1);
3117
QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 1);
3119
// Go out of scope, and see if disconnect is called
3121
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 0);
3122
QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 1);
3124
// Just make sure all the signals get connected correctly
3126
QTestSignalSink casink(&lazy1, SIGNAL(contactsAdded(QList<QContactId>)));
3127
QTestSignalSink crsink(&lazy1, SIGNAL(contactsRemoved(QList<QContactId>)));
3128
QTestSignalSink cmsink(&lazy1, SIGNAL(contactsChanged(QList<QContactId>)));
3129
QTestSignalSink dcsink(&lazy1, SIGNAL(dataChanged()));
3130
QTestSignalSink rasink(&lazy1, SIGNAL(relationshipsAdded(QList<QContactId>)));
3131
QTestSignalSink rrsink(&lazy1, SIGNAL(relationshipsRemoved(QList<QContactId>)));
3132
QTestSignalSink scsink(&lazy1, SIGNAL(selfContactIdChanged(QContactId,QContactId)));
3134
// See if we got all the connections
3135
QCOMPARE(QContactLazyEngine::connectionCounts.count(), 7);
3136
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 1);
3137
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsChanged)), 1);
3138
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsRemoved)), 1);
3139
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::dataChanged)), 1);
3140
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsAdded)), 1);
3141
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsRemoved)), 1);
3142
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::selfContactIdChanged)), 1);
3144
QCOMPARE(QContactLazyEngine::connectionCounts.count(), 7);
3145
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 0);
3146
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsChanged)), 0);
3147
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsRemoved)), 0);
3148
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::dataChanged)), 0);
3149
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsAdded)), 0);
3150
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::relationshipsRemoved)), 0);
3151
QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::selfContactIdChanged)), 0);
3155
QTestSignalSink casink(&lazy2, SIGNAL(contactsAdded(QList<QContactId>)));
3156
QTestSignalSink crsink(&lazy2, SIGNAL(contactsRemoved(QList<QContactId>)));
3157
QTestSignalSink cmsink(&lazy2, SIGNAL(contactsChanged(QList<QContactId>)));
3158
QTestSignalSink dcsink(&lazy2, SIGNAL(dataChanged()));
3159
QTestSignalSink rasink(&lazy2, SIGNAL(relationshipsAdded(QList<QContactId>)));
3160
QTestSignalSink rrsink(&lazy2, SIGNAL(relationshipsRemoved(QList<QContactId>)));
3161
QTestSignalSink scsink(&lazy2, SIGNAL(selfContactIdChanged(QContactId,QContactId)));
3163
// See if we got all the connections
3164
QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 7);
3165
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 1);
3166
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsChanged)), 1);
3167
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsRemoved)), 1);
3168
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::dataChanged)), 1);
3169
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsAdded)), 1);
3170
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsRemoved)), 1);
3171
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::selfContactIdChanged)), 1);
3173
QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 7);
3174
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 0);
3175
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsChanged)), 0);
3176
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsRemoved)), 0);
3177
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::dataChanged)), 0);
3178
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsAdded)), 0);
3179
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::relationshipsRemoved)), 0);
3180
QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::selfContactIdChanged)), 0);
3183
void tst_QContactManager::compareVariant()
3185
// Exercise this function a bit
3186
QFETCH(QVariant, a);
3187
QFETCH(QVariant, b);
3188
QFETCH(Qt::CaseSensitivity, cs);
3189
QFETCH(int, expected);
3191
int comparison = QContactManagerEngine::compareVariant(a, b, cs);
3192
// Since compareVariant is a little imprecise (just sign matters)
3193
// convert that here.
3196
else if (comparison > 0)
3199
QCOMPARE(comparison, expected);
3201
comparison = QContactManagerEngine::compareVariant(b, a, cs);
3204
else if (comparison > 0)
3207
// The sign should be flipped now
3208
QVERIFY((comparison + expected) == 0);
3211
void tst_QContactManager::compareVariant_data()
3213
QTest::addColumn<QVariant>("a");
3214
QTest::addColumn<QVariant>("b");
3216
QTest::addColumn<Qt::CaseSensitivity>("cs");
3217
QTest::addColumn<int>("expected");
3220
QTest::newRow("bool <") << QVariant(false) << QVariant(true) << Qt::CaseInsensitive << -1;
3221
QTest::newRow("bool =") << QVariant(false) << QVariant(false) << Qt::CaseInsensitive << -0;
3222
QTest::newRow("bool >") << QVariant(true) << QVariant(false) << Qt::CaseInsensitive << 1;
3224
// char (who uses these??)
3225
QTest::newRow("char <") << QVariant(QChar('a')) << QVariant(QChar('b')) << Qt::CaseInsensitive << -1;
3226
QTest::newRow("char < ci") << QVariant(QChar('A')) << QVariant(QChar('b')) << Qt::CaseInsensitive << -1;
3227
QTest::newRow("char < ci 2") << QVariant(QChar('a')) << QVariant(QChar('B')) << Qt::CaseInsensitive << -1;
3228
QTest::newRow("char < cs") << QVariant(QChar('a')) << QVariant(QChar('b')) << Qt::CaseSensitive << -1;
3229
QTest::newRow("char < cs") << QVariant(QChar('A')) << QVariant(QChar('b')) << Qt::CaseSensitive << -1;
3231
QTest::newRow("char = ci") << QVariant(QChar('a')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 0;
3232
QTest::newRow("char = ci 2") << QVariant(QChar('a')) << QVariant(QChar('A')) << Qt::CaseInsensitive << 0;
3233
QTest::newRow("char = ci 3") << QVariant(QChar('A')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 0;
3234
QTest::newRow("char = ci 4") << QVariant(QChar('A')) << QVariant(QChar('A')) << Qt::CaseInsensitive << 0;
3235
QTest::newRow("char = cs") << QVariant(QChar('a')) << QVariant(QChar('a')) << Qt::CaseSensitive << 0;
3236
QTest::newRow("char = cs 2") << QVariant(QChar('A')) << QVariant(QChar('A')) << Qt::CaseSensitive << 0;
3238
QTest::newRow("char >") << QVariant(QChar('b')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 1;
3239
QTest::newRow("char > ci") << QVariant(QChar('b')) << QVariant(QChar('A')) << Qt::CaseInsensitive << 1;
3240
QTest::newRow("char > ci 2") << QVariant(QChar('B')) << QVariant(QChar('a')) << Qt::CaseInsensitive << 1;
3241
QTest::newRow("char > cs") << QVariant(QChar('b')) << QVariant(QChar('a')) << Qt::CaseSensitive << 1;
3242
QTest::newRow("char > cs") << QVariant(QChar('b')) << QVariant(QChar('A')) << Qt::CaseSensitive << 1;
3244
// Some numeric types
3246
QTest::newRow("uint < boundary") << QVariant(uint(1)) << QVariant(uint(-1)) << Qt::CaseInsensitive << -1;
3247
QTest::newRow("uint <") << QVariant(uint(1)) << QVariant(uint(2)) << Qt::CaseInsensitive << -1;
3248
QTest::newRow("uint =") << QVariant(uint(2)) << QVariant(uint(2)) << Qt::CaseInsensitive << 0;
3249
QTest::newRow("uint = 0") << QVariant(uint(0)) << QVariant(uint(0)) << Qt::CaseInsensitive << 0;
3250
QTest::newRow("uint = boundary") << QVariant(uint(-1)) << QVariant(uint(-1)) << Qt::CaseInsensitive << 0;
3251
QTest::newRow("uint >") << QVariant(uint(5)) << QVariant(uint(2)) << Qt::CaseInsensitive << 1;
3252
QTest::newRow("uint > boundary") << QVariant(uint(-1)) << QVariant(uint(2)) << Qt::CaseInsensitive << 1; // boundary
3254
// int (hmm, signed 32 bit assumed)
3255
QTest::newRow("int < boundary") << QVariant(int(0x80000000)) << QVariant(int(0x7fffffff)) << Qt::CaseInsensitive << -1;
3256
QTest::newRow("int <") << QVariant(int(1)) << QVariant(int(2)) << Qt::CaseInsensitive << -1;
3257
QTest::newRow("int =") << QVariant(int(2)) << QVariant(int(2)) << Qt::CaseInsensitive << 0;
3258
QTest::newRow("int = 0") << QVariant(int(0)) << QVariant(int(0)) << Qt::CaseInsensitive << 0;
3259
QTest::newRow("int = boundary") << QVariant(int(0x80000000)) << QVariant(int(0x80000000)) << Qt::CaseInsensitive << 0;
3260
QTest::newRow("int >") << QVariant(int(5)) << QVariant(int(2)) << Qt::CaseInsensitive << 1;
3261
QTest::newRow("int > boundary") << QVariant(int(0x7fffffff)) << QVariant(int(0x80000000)) << Qt::CaseInsensitive << 1; // boundary
3264
QTest::newRow("ulonglong < boundary") << QVariant(qulonglong(1)) << QVariant(qulonglong(-1)) << Qt::CaseInsensitive << -1;
3265
QTest::newRow("ulonglong <") << QVariant(qulonglong(1)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << -1;
3266
QTest::newRow("ulonglong =") << QVariant(qulonglong(2)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << 0;
3267
QTest::newRow("ulonglong = 0") << QVariant(qulonglong(0)) << QVariant(qulonglong(0)) << Qt::CaseInsensitive << 0;
3268
QTest::newRow("ulonglong = boundary") << QVariant(qulonglong(-1)) << QVariant(qulonglong(-1)) << Qt::CaseInsensitive << 0;
3269
QTest::newRow("ulonglong >") << QVariant(qulonglong(5)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << 1;
3270
QTest::newRow("ulonglong > boundary") << QVariant(qulonglong(-1)) << QVariant(qulonglong(2)) << Qt::CaseInsensitive << 1; // boundary
3273
QTest::newRow("longlong < boundary") << QVariant(qlonglong(0x8000000000000000LL)) << QVariant(qlonglong(0x7fffffffffffffffLL)) << Qt::CaseInsensitive << -1;
3274
QTest::newRow("longlong <") << QVariant(qlonglong(1)) << QVariant(qlonglong(2)) << Qt::CaseInsensitive << -1;
3275
QTest::newRow("longlong =") << QVariant(qlonglong(2)) << QVariant(qlonglong(2)) << Qt::CaseInsensitive << 0;
3276
QTest::newRow("longlong = 0") << QVariant(qlonglong(0)) << QVariant(qlonglong(0)) << Qt::CaseInsensitive << 0;
3277
QTest::newRow("longlong = boundary") << QVariant(qlonglong(0x8000000000000000LL)) << QVariant(qlonglong(0x8000000000000000LL)) << Qt::CaseInsensitive << 0;
3278
QTest::newRow("longlong >") << QVariant(qlonglong(5)) << QVariant(qlonglong(2)) << Qt::CaseInsensitive << 1;
3279
QTest::newRow("longlong > boundary") << QVariant(qlonglong(0x7fffffffffffffffLL)) << QVariant(qlonglong(0x8000000000000000LL)) << Qt::CaseInsensitive << 1; // boundary
3281
// double (hmm, skips NaNs etc)
3282
QTest::newRow("double < inf 2") << QVariant(-qInf()) << QVariant(qInf()) << Qt::CaseInsensitive << -1;
3283
QTest::newRow("double < inf") << QVariant(1.0) << QVariant(qInf()) << Qt::CaseInsensitive << -1;
3284
QTest::newRow("double <") << QVariant(1.0) << QVariant(2.0) << Qt::CaseInsensitive << -1;
3285
QTest::newRow("double =") << QVariant(2.0) << QVariant(2.0) << Qt::CaseInsensitive << 0;
3286
QTest::newRow("double = 0") << QVariant(0.0) << QVariant(0.0) << Qt::CaseInsensitive << 0;
3287
QTest::newRow("double = inf") << QVariant(qInf()) << QVariant(qInf()) << Qt::CaseInsensitive << 0;
3288
QTest::newRow("double >") << QVariant(5.0) << QVariant(2.0) << Qt::CaseInsensitive << 1;
3289
QTest::newRow("double > inf") << QVariant(qInf()) << QVariant(5.0) << Qt::CaseInsensitive << 1;
3290
QTest::newRow("double > inf 2") << QVariant(0.0) << QVariant(-qInf()) << Qt::CaseInsensitive << 1;
3291
QTest::newRow("double > inf 3") << QVariant(qInf()) << QVariant(-qInf()) << Qt::CaseInsensitive << 1;
3294
QTest::newRow("string <") << QVariant(QString("a")) << QVariant(QString("b")) << Qt::CaseInsensitive << -1;
3295
QTest::newRow("string <") << QVariant(QString("a")) << QVariant(QString("B")) << Qt::CaseInsensitive << -1;
3296
QTest::newRow("string <") << QVariant(QString("A")) << QVariant(QString("b")) << Qt::CaseInsensitive << -1;
3297
QTest::newRow("string <") << QVariant(QString("A")) << QVariant(QString("B")) << Qt::CaseInsensitive << -1;
3298
QTest::newRow("string < cs") << QVariant(QString("a")) << QVariant(QString("b")) << Qt::CaseSensitive << -1;
3299
QTest::newRow("string < cs 2") << QVariant(QString("A")) << QVariant(QString("b")) << Qt::CaseSensitive << -1;
3301
QTest::newRow("string < length") << QVariant(QString("a")) << QVariant(QString("aa")) << Qt::CaseInsensitive << -1;
3302
QTest::newRow("string < length cs") << QVariant(QString("a")) << QVariant(QString("aa")) << Qt::CaseSensitive << -1;
3303
QTest::newRow("string < length 2") << QVariant(QString("a")) << QVariant(QString("ba")) << Qt::CaseInsensitive << -1;
3304
QTest::newRow("string < length cs 2") << QVariant(QString("a")) << QVariant(QString("ba")) << Qt::CaseSensitive << -1;
3306
QTest::newRow("string aa < b") << QVariant(QString("aa")) << QVariant(QString("b")) << Qt::CaseInsensitive << -1;
3307
QTest::newRow("string aa < b cs") << QVariant(QString("aa")) << QVariant(QString("b")) << Qt::CaseSensitive << -1;
3309
QTest::newRow("string '' < a") << QVariant(QString("")) << QVariant(QString("aa")) << Qt::CaseInsensitive << -1;
3310
QTest::newRow("string '' < aa cs") << QVariant(QString("")) << QVariant(QString("aa")) << Qt::CaseSensitive << -1;
3311
QTest::newRow("string 0 < a") << QVariant(QString()) << QVariant(QString("aa")) << Qt::CaseInsensitive << -1;
3312
QTest::newRow("string 0 < aa cs") << QVariant(QString()) << QVariant(QString("aa")) << Qt::CaseSensitive << -1;
3314
QTest::newRow("string '' = ''") << QVariant(QString("")) << QVariant(QString("")) << Qt::CaseInsensitive << 0;
3315
QTest::newRow("string '' = '' cs") << QVariant(QString("")) << QVariant(QString("")) << Qt::CaseSensitive << 0;
3316
QTest::newRow("string 0 = 0") << QVariant(QString()) << QVariant(QString()) << Qt::CaseInsensitive << 0;
3317
QTest::newRow("string 0 = 0 cs") << QVariant(QString()) << QVariant(QString()) << Qt::CaseSensitive << 0;
3318
QTest::newRow("string a = a") << QVariant(QString("a")) << QVariant(QString("a")) << Qt::CaseInsensitive << 0;
3319
QTest::newRow("string a = a cs") << QVariant(QString("a")) << QVariant(QString("a")) << Qt::CaseSensitive << 0;
3322
// {} < {"a"} < {"aa"} < {"aa","bb"} < {"aa", "cc"} < {"bb"}
3325
QStringList listA("a");
3326
QStringList listAA("aa");
3327
QStringList listAABB;
3328
listAABB << "aa" << "bb";
3329
QStringList listAACC;
3330
listAACC << "aa" << "cc";
3333
QStringList listCCAA;
3334
listCCAA << "cc" << "aa";
3335
QStringList listA2("A");
3336
QStringList listAA2("AA");
3338
QTest::newRow("stringlist {} < {a}") << QVariant(empty) << QVariant(listA) << Qt::CaseInsensitive << -1;
3339
QTest::newRow("stringlist {} < {a} cs") << QVariant(empty) << QVariant(listA) << Qt::CaseSensitive << -1;
3340
QTest::newRow("stringlist {} < {A}") << QVariant(empty) << QVariant(listA2) << Qt::CaseInsensitive << -1;
3341
QTest::newRow("stringlist {} < {A} cs") << QVariant(empty) << QVariant(listA2) << Qt::CaseSensitive << -1;
3343
QTest::newRow("stringlist {a} < {aa}") << QVariant(listA) << QVariant(listAA) << Qt::CaseInsensitive << -1;
3344
QTest::newRow("stringlist {a} < {aa} cs") << QVariant(listA) << QVariant(listAA) << Qt::CaseSensitive << -1;
3345
QTest::newRow("stringlist {a} < {AA}") << QVariant(listA) << QVariant(listAA2) << Qt::CaseInsensitive << -1;
3346
QTest::newRow("stringlist {a} < {AA} cs") << QVariant(listA) << QVariant(listAA2) << Qt::CaseSensitive << -1;
3348
QTest::newRow("stringlist {A} < {aa,bb}") << QVariant(listA2) << QVariant(listAABB) << Qt::CaseInsensitive << -1;
3349
QTest::newRow("stringlist {A} < {aa,bb} cs") << QVariant(listA2) << QVariant(listAABB) << Qt::CaseSensitive << -1;
3350
QTest::newRow("stringlist {aa} < {aa,bb}") << QVariant(listAA) << QVariant(listAABB) << Qt::CaseInsensitive << -1;
3351
QTest::newRow("stringlist {aa} < {aa,bb} cs") << QVariant(listAA) << QVariant(listAABB) << Qt::CaseSensitive << -1;
3353
QTest::newRow("stringlist {aa,bb} < {aa,cc}") << QVariant(listAABB) << QVariant(listAACC) << Qt::CaseInsensitive << -1;
3354
QTest::newRow("stringlist {aa,bb} < {aa,cc} cs") << QVariant(listAABB) << QVariant(listAACC) << Qt::CaseSensitive << -1;
3356
QTest::newRow("stringlist {aa,cc} < {bb}") << QVariant(listAACC) << QVariant(listBB) << Qt::CaseInsensitive << -1;
3357
QTest::newRow("stringlist {aa,cc} < {bb} cs") << QVariant(listAACC) << QVariant(listBB) << Qt::CaseSensitive << -1;
3360
QTest::newRow("stringlist {} = {}") << QVariant(empty) << QVariant(empty) << Qt::CaseInsensitive << 0;
3361
QTest::newRow("stringlist {} = {} cs") << QVariant(empty) << QVariant(empty) << Qt::CaseSensitive << 0;
3362
QTest::newRow("stringlist {aa} = {aa}") << QVariant(listAA) << QVariant(listAA) << Qt::CaseInsensitive << 0;
3363
QTest::newRow("stringlist {aa} = {AA}") << QVariant(listAA) << QVariant(listAA2) << Qt::CaseInsensitive << 0;
3364
QTest::newRow("stringlist {aa} = {aa} cs") << QVariant(listAA) << QVariant(listAA) << Qt::CaseSensitive << 0;
3371
QTime t4(23,59,59,999);
3373
QTest::newRow("times t0 < t1") << QVariant(t0) << QVariant(t1) << Qt::CaseInsensitive << -1;
3374
QTest::newRow("times t1 < t2") << QVariant(t1) << QVariant(t2) << Qt::CaseInsensitive << -1;
3375
QTest::newRow("times t2 < t3") << QVariant(t2) << QVariant(t3) << Qt::CaseInsensitive << -1;
3376
QTest::newRow("times t3 < t4") << QVariant(t3) << QVariant(t4) << Qt::CaseInsensitive << -1;
3377
QTest::newRow("times t0 = t0") << QVariant(t0) << QVariant(t0) << Qt::CaseInsensitive << 0;
3378
QTest::newRow("times t4 = t4") << QVariant(t4) << QVariant(t4) << Qt::CaseInsensitive << 0;
3382
QDate d1 = QDate::fromJulianDay(1);
3385
QDate d4 = QDate::fromJulianDay(0x7fffffff);
3386
QDate d5 = QDate::fromJulianDay(0x80000000);
3387
QDate d6 = QDate::fromJulianDay(0xffffffff);
3389
QTest::newRow("dates d0 < d1") << QVariant(d0) << QVariant(d1) << Qt::CaseInsensitive << -1;
3390
QTest::newRow("dates d1 < d2") << QVariant(d1) << QVariant(d2) << Qt::CaseInsensitive << -1;
3391
QTest::newRow("dates d2 < d3") << QVariant(d2) << QVariant(d3) << Qt::CaseInsensitive << -1;
3392
QTest::newRow("dates d3 < d4") << QVariant(d3) << QVariant(d4) << Qt::CaseInsensitive << -1;
3393
QTest::newRow("dates d4 < d5") << QVariant(d4) << QVariant(d5) << Qt::CaseInsensitive << -1;
3394
QTest::newRow("dates d5 < d6") << QVariant(d5) << QVariant(d6) << Qt::CaseInsensitive << -1;
3395
QTest::newRow("dates d0 < d6") << QVariant(d0) << QVariant(d6) << Qt::CaseInsensitive << -1;
3396
QTest::newRow("dates d1 < d6") << QVariant(d1) << QVariant(d6) << Qt::CaseInsensitive << -1;
3397
QTest::newRow("dates d0 = d0") << QVariant(d0) << QVariant(d0) << Qt::CaseInsensitive << 0;
3398
QTest::newRow("dates d1 = d1") << QVariant(d1) << QVariant(d1) << Qt::CaseInsensitive << 0;
3399
QTest::newRow("dates d2 = d2") << QVariant(d2) << QVariant(d2) << Qt::CaseInsensitive << 0;
3400
QTest::newRow("dates d3 = d3") << QVariant(d3) << QVariant(d3) << Qt::CaseInsensitive << 0;
3401
QTest::newRow("dates d4 = d4") << QVariant(d4) << QVariant(d4) << Qt::CaseInsensitive << 0;
3402
QTest::newRow("dates d5 = d5") << QVariant(d5) << QVariant(d5) << Qt::CaseInsensitive << 0;
3403
QTest::newRow("dates d6 = d6") << QVariant(d6) << QVariant(d6) << Qt::CaseInsensitive << 0;
3406
// Somewhat limited testing here
3408
QDateTime dt1(d1, t1);
3409
QDateTime dt2(d1, t2);
3410
QDateTime dt3(d4, t4);
3411
QDateTime dt4(d5, t1);
3412
QDateTime dt5(d6, t4); // end of the universe
3414
// Note: this test used to verify that null QDateTime compared less than a non-null date prior to 1AD
3415
// The current Qt behavior is to compare null as the UNIX epoch, so we will follow that
3416
QTest::newRow("datetimes dt0 > dt1") << QVariant(dt0) << QVariant(dt1) << Qt::CaseInsensitive << 1;
3417
QTest::newRow("datetimes dt1 < dt2") << QVariant(dt1) << QVariant(dt2) << Qt::CaseInsensitive << -1;
3418
QTest::newRow("datetimes dt2 < dt3") << QVariant(dt2) << QVariant(dt3) << Qt::CaseInsensitive << -1;
3419
QTest::newRow("datetimes dt3 < dt4") << QVariant(dt3) << QVariant(dt4) << Qt::CaseInsensitive << -1;
3420
QTest::newRow("datetimes dt4 < dt5") << QVariant(dt4) << QVariant(dt5) << Qt::CaseInsensitive << -1;
3421
QTest::newRow("datetimes dt0 < dt5") << QVariant(dt0) << QVariant(dt5) << Qt::CaseInsensitive << -1;
3422
QTest::newRow("datetimes dt1 < dt5") << QVariant(dt1) << QVariant(dt5) << Qt::CaseInsensitive << -1;
3423
QTest::newRow("datetimes dt0 = dt0") << QVariant(dt0) << QVariant(dt0) << Qt::CaseInsensitive << 0;
3424
QTest::newRow("datetimes dt1 = dt1") << QVariant(dt1) << QVariant(dt1) << Qt::CaseInsensitive << 0;
3425
QTest::newRow("datetimes dt2 = dt2") << QVariant(dt2) << QVariant(dt2) << Qt::CaseInsensitive << 0;
3426
QTest::newRow("datetimes dt3 = dt3") << QVariant(dt3) << QVariant(dt3) << Qt::CaseInsensitive << 0;
3427
QTest::newRow("datetimes dt4 = dt4") << QVariant(dt4) << QVariant(dt4) << Qt::CaseInsensitive << 0;
3428
QTest::newRow("datetimes dt5 = dt5") << QVariant(dt5) << QVariant(dt5) << Qt::CaseInsensitive << 0;
3431
QTEST_MAIN(tst_QContactManager)
3432
#include "tst_qcontactmanager.moc"