~renatofilho/vivid/qtpim-opensource-src

« back to all changes in this revision

Viewing changes to .pc/disable_failing_tests.patch/tests/auto/contacts/qcontactmanager/tst_qcontactmanager.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2014-05-15 09:27:46 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20140515092746-xfip01s9udpv1q06
Tags: 5.0~git20140515~29475884-0ubuntu1
* New upstream snapshot with several upstreamed fixes from renato
  - Remove also the following merged patches:
    Set-the-contact-detail-parent-to-avoid-memory-leak.patch
    Delete-declarative-contact-after-remove-it-from-the-.patch
  - A handful more of now failing upstream tests disabled

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the test suite of the Qt Toolkit.
 
7
**
 
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.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 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.
 
24
**
 
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.
 
28
**
 
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.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#define QT_STATICPLUGIN
 
43
 
 
44
#include <QtTest/QtTest>
 
45
#include <QtGlobal>
 
46
#include <QtCore/qnumeric.h>
 
47
 
 
48
#include <QtContacts>
 
49
#include "qcontactmanagerdataholder.h"
 
50
#include "jsondbprocess.h"
 
51
#include "qcontactidmock.h"
 
52
 
 
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
 
59
#endif
 
60
 
 
61
QTCONTACTS_USE_NAMESPACE
 
62
 
 
63
#define QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(params)  params.remove(QString::fromLatin1(QTCONTACTS_VERSION_NAME)); \
 
64
                                                          params.remove(QString::fromLatin1(QTCONTACTS_IMPLEMENTATION_VERSION_NAME))
 
65
 
 
66
#define QTRY_COMPARE_SIGNALS_LOCALID_COUNT(__signalSpy, __expectedCount) \
 
67
    do { \
 
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())); \
 
78
                   __spiedSigCount++; \
 
79
                } \
 
80
            } \
 
81
            if(__spiedSigCount == __expectedCount) { \
 
82
                break; \
 
83
            } \
 
84
            QTest::qWait(__step); \
 
85
        } \
 
86
        QCOMPARE(__spiedSigCount, __expectedCount); \
 
87
    } while(0)
 
88
 
 
89
//TESTED_COMPONENT=src/contacts
 
90
 
 
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>)
 
95
 
 
96
/* A class that no backend can support */
 
97
class UnsupportedMetatype {
 
98
    int foo;
 
99
};
 
100
Q_DECLARE_METATYPE(UnsupportedMetatype)
 
101
Q_DECLARE_METATYPE(QContact)
 
102
Q_DECLARE_METATYPE(QContactManager::Error)
 
103
Q_DECLARE_METATYPE(Qt::CaseSensitivity)
 
104
 
 
105
class tst_QContactManager : public QObject
 
106
{
 
107
Q_OBJECT
 
108
 
 
109
public:
 
110
    tst_QContactManager();
 
111
    virtual ~tst_QContactManager();
 
112
 
 
113
private:
 
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;
 
122
 
 
123
    JsonDbProcess m_jsondbProcess;
 
124
 
 
125
    QScopedPointer<QContactManagerDataHolder> managerDataHolder;
 
126
 
 
127
public slots:
 
128
    void initTestCase();
 
129
    void cleanupTestCase();
 
130
private slots:
 
131
 
 
132
    void doDump();
 
133
    void doDump_data() {addManagers();}
 
134
 
 
135
    /* Special test with special data */
 
136
    void uriParsing();
 
137
    void nameSynthesis();
 
138
 
 
139
    /* Tests that are run on all managers */
 
140
    void metadata();
 
141
    void nullIdOperations();
 
142
    void add();
 
143
    void update();
 
144
    void remove();
 
145
    void addAndUpdate();
 
146
    void batch();
 
147
    void observerDeletion();
 
148
    void signalEmission();
 
149
    void actionPreferences();
 
150
    void selfContactId();
 
151
    void detailOrders();
 
152
    void relationships();
 
153
    void contactType();
 
154
    void lateDeletion();
 
155
    void compareVariant();
 
156
 
 
157
#if defined(USE_VERSIT_PLZ)
 
158
    void partialSave();
 
159
    void partialSave_data() {addManagers();}
 
160
#endif
 
161
 
 
162
    /* Tests that take no data */
 
163
    void errorStayingPut();
 
164
    void ctors();
 
165
    void invalidManager();
 
166
    void memoryManager();
 
167
    void overrideManager();
 
168
    void changeSet();
 
169
    void fetchHint();
 
170
    void lazyConnections();
 
171
    void testInterSectionOfIdFilters();
 
172
    void testInterSectionOfIdAndDetailFilters();
 
173
 
 
174
    /* Special test with special data */
 
175
    void uriParsing_data();
 
176
    void nameSynthesis_data();
 
177
    void compareVariant_data();
 
178
 
 
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();}
 
196
};
 
197
 
 
198
// Helper class that connects to a signal on ctor, and disconnects on dtor
 
199
class QTestSignalSink : public QObject {
 
200
    Q_OBJECT
 
201
public:
 
202
    // signal and object must remain valid for the lifetime
 
203
    QTestSignalSink(QObject *object, const char *signal)
 
204
        : mObject(object), mSignal(signal)
 
205
    {
 
206
        connect(object, signal, this, SLOT(ignored()));
 
207
    }
 
208
 
 
209
    ~QTestSignalSink()
 
210
    {
 
211
        disconnect(mObject, mSignal, this, SLOT(ignored()));
 
212
    }
 
213
 
 
214
public slots:
 
215
    void ignored() {}
 
216
 
 
217
private:
 
218
    QObject *mObject;
 
219
    const char * const mSignal;
 
220
};
 
221
 
 
222
QT_BEGIN_NAMESPACE
 
223
static uint qHash(const QMetaMethod &m)
 
224
{
 
225
    return qHash(m.methodIndex());
 
226
}
 
227
QT_END_NAMESPACE
 
228
 
 
229
/* Two backends for testing lazy signal connections */
 
230
class QContactLazyEngine2 : public QContactManagerEngine
 
231
{
 
232
public:
 
233
    QContactLazyEngine2() {}
 
234
    QString managerName() const {return "lazy2";}
 
235
 
 
236
    /*! \reimp */
 
237
    int managerVersion() const {return 0;}
 
238
 
 
239
    void connectNotify(const QMetaMethod &signal)
 
240
    {
 
241
        connectionCounts[signal]++;
 
242
    }
 
243
    void disconnectNotify(const QMetaMethod &signal)
 
244
    {
 
245
        connectionCounts[signal]--;
 
246
    }
 
247
 
 
248
    static QHash<QMetaMethod, int> connectionCounts; // signal to count
 
249
};
 
250
QHash<QMetaMethod, int> QContactLazyEngine2::connectionCounts;
 
251
 
 
252
class QContactLazyEngine : public QContactManagerEngine
 
253
{
 
254
public:
 
255
    QContactLazyEngine() {}
 
256
    QString managerName() const {
 
257
        return "lazy";}
 
258
 
 
259
    /*! \reimp */
 
260
    int managerVersion() const {return 0;}
 
261
 
 
262
    void connectNotify(const QMetaMethod &signal)
 
263
    {
 
264
        connectionCounts[signal]++;
 
265
    }
 
266
    void disconnectNotify(const QMetaMethod &signal)
 
267
    {
 
268
        connectionCounts[signal]--;
 
269
    }
 
270
    static QHash<QMetaMethod, int> connectionCounts; // signal to count
 
271
};
 
272
QHash<QMetaMethod, int> QContactLazyEngine::connectionCounts;
 
273
 
 
274
/* Static lazy engine factory */
 
275
class LazyEngineFactory : public QContactManagerEngineFactory
 
276
{
 
277
    Q_OBJECT
 
278
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QContactManagerEngineFactoryInterface" FILE "lazy.json")
 
279
    public:
 
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";}
 
283
};
 
284
 
 
285
QContactManagerEngine* LazyEngineFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
 
286
{
 
287
    // Return one or the other
 
288
    Q_UNUSED(error)
 
289
    if (parameters.value("version") == QString("1"))
 
290
        return new QContactLazyEngine();
 
291
    else
 
292
        return new QContactLazyEngine2();
 
293
}
 
294
 
 
295
QContactEngineId* LazyEngineFactory::createContactEngineId(const QMap<QString, QString>& parameters, const QString& idString) const
 
296
{
 
297
    Q_UNUSED(parameters)
 
298
    Q_UNUSED(idString)
 
299
    return new QContactIdMock("",1);
 
300
}
 
301
 
 
302
tst_QContactManager::tst_QContactManager()
 
303
{
 
304
}
 
305
 
 
306
tst_QContactManager::~tst_QContactManager()
 
307
{
 
308
}
 
309
 
 
310
void tst_QContactManager::initTestCase()
 
311
{
 
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");
 
317
    }
 
318
 
 
319
    managerDataHolder.reset(new QContactManagerDataHolder());
 
320
 
 
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"));
 
326
}
 
327
 
 
328
void tst_QContactManager::cleanupTestCase()
 
329
{
 
330
    managerDataHolder.reset(0);
 
331
 
 
332
    if (QContactManager::availableManagers().contains("jsondb"))
 
333
        m_jsondbProcess.terminate();
 
334
}
 
335
 
 
336
void tst_QContactManager::dumpContactDifferences(const QContact& ca, const QContact& cb)
 
337
{
 
338
    // Try to narrow down the differences
 
339
    QContact a(ca);
 
340
    QContact b(cb);
 
341
 
 
342
    QContactName n1 = a.detail(QContactName::Type);
 
343
    QContactName n2 = b.detail(QContactName::Type);
 
344
 
 
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());
 
351
 
 
352
    // Now look at the rest
 
353
    QList<QContactDetail> aDetails = a.details();
 
354
    QList<QContactDetail> bDetails = b.details();
 
355
 
 
356
    // They can be in any order, so loop
 
357
    // First remove any matches
 
358
    foreach(QContactDetail d, aDetails) {
 
359
        foreach(QContactDetail d2, bDetails) {
 
360
            if(d == d2) {
 
361
                a.removeDetail(&d);
 
362
                b.removeDetail(&d2);
 
363
                break;
 
364
            }
 
365
        }
 
366
    }
 
367
 
 
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();
 
375
    }
 
376
    // and same for B
 
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();
 
380
    }
 
381
 
 
382
    if (a.type() != b.type()) {
 
383
        qDebug() << "A contact type =" << a.type();
 
384
        qDebug() << "B contact type =" << b.type();
 
385
    }
 
386
}
 
387
 
 
388
bool tst_QContactManager::isSuperset(const QContact& ca, const QContact& cb)
 
389
{
 
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.
 
394
 
 
395
    QContact a(ca);
 
396
    QContact b(cb);
 
397
    QList<QContactDetail> aDetails = a.details();
 
398
    QList<QContactDetail> bDetails = b.details();
 
399
 
 
400
    // They can be in any order, so loop
 
401
    // First remove any matches
 
402
    foreach(QContactDetail d, aDetails) {
 
403
        foreach(QContactDetail d2, bDetails) {
 
404
            if(d == d2) {
 
405
                a.removeDetail(&d);
 
406
                b.removeDetail(&d2);
 
407
                break;
 
408
            }
 
409
        }
 
410
    }
 
411
 
 
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
 
424
                        // change the value.
 
425
                        canRemove = false;
 
426
                    }
 
427
                }
 
428
 
 
429
                if (canRemove) {
 
430
                    // if we get to here, we can remove the details.
 
431
                    a.removeDetail(&d);
 
432
                    b.removeDetail(&d2);
 
433
                    break;
 
434
                }
 
435
            }
 
436
        }
 
437
    }
 
438
 
 
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.
 
446
 
 
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)))
 
451
        return false;
 
452
    return true;
 
453
}
 
454
 
 
455
void tst_QContactManager::dumpContact(const QContact& contact)
 
456
{
 
457
    QContactManager m;
 
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();
 
463
    }
 
464
}
 
465
 
 
466
void tst_QContactManager::dumpContacts(QContactManager *cm)
 
467
{
 
468
    QList<QContactId> ids = cm->contactIds();
 
469
 
 
470
    qDebug() << "There are" << ids.count() << "contacts in" << cm->managerUri();
 
471
 
 
472
    foreach (QContactId id, ids) {
 
473
        QContact c = cm->contact(id);
 
474
        dumpContact(c);
 
475
    }
 
476
}
 
477
 
 
478
void tst_QContactManager::uriParsing_data()
 
479
{
 
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");
 
484
 
 
485
    QMap<QString, QString> inparameters;
 
486
    inparameters.insert("foo", "bar");
 
487
    inparameters.insert("bazflag", QString());
 
488
    inparameters.insert("bar", "glob");
 
489
 
 
490
    QMap<QString, QString> inparameters2;
 
491
    inparameters2.insert("this has spaces", QString());
 
492
    inparameters2.insert("and& an", " &amp;");
 
493
    inparameters2.insert("and an ", "=quals");
 
494
 
 
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;
 
517
}
 
518
 
 
519
void tst_QContactManager::addManagers()
 
520
{
 
521
    QTest::addColumn<QString>("uri");
 
522
 
 
523
    QStringList managers = QContactManager::availableManagers();
 
524
 
 
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");
 
531
 
 
532
    // "internal" engines
 
533
    managers.removeAll("social");
 
534
    managers.removeAll("simcard");
 
535
    managers.removeAll("com.nokia.messaging.contacts.engines.mail.contactslookup");
 
536
 
 
537
 
 
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);
 
544
        }
 
545
    }
 
546
}
 
547
 
 
548
/*
 
549
 * Helper method for creating a QContact instance with name and phone number
 
550
 * details.
 
551
 */
 
552
QContact tst_QContactManager::createContact(
 
553
    QString firstName,
 
554
    QString lastName,
 
555
    QString phoneNumber)
 
556
{
 
557
    QContact contact;
 
558
    QContactName n;
 
559
 
 
560
    if (!firstName.isEmpty()) {
 
561
        n.setFirstName(firstName);
 
562
    };
 
563
    if (!lastName.isEmpty()) {
 
564
        n.setLastName(lastName);
 
565
    }
 
566
    if (!n.isEmpty()) {
 
567
        contact.saveDetail(&n);
 
568
    }
 
569
 
 
570
    if (!phoneNumber.isEmpty()) {
 
571
        QContactPhoneNumber ph;
 
572
        ph.setNumber(phoneNumber);
 
573
        contact.saveDetail(&ph);
 
574
    }
 
575
 
 
576
    return contact;
 
577
}
 
578
 
 
579
void tst_QContactManager::saveContactName(QContact *contact, QContactName *contactName, const QString &name) const
 
580
{
 
581
    contactName->setFirstName(name);
 
582
    contactName->setLastName(name);
 
583
     contact->saveDetail(contactName);
 
584
}
 
585
 
 
586
void tst_QContactManager::metadata()
 
587
{
 
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());
 
592
}
 
593
 
 
594
 
 
595
void tst_QContactManager::nullIdOperations()
 
596
{
 
597
    QFETCH(QString, uri);
 
598
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
599
    QVERIFY(!cm->removeContact(QContactId()));
 
600
    QVERIFY(cm->error() == QContactManager::DoesNotExistError);
 
601
 
 
602
 
 
603
    QContact c = cm->contact(QContactId());
 
604
    QVERIFY(c.id() == QContactId());
 
605
    QVERIFY(c.isEmpty());
 
606
    QVERIFY(cm->error() == QContactManager::DoesNotExistError);
 
607
}
 
608
 
 
609
void tst_QContactManager::uriParsing()
 
610
{
 
611
    QFETCH(QString, uri);
 
612
    QFETCH(bool, good);
 
613
    QFETCH(QString, manager);
 
614
    QFETCH(tst_QContactManager_QStringMap, parameters);
 
615
 
 
616
    QString outmanager;
 
617
    QMap<QString, QString> outparameters;
 
618
 
 
619
    if (good) {
 
620
        /* Good split */
 
621
        /* Test splitting */
 
622
        QVERIFY(QContactManager::parseUri(uri, 0, 0)); // no out parms
 
623
 
 
624
        // 1 out param
 
625
        QVERIFY(QContactManager::parseUri(uri, &outmanager, 0));
 
626
        QCOMPARE(manager, outmanager);
 
627
        QVERIFY(QContactManager::parseUri(uri, 0, &outparameters));
 
628
 
 
629
        QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters);
 
630
 
 
631
        QCOMPARE(parameters, outparameters);
 
632
 
 
633
        outmanager.clear();
 
634
        outparameters.clear();
 
635
        QVERIFY(QContactManager::parseUri(uri, &outmanager, &outparameters));
 
636
 
 
637
        QCONTACTMANAGER_REMOVE_VERSIONS_FROM_URI(outparameters);
 
638
 
 
639
        QCOMPARE(manager, outmanager);
 
640
        QCOMPARE(parameters, outparameters);
 
641
    } else {
 
642
        /* bad splitting */
 
643
        outmanager.clear();
 
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());
 
651
 
 
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);
 
660
    }
 
661
}
 
662
 
 
663
void tst_QContactManager::ctors()
 
664
{
 
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);
 
669
 
 
670
    qDebug() << "Available managers:" << QContactManager::availableManagers();
 
671
 
 
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");
 
677
 
 
678
    QObject parent;
 
679
 
 
680
    QContactManager cm; // default
 
681
    QContactManager cm2(defaultStore);
 
682
    QContactManager cm3(defaultStore, QMap<QString, QString>());
 
683
 
 
684
    QContactManager cm9b(0); // QObject* ctor, should be same as cm2 etc
 
685
    QContactManager cm9c(&parent); // same as cm2 etc.
 
686
 
 
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));
 
690
 
 
691
    QVERIFY(cm9->parent() == &parent);
 
692
    QVERIFY(cm9b.parent() == 0);
 
693
    QVERIFY(cm9c.parent() == &parent);
 
694
 
 
695
 
 
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());
 
710
 
 
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);
 
715
 
 
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()));
 
720
 
 
721
 
 
722
    /*
 
723
     * Sets of stores that should be equivalent:
 
724
     * - 1, 2, 4, 5
 
725
     * - 3, 6
 
726
     */
 
727
 
 
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());
 
735
 
 
736
    QVERIFY(em3.managerUri() == em6->managerUri());
 
737
 
 
738
    /* Test the stores that should not be the same */
 
739
    QVERIFY(em.managerUri() != em3.managerUri());
 
740
    QVERIFY(em.managerUri() != em6->managerUri());
 
741
 
 
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.
 
754
 
 
755
 
 
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"));
 
761
#else
 
762
    QCOMPARE(defaultStore, QString("invalid"));
 
763
#endif
 
764
}
 
765
 
 
766
void tst_QContactManager::doDump()
 
767
{
 
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));
 
772
 
 
773
        dumpContacts(cm.data());
 
774
    }
 
775
}
 
776
 
 
777
Q_DECLARE_METATYPE(QVariant)
 
778
 
 
779
 
 
780
void tst_QContactManager::add()
 
781
{
 
782
    QFETCH(QString, uri);
 
783
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
784
 
 
785
    QContact alice = createContact("Alice", "inWonderland", "1234567");
 
786
    int currCount = cm->contactIds().count();
 
787
    QVERIFY(cm->saveContact(&alice));
 
788
    QVERIFY(cm->error() == QContactManager::NoError);
 
789
 
 
790
    QVERIFY(!alice.id().managerUri().isEmpty());
 
791
    QVERIFY(!(alice.id().isNull()));
 
792
    QCOMPARE(cm->contactIds().count(), currCount+1);
 
793
 
 
794
    QContact added = cm->contact(alice.id());
 
795
    QVERIFY(added.id() == alice.id());
 
796
 
 
797
    if (!isSuperset(added, alice)) {
 
798
        dumpContacts(cm.data());
 
799
        dumpContactDifferences(added, alice);
 
800
        QCOMPARE(added, alice);
 
801
    }
 
802
 
 
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));
 
812
    }
 
813
 
 
814
    // check that all the numbers were added successfully
 
815
    QVERIFY(veryContactable.details(QContactPhoneNumber::Type).size() == nrOfdetails);
 
816
 
 
817
    // check if it can be saved
 
818
    QVERIFY(cm->saveContact(&veryContactable));
 
819
 
 
820
    // verify save
 
821
    QContact retrievedContactable = cm->contact(veryContactable.id());
 
822
    if (!isSuperset(retrievedContactable, veryContactable)) {
 
823
        dumpContactDifferences(veryContactable, retrievedContactable);
 
824
        QCOMPARE(veryContactable, retrievedContactable);
 
825
    }
 
826
}
 
827
 
 
828
void tst_QContactManager::testInterSectionOfIdAndDetailFilters()
 
829
{
 
830
    QFETCH(QString, uri);
 
831
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
832
 
 
833
    //prepare filter data
 
834
    QContact alice = createContact("Alice", "inWonderland", "1234567");
 
835
    QVERIFY(cm->saveContact(&alice));
 
836
 
 
837
    QContact john = createContact("John", "inFinland", "2345678");
 
838
    QVERIFY(cm->saveContact(&john));
 
839
 
 
840
    QContactIdFilter idFilter1;
 
841
    QList<QContactId> contactIdList;
 
842
    contactIdList.append(alice.id());
 
843
    idFilter1.setIds(contactIdList);
 
844
 
 
845
    QContactDetailFilter df;
 
846
    df.setDetailType(QContactName::Type,QContactName::FieldFirstName);
 
847
    df.setValue("Alice");
 
848
 
 
849
    contactIdList.clear();
 
850
 
 
851
    QContactIntersectionFilter isf;
 
852
    isf.append(idFilter1);
 
853
    isf.append(df);
 
854
 
 
855
    //Intersection filter of a matching Idfilter and detailfilter
 
856
    QList<QContact> contactList = cm->contacts(isf);
 
857
    QCOMPARE(contactList.size(), 1);
 
858
 
 
859
    contactIdList.clear();
 
860
 
 
861
    //Intersection filter of a non matching Idfilter and detailfilter
 
862
    isf.remove(df);
 
863
    df.setValue("John");
 
864
    isf.append(df);
 
865
 
 
866
    contactList = cm->contacts(isf);
 
867
    QCOMPARE(contactList.size(), 0);
 
868
}
 
869
 
 
870
void tst_QContactManager::testInterSectionOfIdFilters()
 
871
{
 
872
    QFETCH(QString, uri);
 
873
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
874
 
 
875
    //prepare filter data
 
876
    QContact alice = createContact("Alice", "inWonderland", "1234567");
 
877
    QVERIFY(cm->saveContact(&alice));
 
878
 
 
879
    QContact john = createContact("John", "inFinland", "2345678");
 
880
    QVERIFY(cm->saveContact(&john));
 
881
 
 
882
    QContactIdFilter idFilter1;
 
883
    QList<QContactId> contactIdList;
 
884
    contactIdList.append(alice.id());
 
885
    idFilter1.setIds(contactIdList);
 
886
 
 
887
    QContactIdFilter idFilter2;
 
888
    contactIdList.clear();
 
889
    contactIdList.append(john.id());
 
890
    idFilter2.setIds(contactIdList);
 
891
 
 
892
    contactIdList.clear();
 
893
 
 
894
    //Test intersection filter with two different idFilters
 
895
    QContactIntersectionFilter isf;
 
896
    isf.append(idFilter1);
 
897
    isf.append(idFilter2);
 
898
 
 
899
    QList<QContact> contactList = cm->contacts(idFilter1);
 
900
    QCOMPARE(contactList.size(), 1);
 
901
    QCOMPARE(contactList.at(0).id(), alice.id());
 
902
 
 
903
    contactIdList.clear();
 
904
 
 
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);
 
909
 
 
910
 
 
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);
 
916
 
 
917
    contactIdList.clear();
 
918
 
 
919
    isf.append(idFilter2);
 
920
    contactList = cm->contacts(isf);
 
921
    QCOMPARE(contactList.size(), 1);
 
922
 
 
923
    contactIdList.clear();
 
924
 
 
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
 
929
 
 
930
    contactIdList << alice.id() << john.id();
 
931
    idFilter2.setIds(contactIdList);
 
932
    isf.append(idFilter2);
 
933
 
 
934
    contactIdList.clear();
 
935
 
 
936
    contactList = cm->contacts(isf);
 
937
    QCOMPARE(contactList.size(), 1);
 
938
    QCOMPARE(contactList.at(0).id(), alice.id());
 
939
 
 
940
    //clean up filters and the contactIdList
 
941
    isf.remove(idFilter2);
 
942
    isf.remove(idFilter1);
 
943
    contactIdList.clear();
 
944
 
 
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);
 
957
 
 
958
    //clean up filters and the contactIdList
 
959
    isf.remove(idFilter2);
 
960
    isf.remove(idFilter1);
 
961
    contactIdList.clear();
 
962
 
 
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();
 
968
 
 
969
    contactIdList.append(john.id());
 
970
    idFilter2.setIds(contactIdList);
 
971
    contactIdList.clear();
 
972
 
 
973
    QContactIdFilter idFilter3;
 
974
    contactIdList.append(john.id());
 
975
    idFilter3.setIds(contactIdList);
 
976
    contactIdList.clear();
 
977
 
 
978
    isf.append(idFilter1);
 
979
    isf.append(idFilter2);
 
980
    isf.append(idFilter3);
 
981
 
 
982
    QCOMPARE(isf.filters().size(), 3);
 
983
    contactList = cm->contacts(isf);
 
984
    QCOMPARE(contactList.size(), 0);
 
985
 
 
986
    //clean up filters and the contactIdList
 
987
    isf.remove(idFilter1);
 
988
    isf.remove(idFilter2);
 
989
    isf.remove(idFilter3);
 
990
    contactIdList.clear();
 
991
}
 
992
 
 
993
void tst_QContactManager::update()
 
994
{
 
995
    QFETCH(QString, uri);
 
996
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
997
 
 
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);
 
1005
 
 
1006
    /* Update name */
 
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
 
1020
 
 
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
 
1028
 
 
1029
    // This test is dangerous, since backends can add timestamps etc...
 
1030
    detailCount += 1;
 
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
 
1047
 
 
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
 
1050
 
 
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
 
1058
 
 
1059
    // This test is dangerous, since backends can add timestamps etc...
 
1060
    //detailCount -= 1;
 
1061
    //QCOMPARE(detailCount, alice.details().size()); // removing a detail should cause the detail count to decrease by one.
 
1062
 
 
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);
 
1071
 
 
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);
 
1079
    }
 
1080
}
 
1081
 
 
1082
void tst_QContactManager::remove()
 
1083
{
 
1084
    QFETCH(QString, uri);
 
1085
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
1086
 
 
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());
 
1092
 
 
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);
 
1099
}
 
1100
 
 
1101
void tst_QContactManager::addAndUpdate()
 
1102
{
 
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;
 
1114
    }
 
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);
 
1124
    }
 
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);
 
1132
    }
 
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()));
 
1138
    }
 
1139
}
 
1140
 
 
1141
void tst_QContactManager::batch()
 
1142
{
 
1143
    QFETCH(QString, uri);
 
1144
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
1145
 
 
1146
    /* First test null pointer operations */
 
1147
    QVERIFY(!cm->saveContacts(NULL, NULL));
 
1148
    QVERIFY(cm->error() == QContactManager::BadArgumentError);
 
1149
 
 
1150
    QVERIFY(!cm->removeContacts(QList<QContactId>(), NULL));
 
1151
    QVERIFY(cm->error() == QContactManager::BadArgumentError);
 
1152
 
 
1153
    // Get supported name field
 
1154
    int nameField = QContactName::FieldFirstName;
 
1155
 
 
1156
    /* Now add 3 contacts, all valid */
 
1157
    QContact a;
 
1158
    QContactName na;
 
1159
    na.setValue(nameField, "XXXXXX Albert");
 
1160
    a.saveDetail(&na);
 
1161
 
 
1162
    QContact b;
 
1163
    QContactName nb;
 
1164
    nb.setValue(nameField, "XXXXXX Bob");
 
1165
    b.saveDetail(&nb);
 
1166
 
 
1167
    QContact c;
 
1168
    QContactName nc;
 
1169
    nc.setValue(nameField, "XXXXXX Carol");
 
1170
    c.saveDetail(&nc);
 
1171
 
 
1172
    QList<QContact> contacts;
 
1173
    contacts << a << b << c;
 
1174
 
 
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);
 
1181
 
 
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());
 
1187
 
 
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);
 
1191
 
 
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);
 
1199
 
 
1200
    /* Save again, with a null error map */
 
1201
    QVERIFY(cm->saveContacts(&contacts, NULL));
 
1202
    QVERIFY(cm->error() == QContactManager::NoError);
 
1203
 
 
1204
    /* Now make an update to them all */
 
1205
    QContactPhoneNumber number;
 
1206
    number.setNumber("1234567");
 
1207
 
 
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));
 
1213
 
 
1214
    QVERIFY(cm->saveContacts(&contacts, &errorMap));
 
1215
    QVERIFY(cm->error() == QContactManager::NoError);
 
1216
    QVERIFY(errorMap.count() == 0);
 
1217
 
 
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);
 
1225
 
 
1226
    QVERIFY(a.details<QContactPhoneNumber>().count() == 1);
 
1227
    QVERIFY(b.details<QContactPhoneNumber>().count() == 1);
 
1228
    QVERIFY(c.details<QContactPhoneNumber>().count() == 1);
 
1229
 
 
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");
 
1233
 
 
1234
    /* Retrieve them with the batch ID fetch API */
 
1235
    QList<QContactId> batchIds;
 
1236
    batchIds << a.id() << b.id() << c.id();
 
1237
 
 
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);
 
1245
 
 
1246
    // With error map
 
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);
 
1254
 
 
1255
    /* Now an empty id */
 
1256
    batchIds.clear();
 
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);
 
1265
 
 
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);
 
1275
 
 
1276
    /* Now multiple of the same contact */
 
1277
    batchIds.clear();
 
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);
 
1288
 
 
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);
 
1295
 
 
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);
 
1306
 
 
1307
    /* Now try removing with all invalid ids (e.g. the ones we just removed) */
 
1308
    ids.clear();
 
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);
 
1316
 
 
1317
    /* And again with a null error map */
 
1318
    QVERIFY(!cm->removeContacts(ids, NULL));
 
1319
    QVERIFY(cm->error() == QContactManager::DoesNotExistError);
 
1320
 
 
1321
    /* Try adding some new ones again, this time one with an error */
 
1322
    contacts.clear();
 
1323
    a.setId(QContactId());
 
1324
    b.setId(QContactId());
 
1325
    c.setId(QContactId());
 
1326
 
 
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");
 
1330
    b.saveDetail(&bad);
 
1331
 
 
1332
    contacts << a << b << c;
 
1333
 
 
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);
 
1339
 
 
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));
 
1345
 
 
1346
    /* Now delete 3 items, but with one bad argument */
 
1347
    ids.clear();
 
1348
    ids << contacts.at(0).id();
 
1349
    ids << removedId;
 
1350
    ids << contacts.at(2).id();
 
1351
 
 
1352
    QVERIFY(!cm->removeContacts(ids, &errorMap));
 
1353
    QVERIFY(cm->error() != QContactManager::NoError);
 
1354
 
 
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);
 
1358
 
 
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());
 
1363
    } else {
 
1364
        QVERIFY(contacts.at(0).id() != QContactId());
 
1365
    }
 
1366
 
 
1367
    /* B should definitely have failed */
 
1368
    QVERIFY(errorMap.value(1) == QContactManager::DoesNotExistError);
 
1369
    QVERIFY(ids.at(1) == removedId);
 
1370
 
 
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());
 
1375
    } else {
 
1376
        QVERIFY(contacts.at(2).id() != QContactId());
 
1377
    }
 
1378
}
 
1379
 
 
1380
void tst_QContactManager::invalidManager()
 
1381
{
 
1382
    /* Create an invalid manager */
 
1383
    QContactManager manager("this should never work");
 
1384
    QVERIFY(manager.managerName() == "invalid");
 
1385
    QVERIFY(manager.managerVersion() == 0);
 
1386
 
 
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);
 
1391
 
 
1392
    /* Now test that all the operations fail */
 
1393
    QVERIFY(manager.contactIds().count() == 0);
 
1394
    QVERIFY(manager.error() == QContactManager::NotSupportedError);
 
1395
 
 
1396
    QContact foo;
 
1397
    QContactName nf;
 
1398
    nf.setLastName("Lastname");
 
1399
    foo.saveDetail(&nf);
 
1400
 
 
1401
    QVERIFY(manager.error() == QContactManager::NotSupportedError);
 
1402
 
 
1403
    QVERIFY(manager.saveContact(&foo) == false);
 
1404
    QVERIFY(manager.error() == QContactManager::NotSupportedError);
 
1405
    QVERIFY(foo.id() == QContactId());
 
1406
    QVERIFY(manager.contactIds().count() == 0);
 
1407
 
 
1408
    QVERIFY(manager.contact(foo.id()).id() == QContactId());
 
1409
    QVERIFY(manager.contact(foo.id()).isEmpty());
 
1410
    QVERIFY(manager.error() == QContactManager::NotSupportedError);
 
1411
 
 
1412
    QVERIFY(manager.removeContact(foo.id()) == false);
 
1413
    QVERIFY(manager.error() == QContactManager::NotSupportedError);
 
1414
 
 
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);
 
1421
 
 
1422
    /* filters */
 
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);
 
1434
 
 
1435
    QVERIFY(manager.isFilterSupported(f) == false);
 
1436
    QVERIFY(manager.isFilterSupported(df) == false);
 
1437
 
 
1438
    QList<QContact> list;
 
1439
    list << foo;
 
1440
 
 
1441
    QVERIFY(!manager.saveContacts(&list, &errorMap));
 
1442
    QVERIFY(errorMap.count() == 0);
 
1443
    QVERIFY(manager.error() == QContactManager::NotSupportedError);
 
1444
 
 
1445
    QVERIFY(!manager.removeContacts(QList<QContactId>(), &errorMap));
 
1446
    QVERIFY(errorMap.count() == 0);
 
1447
    QVERIFY(manager.error() == QContactManager::BadArgumentError);
 
1448
 
 
1449
    QList<QContactId> idlist;
 
1450
    idlist << foo.id();
 
1451
    QVERIFY(!manager.removeContacts(idlist, &errorMap));
 
1452
    QVERIFY(errorMap.count() == 0);
 
1453
    QVERIFY(manager.error() == QContactManager::NotSupportedError);
 
1454
 
 
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);
 
1460
 
 
1461
    /* Relationships */
 
1462
    QContact one, two;
 
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);
 
1476
 
 
1477
    /* Capabilities */
 
1478
    QVERIFY(manager.supportedDataTypes().count() == 0);
 
1479
}
 
1480
 
 
1481
void tst_QContactManager::memoryManager()
 
1482
{
 
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
 
1492
 
 
1493
    // add a contact to each of m1, m2, m3
 
1494
    QContact c;
 
1495
    QContactName nc;
 
1496
    nc.setFirstName("John");
 
1497
    nc.setLastName("Civilian");
 
1498
    c.saveDetail(&nc);
 
1499
    m1.saveContact(&c);
 
1500
    c.setId(QContactId());
 
1501
    QContact c2;
 
1502
    QContactName nc2 = c2.detail(QContactName::Type);
 
1503
    c2 = c;
 
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());
 
1509
    nc.setSuffix("MD");
 
1510
    c.saveDetail(&nc);
 
1511
    m3.saveContact(&c);
 
1512
 
 
1513
    /* test that m1 != m2 != m3 and that m3 == m4 */
 
1514
 
 
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);
 
1521
 
 
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);
 
1529
 
 
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)));
 
1536
 
 
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);
 
1542
}
 
1543
 
 
1544
void tst_QContactManager::overrideManager()
 
1545
{
 
1546
    QString defaultStore = QContactManager::availableManagers().value(0);
 
1547
 
 
1548
    // preserve existing environment override
 
1549
    QString overrideManager = qgetenv("QTCONTACTS_MANAGER_OVERRIDE");
 
1550
 
 
1551
    // override with specific managers
 
1552
    qputenv("QTCONTACTS_MANAGER_OVERRIDE", "memory");
 
1553
    QContactManager m1;
 
1554
    QCOMPARE(m1.managerName(), QString::fromLatin1("memory"));
 
1555
 
 
1556
    qputenv("QTCONTACTS_MANAGER_OVERRIDE", "invalid");
 
1557
    QContactManager m2;
 
1558
    QCOMPARE(m2.managerName(), QString::fromLatin1("invalid"));
 
1559
 
 
1560
    qputenv("QTCONTACTS_MANAGER_OVERRIDE", "");
 
1561
    QContactManager m3;
 
1562
    QCOMPARE(m3.managerName(), defaultStore);
 
1563
 
 
1564
    qputenv("QTCONTACTS_MANAGER_OVERRIDE", overrideManager.toLatin1());
 
1565
}
 
1566
 
 
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()
 
1570
{
 
1571
    QFETCH(QString, uri);
 
1572
    QString managerName;
 
1573
    QMap<QString, QString> managerParameters;
 
1574
    QContactManager::parseUri(uri, &managerName, &managerParameters);
 
1575
    if (managerName != QString("symbian"))
 
1576
        return;
 
1577
 
 
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();
 
1583
 
 
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();
 
1590
 
 
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);
 
1596
 
 
1597
    // save the updated contact.
 
1598
    cntdb->CommitContactL(*testItem);
 
1599
    cntdb->CloseContactL(testItem->Id());
 
1600
    CleanupStack::PopAndDestroy(2); // testItem, cntdb
 
1601
 
 
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();
 
1605
}
 
1606
#endif
 
1607
 
 
1608
void tst_QContactManager::nameSynthesis_data()
 
1609
{
 
1610
    QTest::addColumn<QString>("expected");
 
1611
 
 
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");
 
1618
 
 
1619
    QTest::addColumn<bool>("addcompany");
 
1620
    QTest::addColumn<QString>("company");
 
1621
 
 
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");
 
1628
 
 
1629
    QTest::addColumn<bool>("addcompany2");
 
1630
    QTest::addColumn<QString>("secondcompany");
 
1631
 
 
1632
    QString e; // empty string.. gets a work out
 
1633
 
 
1634
    /* Various empty ones */
 
1635
    QTest::newRow("empty contact") << e
 
1636
            << false << e << e << e << e << e
 
1637
            << false << e
 
1638
            << false << e << e << e << e << e
 
1639
            << false << e;
 
1640
    QTest::newRow("empty name") << e
 
1641
            << true << e << e << e << e << e
 
1642
            << false << e
 
1643
            << false << e << e << e << e << e
 
1644
            << false << e;
 
1645
    QTest::newRow("empty names") << e
 
1646
            << true << e << e << e << e << e
 
1647
            << false << e
 
1648
            << true << e << e << e << e << e
 
1649
            << false << e;
 
1650
    QTest::newRow("empty org") << e
 
1651
            << false << e << e << e << e << e
 
1652
            << true << e
 
1653
            << false << e << e << e << e << e
 
1654
            << true << e;
 
1655
    QTest::newRow("empty orgs") << e
 
1656
            << false << e << e << e << e << e
 
1657
            << true << e
 
1658
            << false << e << e << e << e << e
 
1659
            << true << e;
 
1660
    QTest::newRow("empty orgs and names") << e
 
1661
            << true << e << e << e << e << e
 
1662
            << true << e
 
1663
            << true << e << e << e << e << e
 
1664
            << true << e;
 
1665
 
 
1666
    /* Single values */
 
1667
    QTest::newRow("prefix") << "Prefix"
 
1668
            << true << "Prefix" << e << e << e << e
 
1669
            << false << e
 
1670
            << false << e << e << e << e << e
 
1671
            << false << e;
 
1672
    QTest::newRow("first") << "First"
 
1673
            << true << e << "First" << e << e << e
 
1674
            << false << e
 
1675
            << false << e << e << e << e << e
 
1676
            << false << e;
 
1677
    QTest::newRow("middle") << "Middle"
 
1678
            << true << e << e << "Middle" << e << e
 
1679
            << false << e
 
1680
            << false << e << e << e << e << e
 
1681
            << false << e;
 
1682
    QTest::newRow("last") << "Last"
 
1683
            << true << e << e << e << "Last" << e
 
1684
            << false << e
 
1685
            << false << e << e << e << e << e
 
1686
            << false << e;
 
1687
    QTest::newRow("suffix") << "Suffix"
 
1688
            << true << e << e << e << e << "Suffix"
 
1689
            << false << e
 
1690
            << false << e << e << e << e << e
 
1691
            << false << e;
 
1692
 
 
1693
    /* Single values in the second name */
 
1694
    QTest::newRow("prefix in second") << "Prefix"
 
1695
            << false << "Prefix" << e << e << e << e
 
1696
            << false << e
 
1697
            << true << "Prefix" << e << e << e << e
 
1698
            << false << e;
 
1699
    QTest::newRow("first in second") << "First"
 
1700
            << false << e << "First" << e << e << e
 
1701
            << false << e
 
1702
            << true << e << "First" << e << e << e
 
1703
            << false << e;
 
1704
    QTest::newRow("middle in second") << "Middle"
 
1705
            << false << e << e << "Middle" << e << e
 
1706
            << false << e
 
1707
            << true << e << e << "Middle" << e << e
 
1708
            << false << e;
 
1709
    QTest::newRow("last in second") << "Last"
 
1710
            << false << e << e << e << "Last" << e
 
1711
            << false << e
 
1712
            << true << e << e << e << "Last" << e
 
1713
            << false << e;
 
1714
    QTest::newRow("suffix in second") << "Suffix"
 
1715
            << false << e << e << e << e << "Suffix"
 
1716
            << false << e
 
1717
            << true << e << e << e << e << "Suffix"
 
1718
            << false << e;
 
1719
 
 
1720
    /* Multiple name values */
 
1721
    QTest::newRow("prefix first") << "Prefix First"
 
1722
            << true << "Prefix" << "First" << e << e << e
 
1723
            << false << e
 
1724
            << false << e << e << e << e << e
 
1725
            << false << e;
 
1726
    QTest::newRow("prefix middle") << "Prefix Middle"
 
1727
            << true << "Prefix" << e << "Middle" << e << e
 
1728
            << false << e
 
1729
            << false << e << e << e << e << e
 
1730
            << false << e;
 
1731
    QTest::newRow("prefix last") << "Prefix Last"
 
1732
            << true << "Prefix" << e << e << "Last" << e
 
1733
            << false << e
 
1734
            << false << e << e << e << e << e
 
1735
            << false << e;
 
1736
    QTest::newRow("prefix suffix") << "Prefix Suffix"
 
1737
            << true << "Prefix" << e << e << e << "Suffix"
 
1738
            << false << e
 
1739
            << false << e << e << e << e << e
 
1740
            << false << e;
 
1741
    QTest::newRow("first middle") << "First Middle"
 
1742
            << true << e << "First" << "Middle" << e << e
 
1743
            << false << e
 
1744
            << false << e << e << e << e << e
 
1745
            << false << e;
 
1746
    QTest::newRow("first last") << "First Last"
 
1747
            << true << e << "First" << e << "Last" << e
 
1748
            << false << e
 
1749
            << false << e << e << e << e << e
 
1750
            << false << e;
 
1751
    QTest::newRow("first suffix") << "First Suffix"
 
1752
            << true << e << "First" << e << e << "Suffix"
 
1753
            << false << e
 
1754
            << false << e << e << e << e << e
 
1755
            << false << e;
 
1756
    QTest::newRow("middle last") << "Middle Last"
 
1757
            << true << e << e << "Middle" << "Last" << e
 
1758
            << false << e
 
1759
            << false << e << e << e << e << e
 
1760
            << false << e;
 
1761
    QTest::newRow("middle suffix") << "Middle Suffix"
 
1762
            << true << e << e << "Middle" << e << "Suffix"
 
1763
            << false << e
 
1764
            << false << e << e << e << e << e
 
1765
            << false << e;
 
1766
    QTest::newRow("last suffix") << "Last Suffix"
 
1767
            << true << e << e << e << "Last" << "Suffix"
 
1768
            << false << e
 
1769
            << false << e << e << e << e << e
 
1770
            << false << e;
 
1771
 
 
1772
    /* Everything.. */
 
1773
    QTest::newRow("all name") << "Prefix First Middle Last Suffix"
 
1774
            << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
 
1775
            << false << e
 
1776
            << false << e << e << e << e << e
 
1777
            << false << e;
 
1778
    QTest::newRow("all name second") << "Prefix First Middle Last Suffix"
 
1779
            << false << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
 
1780
            << false << e
 
1781
            << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
 
1782
            << false << e;
 
1783
 
 
1784
    /* Org */
 
1785
    QTest::newRow("org") << "Company"
 
1786
            << false << e << e << e << e << e
 
1787
            << true << "Company"
 
1788
            << false << e << e << e << e << e
 
1789
            << false << e;
 
1790
    QTest::newRow("second org") << "Company"
 
1791
            << false << e << e << e << e << e
 
1792
            << false << e
 
1793
            << false << e << e << e << e << e
 
1794
            << true << "Company";
 
1795
 
 
1796
    /* Mix */
 
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
 
1801
            << false << e;
 
1802
 
 
1803
    QTest::newRow("name and empty org") << "Prefix First Middle Last Suffix"
 
1804
            << true << "Prefix" << "First" << "Middle" << "Last" << "Suffix"
 
1805
            << false << e
 
1806
            << false << e << e << e << e << e
 
1807
            << false << e;
 
1808
 
 
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
 
1814
            << false << e;
 
1815
 
 
1816
}
 
1817
 
 
1818
void tst_QContactManager::nameSynthesis()
 
1819
{
 
1820
    QContactManager cm("memory");
 
1821
 
 
1822
    QFETCH(QString, expected);
 
1823
 
 
1824
    QFETCH(QString, prefix);
 
1825
    QFETCH(QString, first);
 
1826
    QFETCH(QString, middle);
 
1827
    QFETCH(QString, last);
 
1828
    QFETCH(QString, suffix);
 
1829
    QFETCH(QString, company);
 
1830
 
 
1831
    QFETCH(QString, secondprefix);
 
1832
    QFETCH(QString, secondfirst);
 
1833
    QFETCH(QString, secondmiddle);
 
1834
    QFETCH(QString, secondlast);
 
1835
    QFETCH(QString, secondsuffix);
 
1836
    QFETCH(QString, secondcompany);
 
1837
 
 
1838
    QFETCH(bool, addname);
 
1839
    QFETCH(bool, addname2);
 
1840
    QFETCH(bool, addcompany);
 
1841
    QFETCH(bool, addcompany2);
 
1842
 
 
1843
    /* Test the default name synthesis code */
 
1844
    QContact c;
 
1845
 
 
1846
    QContactName name, name2;
 
1847
    QContactOrganization org, org2;
 
1848
 
 
1849
    name.setPrefix(prefix);
 
1850
    name.setFirstName(first);
 
1851
    name.setMiddleName(middle);
 
1852
    name.setLastName(last);
 
1853
    name.setSuffix(suffix);
 
1854
 
 
1855
    name2.setPrefix(secondprefix);
 
1856
    name2.setFirstName(secondfirst);
 
1857
    name2.setMiddleName(secondmiddle);
 
1858
    name2.setLastName(secondlast);
 
1859
    name2.setSuffix(secondsuffix);
 
1860
 
 
1861
    org.setName(company);
 
1862
    org2.setName(secondcompany);
 
1863
 
 
1864
    if (addname)
 
1865
        c.saveDetail(&name);
 
1866
    if (addname2)
 
1867
        c.saveDetail(&name2);
 
1868
    if (addcompany)
 
1869
        c.saveDetail(&org);
 
1870
    if (addcompany2)
 
1871
        c.saveDetail(&org2);
 
1872
}
 
1873
 
 
1874
void tst_QContactManager::observerDeletion()
 
1875
{
 
1876
    QContactManager *manager = new QContactManager("memory");
 
1877
    QContact c;
 
1878
    QVERIFY(manager->saveContact(&c));
 
1879
    QContactId id = c.id();
 
1880
    QContactObserver *observer = new QContactObserver(manager, id);
 
1881
    Q_UNUSED(observer)
 
1882
    delete manager;
 
1883
    delete observer;
 
1884
    // Test for bug MOBILITY-2566 - that QContactObserver doesn't crash when it is
 
1885
    // destroyed after the associated QContactManager
 
1886
}
 
1887
 
 
1888
void tst_QContactManager::signalEmission()
 
1889
{
 
1890
    QTest::qWait(500); // clear the signal queue
 
1891
    QFETCH(QString, uri);
 
1892
    QScopedPointer<QContactManager> m1(QContactManager::fromUri(uri));
 
1893
 
 
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>)));
 
1899
 
 
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>)));
 
1903
 
 
1904
    QList<QVariant> args;
 
1905
    QList<QContactId> arg;
 
1906
    QContact c;
 
1907
    QList<QContact> batchAdd;
 
1908
    QList<QContactId> batchRemove;
 
1909
    int addSigCount = 0; // the expected signal counts.
 
1910
    int modSigCount = 0;
 
1911
    int remSigCount = 0;
 
1912
 
 
1913
    // verify add emits signal added
 
1914
    QContactName nc;
 
1915
    saveContactName(&c, &nc, "John");
 
1916
    QVERIFY(m1->saveContact(&c));
 
1917
    QContactId cid = c.id();
 
1918
    addSigCount += 1;
 
1919
    QTRY_COMPARE(spyCA.count(), addSigCount);
 
1920
    args = spyCA.takeFirst();
 
1921
    addSigCount -= 1;
 
1922
    arg = args.first().value<QList<QContactId> >();
 
1923
    QVERIFY(arg.count() == 1);
 
1924
    QCOMPARE(QContactId(arg.at(0)), cid);
 
1925
 
 
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())));
 
1929
 
 
1930
    // verify save modified emits signal changed
 
1931
    saveContactName(&c, &nc, "Citizen");
 
1932
    QVERIFY(m1->saveContact(&c));
 
1933
    modSigCount += 1;
 
1934
    QTRY_COMPARE(spyCM.count(), modSigCount);
 
1935
    QTRY_COMPARE(spyCOM1->count(), 1);
 
1936
    args = spyCM.takeFirst();
 
1937
    modSigCount -= 1;
 
1938
    arg = args.first().value<QList<QContactId> >();
 
1939
    QVERIFY(arg.count() == 1);
 
1940
    QCOMPARE(QContactId(arg.at(0)), cid);
 
1941
 
 
1942
    // verify remove emits signal removed
 
1943
    m1->removeContact(c.id());
 
1944
    remSigCount += 1;
 
1945
    QTRY_COMPARE(spyCR.count(), remSigCount);
 
1946
    QTRY_COMPARE(spyCOR1->count(), 1);
 
1947
    args = spyCR.takeFirst();
 
1948
    remSigCount -= 1;
 
1949
    arg = args.first().value<QList<QContactId> >();
 
1950
    QVERIFY(arg.count() == 1);
 
1951
    QCOMPARE(QContactId(arg.at(0)), cid);
 
1952
 
 
1953
    // verify multiple adds works as advertised
 
1954
    QContact c2, c3;
 
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();
 
1963
 
 
1964
    spyCOM1->clear();
 
1965
    spyCOR1->clear();
 
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())));
 
1972
 
 
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);
 
1985
 
 
1986
    // verify multiple removes works as advertised
 
1987
    m1->removeContact(c3.id());
 
1988
    remSigCount += 1;
 
1989
    m1->removeContact(c2.id());
 
1990
    remSigCount += 1;
 
1991
    QTRY_VERIFY(spyCOR2->count() > 0);
 
1992
    QTRY_VERIFY(spyCOR3->count() > 0);
 
1993
    QCOMPARE(spyCOR1->count(), 0);
 
1994
 
 
1995
    /* Now test the batch equivalents */
 
1996
    spyCA.clear();
 
1997
    spyCM.clear();
 
1998
    spyCR.clear();
 
1999
 
 
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));
 
2007
 
 
2008
    QVERIFY(batchAdd.count() == 3);
 
2009
    c = batchAdd.at(0);
 
2010
    c2 = batchAdd.at(1);
 
2011
    c3 = batchAdd.at(2);
 
2012
 
 
2013
    // We want to see one contactsAdded signal listing id's for all three contacts.
 
2014
    QTRY_COMPARE(spyCA.count(), 1);
 
2015
    {
 
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()));
 
2020
    }
 
2021
 
 
2022
    QTRY_COMPARE(spyCM.count(), 0);
 
2023
 
 
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);
 
2034
 
 
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");
 
2042
 
 
2043
    batchAdd.clear();
 
2044
    batchAdd << c << c2 << c3;
 
2045
    QVERIFY(m1->saveContacts(&batchAdd, &errorMap));
 
2046
 
 
2047
    // We want to see one contactsChanged signal listing id's for all three contacts.
 
2048
    QTRY_COMPARE(spyCM.count(), 1);
 
2049
    {
 
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()));
 
2054
    }
 
2055
    QTRY_COMPARE(spyCOM1->count(), 1);
 
2056
    QTRY_COMPARE(spyCOM2->count(), 1);
 
2057
    QTRY_COMPARE(spyCOM3->count(), 1);
 
2058
 
 
2059
    /* Batch removes */
 
2060
    batchRemove << c.id() << c2.id() << c3.id();
 
2061
    QVERIFY(m1->removeContacts(batchRemove, &errorMap));
 
2062
 
 
2063
    // We want to see one contactsRemoved signal listing id's for all three contacts.
 
2064
    QTRY_COMPARE(spyCR.count(), 1);
 
2065
    {
 
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()));
 
2070
    }
 
2071
    QTRY_COMPARE(spyCOR1->count(), 1);
 
2072
    QTRY_COMPARE(spyCOR2->count(), 1);
 
2073
    QTRY_COMPARE(spyCOR3->count(), 1);
 
2074
 
 
2075
    QTRY_COMPARE(spyCA.count(), 0);
 
2076
    QTRY_COMPARE(spyCM.count(), 0);
 
2077
 
 
2078
    QScopedPointer<QContactManager> m2(QContactManager::fromUri(uri));
 
2079
 
 
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")) {
 
2088
        QTest::qWait(0);
 
2089
        spyCA.clear();
 
2090
        spyCM.clear();
 
2091
        spyCR.clear();
 
2092
    }
 
2093
 
 
2094
}
 
2095
 
 
2096
void tst_QContactManager::errorStayingPut()
 
2097
{
 
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);
 
2102
 
 
2103
    QVERIFY(m1.error() == QContactManager::NoError);
 
2104
 
 
2105
    /* Remove an invalid contact to get an error */
 
2106
    QVERIFY(m1.removeContact(QContactId()) == false);
 
2107
    QVERIFY(m1.error() == QContactManager::DoesNotExistError);
 
2108
 
 
2109
    /* Create a new manager with hopefully the same backend */
 
2110
    QContactManager m2("memory", params);
 
2111
 
 
2112
    QVERIFY(m1.error() == QContactManager::DoesNotExistError);
 
2113
    QVERIFY(m2.error() == QContactManager::NoError);
 
2114
 
 
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);
 
2119
 
 
2120
    QContact c;
 
2121
    int unknown = 12345;
 
2122
    QContactDetail::DetailType unknownType = static_cast<QContactDetail::DetailType>(unknown);
 
2123
    QContactDetail d(unknownType);
 
2124
    d.setValue(unknown, 5);
 
2125
    c.saveDetail(&d);
 
2126
 
 
2127
    QVERIFY(m1.saveContact(&c) == false);
 
2128
    QVERIFY(m1.error() == QContactManager::InvalidDetailError);
 
2129
    QVERIFY(m2.error() == QContactManager::BadArgumentError);
 
2130
}
 
2131
 
 
2132
void tst_QContactManager::actionPreferences()
 
2133
{
 
2134
    QFETCH(QString, uri);
 
2135
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
2136
 
 
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");
 
2140
    }
 
2141
 
 
2142
    // create a sample contact
 
2143
    QContactAvatar a;
 
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");
 
2151
    QContactUrl u;
 
2152
    u.setUrl("http://test.nokia.com");
 
2153
    QContactName n;
 
2154
    QContact c;
 
2155
    saveContactName(&c, &n, "TestContact");
 
2156
    c.saveDetail(&a);
 
2157
    c.saveDetail(&p1);
 
2158
    c.saveDetail(&p2);
 
2159
    c.saveDetail(&p3);
 
2160
    c.saveDetail(&u);
 
2161
 
 
2162
    // set a preference for dialing a particular saved phonenumber.
 
2163
    c.setPreferredDetail("Dial", p2);
 
2164
 
 
2165
    QVERIFY(cm->saveContact(&c));          // save the contact
 
2166
    QContact loaded = cm->contact(c.id()); // reload the contact
 
2167
 
 
2168
    // test that the preference was saved correctly.
 
2169
    QContactDetail pref = loaded.preferredDetail("Dial");
 
2170
    QVERIFY(pref == p2);
 
2171
 
 
2172
    cm->removeContact(c.id());
 
2173
}
 
2174
 
 
2175
void tst_QContactManager::changeSet()
 
2176
{
 
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());
 
2182
 
 
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));
 
2188
 
 
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());
 
2198
 
 
2199
    changeSet.insertRemovedContacts(QList<QContactId>() << id);
 
2200
    QVERIFY(changeSet.removedContacts().contains(id));
 
2201
    changeSet.clearRemovedContacts();
 
2202
    QVERIFY(changeSet.removedContacts().isEmpty());
 
2203
 
 
2204
    QVERIFY(changeSet.dataChanged() == false);
 
2205
    QContactChangeSet changeSet2;
 
2206
    changeSet2 = changeSet;
 
2207
    QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts());
 
2208
    changeSet.emitSignals(0);
 
2209
 
 
2210
    changeSet2.clearAddedContacts();
 
2211
    QVERIFY(changeSet2.addedContacts().isEmpty());
 
2212
    changeSet2.insertAddedContacts(changeSet.addedContacts().toList());
 
2213
    QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts());
 
2214
 
 
2215
    changeSet2.clearAll();
 
2216
    QVERIFY(changeSet.addedContacts() != changeSet2.addedContacts());
 
2217
 
 
2218
    QContactChangeSet changeSet3(changeSet2);
 
2219
    QVERIFY(changeSet.addedContacts() != changeSet3.addedContacts());
 
2220
    QVERIFY(changeSet2.addedContacts() == changeSet3.addedContacts());
 
2221
 
 
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);
 
2227
 
 
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);
 
2240
 
 
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);
 
2251
}
 
2252
 
 
2253
void tst_QContactManager::fetchHint()
 
2254
{
 
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);
 
2260
    QStringList rels;
 
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);
 
2272
    int limit = 15;
 
2273
    hint.setMaxCountHint(limit);
 
2274
    QCOMPARE(hint.maxCountHint(), limit);
 
2275
}
 
2276
 
 
2277
void tst_QContactManager::selfContactId()
 
2278
{
 
2279
    QFETCH(QString, uri);
 
2280
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
2281
 
 
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...");
 
2286
 
 
2287
 
 
2288
    // create a new "self" contact and retrieve its Id
 
2289
    QVERIFY(cm->error() == QContactManager::NoError || cm->error() == QContactManager::DoesNotExistError);
 
2290
    QContact self;
 
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");
 
2296
    }
 
2297
    QContactId newSelfContact = self.id();
 
2298
 
 
2299
    // Setup signal spy
 
2300
    qRegisterMetaType<QContactId>("QContactId");
 
2301
    QSignalSpy spy(cm.data(), SIGNAL(selfContactIdChanged(QContactId,QContactId)));
 
2302
    QTestSignalSink sink(cm.data(), SIGNAL(selfContactIdChanged(QContactId,QContactId)));
 
2303
 
 
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);
 
2314
 
 
2315
    // Remove self contact
 
2316
    if (!cm->removeContact(self.id())) {
 
2317
        QSKIP("Unable to remove self contact");
 
2318
    }
 
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.
 
2324
 
 
2325
    // reset to original state.
 
2326
    cm->setSelfContactId(selfContact);
 
2327
}
 
2328
 
 
2329
QList<QContactDetail> tst_QContactManager::removeAllDefaultDetails(const QList<QContactDetail>& details)
 
2330
{
 
2331
    QList<QContactDetail> newlist;
 
2332
    foreach (const QContactDetail d, details) {
 
2333
        if (d.type() != QContactType::Type && d.type() != QContactTimestamp::Type) {
 
2334
            newlist << d;
 
2335
        }
 
2336
    }
 
2337
    return newlist;
 
2338
}
 
2339
 
 
2340
void tst_QContactManager::detailOrders()
 
2341
{
 
2342
    QFETCH(QString, uri);
 
2343
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
2344
 
 
2345
    if (cm->managerName() == "jsondb" || cm->managerName() == "memory")
 
2346
        QSKIP("Skipping: This manager does not support detail ordering!");
 
2347
 
 
2348
    QContact a;
 
2349
    //phone numbers
 
2350
 
 
2351
    QContactPhoneNumber number1, number2, number3;
 
2352
 
 
2353
    number1.setNumber("11111111");
 
2354
    number1.setContexts(QContactPhoneNumber::ContextHome);
 
2355
 
 
2356
    number2.setNumber("22222222");
 
2357
    number2.setContexts(QContactPhoneNumber::ContextWork);
 
2358
 
 
2359
    number3.setNumber("33333333");
 
2360
    number3.setContexts(QContactPhoneNumber::ContextOther);
 
2361
 
 
2362
    a.saveDetail(&number1);
 
2363
    a.saveDetail(&number2);
 
2364
    a.saveDetail(&number3);
 
2365
 
 
2366
    QVERIFY(cm->saveContact(&a));
 
2367
    a = cm->contact(a.id());
 
2368
 
 
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);
 
2374
 
 
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);
 
2383
 
 
2384
    a.saveDetail(&number2);
 
2385
    QVERIFY(cm->saveContact(&a));
 
2386
    a = cm->contact(a.id());
 
2387
 
 
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);
 
2393
 
 
2394
    //addresses
 
2395
    QContactAddress address1, address2, address3;
 
2396
 
 
2397
    address1.setStreet("Brandl St");
 
2398
    address1.setRegion("Brisbane");
 
2399
    address3 = address2 = address1;
 
2400
 
 
2401
    address1.setContexts(QContactAddress::ContextHome);
 
2402
    address2.setContexts(QContactAddress::ContextWork);
 
2403
    address3.setContexts(QContactAddress::ContextOther);
 
2404
 
 
2405
    QVERIFY(a.saveDetail(&address1));
 
2406
    QVERIFY(a.saveDetail(&address2));
 
2407
    QVERIFY(a.saveDetail(&address3));
 
2408
 
 
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
 
2413
 
 
2414
    // Detail keys for the moment are not persistent through an contact save / fetch
 
2415
    address3 = details.at(0);
 
2416
 
 
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.
 
2424
 
 
2425
    a.saveDetail(&address2);
 
2426
    QVERIFY(cm->saveContact(&a));
 
2427
    a = cm->contact(a.id());
 
2428
 
 
2429
    details = a.details(QContactAddress::Type);
 
2430
    QVERIFY(details.count() == 1); // add one back.
 
2431
 
 
2432
 
 
2433
    //emails
 
2434
    QContactEmailAddress email1, email2, email3;
 
2435
 
 
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);
 
2441
 
 
2442
    a.saveDetail(&email1);
 
2443
    a.saveDetail(&email2);
 
2444
    a.saveDetail(&email3);
 
2445
 
 
2446
    QVERIFY(cm->saveContact(&a));
 
2447
    a = cm->contact(a.id());
 
2448
 
 
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);
 
2453
 
 
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.
 
2461
 
 
2462
    a.saveDetail(&email2);
 
2463
    QVERIFY(cm->saveContact(&a));
 
2464
    a = cm->contact(a.id());
 
2465
 
 
2466
    details = a.details(QContactEmailAddress::Type);
 
2467
    QVERIFY(details.count() == 1); // add one back.
 
2468
 
 
2469
    QVERIFY(cm->removeContact(a.id()));
 
2470
    QVERIFY(cm->error() == QContactManager::NoError);
 
2471
}
 
2472
 
 
2473
void tst_QContactManager::relationships()
 
2474
{
 
2475
    QFETCH(QString, uri);
 
2476
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
2477
 
 
2478
    if (cm->managerName() == "jsondb")
 
2479
        QSKIP("Jsondb doesnt support relationships");
 
2480
 
 
2481
 
 
2482
    // save some contacts
 
2483
    QContact source;
 
2484
    QContact dest1, dest2, dest3, dest4;
 
2485
    QContactPhoneNumber n1, n2, n3, n4;
 
2486
    n1.setNumber("1");
 
2487
    n2.setNumber("2");
 
2488
    n3.setNumber("3");
 
2489
    n4.setNumber("4");
 
2490
 
 
2491
    dest1.saveDetail(&n1);
 
2492
    dest2.saveDetail(&n2);
 
2493
    dest3.saveDetail(&n3);
 
2494
    dest4.saveDetail(&n4);
 
2495
 
 
2496
    cm->saveContact(&source);
 
2497
    cm->saveContact(&dest1);
 
2498
    cm->saveContact(&dest2);
 
2499
    cm->saveContact(&dest3);
 
2500
    cm->saveContact(&dest4);
 
2501
 
 
2502
    // check if manager supports relationships
 
2503
 
 
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());
 
2516
 
 
2517
        QList<QContactRelationship> batchList;
 
2518
        batchList << r2 << r3;
 
2519
 
 
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);
 
2527
 
 
2528
        // test retrieval
 
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);
 
2539
 
 
2540
 
 
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);
 
2556
        return;
 
2557
    }
 
2558
 
 
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();
 
2571
 
 
2572
    // add some arbitrary type for testing
 
2573
    if (availableRelationshipTypes.count())
 
2574
        availableRelationshipTypes.insert(0, "test-arbitrary-relationship-type");
 
2575
    else {
 
2576
        availableRelationshipTypes.append("test-arbitrary-relationship-type");
 
2577
        availableRelationshipTypes.append(QContactRelationship::HasMember());
 
2578
        availableRelationshipTypes.append(QContactRelationship::HasAssistant());
 
2579
    }
 
2580
 
 
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());
 
2585
 
 
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);
 
2593
    }
 
2594
 
 
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));
 
2603
 
 
2604
    // save the relationship
 
2605
    int managerRelationshipsCount = cm->relationships(availableRelationshipTypes.at(0)).count();
 
2606
    QVERIFY(cm->saveRelationship(&customRelationshipOne));
 
2607
 
 
2608
    // test our accessors.
 
2609
    QCOMPARE(cm->relationships(availableRelationshipTypes.at(0)).count(), (managerRelationshipsCount + 1));
 
2610
    QVERIFY(cm->relationships(availableRelationshipTypes.at(0), source).count() == 1);
 
2611
 
 
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);
 
2615
 
 
2616
    // modify and save the relationship
 
2617
    customRelationshipOne.setSecond(dest2);
 
2618
    QVERIFY(cm->saveRelationship(&customRelationshipOne));
 
2619
 
 
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.
 
2624
 
 
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.
 
2628
 
 
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));
 
2635
 
 
2636
    // Add a second relationship
 
2637
    QContactRelationship customRelationshipTwo;
 
2638
    customRelationshipTwo.setFirst(source);
 
2639
    if (availableRelationshipTypes.count() > 1)
 
2640
        customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(1));
 
2641
    else
 
2642
        customRelationshipTwo.setRelationshipType(availableRelationshipTypes.at(0));
 
2643
    customRelationshipTwo.setSecond(dest3);
 
2644
    QVERIFY(cm->saveRelationship(&customRelationshipTwo));
 
2645
 
 
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());
 
2651
 
 
2652
    // now refresh the contacts
 
2653
    dest3 = cm->contact(dest3.id());
 
2654
    dest2 = cm->contact(dest2.id());
 
2655
    source = cm->contact(source.id());
 
2656
 
 
2657
    // and test again.
 
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());
 
2665
 
 
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));
 
2675
 
 
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));
 
2680
 
 
2681
    // Test iteration
 
2682
    QList<QContactRelationship> relats = source.relationships();
 
2683
    QList<QContactRelationship>::iterator it = relats.begin();
 
2684
 
 
2685
    while (it != relats.end()) {
 
2686
        QContact firstContact = it->first();
 
2687
        QVERIFY(firstContact == source);
 
2688
        QVERIFY(it->second() == dest2 || it->second() == dest3);
 
2689
        it++;
 
2690
    }
 
2691
 
 
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());
 
2695
 
 
2696
        QVERIFY(dest2.relationships(availableRelationshipTypes.at(1)).isEmpty());
 
2697
 
 
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());
 
2707
    } else {
 
2708
        QVERIFY(source.relatedContacts(availableRelationshipTypes.at(0), QContactRelationship::Second).contains(dest3));
 
2709
    }
 
2710
 
 
2711
    // Cleanup a bit
 
2712
    QMap<int, QContactManager::Error> errorMap;
 
2713
    QList<QContactRelationship> moreRels;
 
2714
 
 
2715
    moreRels << customRelationshipOne << customRelationshipTwo;
 
2716
    errorMap.insert(5, QContactManager::BadArgumentError);
 
2717
    QVERIFY(cm->removeRelationships(moreRels, &errorMap));
 
2718
    QVERIFY(errorMap.count() == 0);
 
2719
 
 
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));
 
2734
    } else {
 
2735
        br3.setFirst(source);
 
2736
        br3.setSecond(dest4);
 
2737
        br3.setRelationshipType(availableRelationshipTypes.at(0));
 
2738
    }
 
2739
    batchList << br1 << br2 << br3;
 
2740
 
 
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));
 
2748
 
 
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.
 
2755
 
 
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);
 
2761
 
 
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));
 
2766
    while (true) {
 
2767
        nonexistentLocalId = cm->contact(nonexistentLocalId).id();
 
2768
        if (nonexistentLocalId == QContactId()) {
 
2769
            // found a "spare" local id (no contact with that id)
 
2770
            break;
 
2771
        }
 
2772
 
 
2773
        // keep looking...
 
2774
        idSeed += 1;
 
2775
        nonexistentLocalId = QContactId::fromString(QString::number(idSeed));
 
2776
        QVERIFY(nonexistentLocalId != QContactId()); // integer overflow check.
 
2777
    }
 
2778
//    nonexistentDest.id().setLocalId(nonexistentLocalId);
 
2779
 
 
2780
    QContactRelationship maliciousRel;
 
2781
    maliciousRel.setFirst(source);
 
2782
    maliciousRel.setSecond(nonexistentDest);
 
2783
    maliciousRel.setRelationshipType("nokia-test-invalid-relationship-type");
 
2784
    QVERIFY(!cm->saveRelationship(&maliciousRel));
 
2785
 
 
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));
 
2791
 
 
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));
 
2806
 
 
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));
 
2814
 
 
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.
 
2820
 
 
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));
 
2825
 
 
2826
    // Test batch save with an error map
 
2827
    moreRels.clear();
 
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.
 
2839
 
 
2840
    // now clean up and remove our dests.
 
2841
    QVERIFY(cm->removeContact(source.id()));
 
2842
    QVERIFY(cm->removeContact(dest3.id()));
 
2843
 
 
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);
 
2853
}
 
2854
 
 
2855
void tst_QContactManager::contactType()
 
2856
{
 
2857
    QFETCH(QString, uri);
 
2858
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
2859
 
 
2860
    if (!cm->supportedContactTypes().contains(QContactType::TypeGroup))
 
2861
        QSKIP("Skipping: This manager does not support group contacts!");
 
2862
 
 
2863
    QContact g1, g2, c;
 
2864
 
 
2865
    g1.setType(QContactType::TypeGroup);
 
2866
    g2.setType(QContactType::TypeGroup);
 
2867
 
 
2868
    QContactPhoneNumber g1p, g2p, cp;
 
2869
    g1p.setNumber("22222");
 
2870
    g2p.setNumber("11111");
 
2871
    cp.setNumber("33333");
 
2872
 
 
2873
    g1.saveDetail(&g1p);
 
2874
    g2.saveDetail(&g2p);
 
2875
    c.saveDetail(&cp);
 
2876
 
 
2877
    QVERIFY(cm->saveContact(&g1));
 
2878
    QVERIFY(cm->saveContact(&g2));
 
2879
    QVERIFY(cm->saveContact(&c));
 
2880
 
 
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()));
 
2888
 
 
2889
    QList<QContactSortOrder> sortOrders;
 
2890
    QContactSortOrder byPhoneNumber;
 
2891
    byPhoneNumber.setDetailType(QContactPhoneNumber::Type, QContactPhoneNumber::FieldNumber);
 
2892
    sortOrders.append(byPhoneNumber);
 
2893
 
 
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()));
 
2897
 
 
2898
    cm->removeContact(g1.id());
 
2899
    cm->removeContact(g2.id());
 
2900
    cm->removeContact(c.id());
 
2901
}
 
2902
 
 
2903
#if defined(USE_VERSIT_PLZ)
 
2904
void tst_QContactManager::partialSave()
 
2905
{
 
2906
    QFETCH(QString, uri);
 
2907
    QScopedPointer<QContactManager> cm(QContactManager::fromUri(uri));
 
2908
 
 
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);
 
2918
 
 
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"));
 
2926
 
 
2927
    QList<QContact> contacts = imp.contacts();
 
2928
    QMap<int, QContactManager::Error> errorMap;
 
2929
 
 
2930
    // First save these contacts
 
2931
    QVERIFY(cm->saveContacts(&contacts, &errorMap));
 
2932
    QList<QContact> originalContacts = contacts;
 
2933
 
 
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
 
2944
 
 
2945
    QContactPhoneNumber pn;
 
2946
    pn.setNumber("111111");
 
2947
    contacts[0].saveDetail(&pn);
 
2948
 
 
2949
    // 0) empty mask
 
2950
    QVERIFY(cm->saveContacts(&contacts, QStringList(), &errorMap));
 
2951
 
 
2952
    // That should have updated everything
 
2953
    QContact a = cm->contact(originalContacts[0].id());
 
2954
    QVERIFY(a.details<QContactPhoneNumber>().count() == 2);
 
2955
 
 
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());
 
2960
 
 
2961
    QContact b = cm->contact(originalContacts[1].id());
 
2962
    QVERIFY(b.details<QContactPhoneNumber>().count() == 1);
 
2963
 
 
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
 
2968
 
 
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);
 
2974
 
 
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);
 
2985
 
 
2986
    // 4 - New contact, no details in the mask
 
2987
    QContact newContact = originalContacts[3];
 
2988
    newContact.setId(QContactId());
 
2989
 
 
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
 
2997
 
 
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
 
3008
 
 
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);
 
3021
 
 
3022
    // 7) Have a non existing contact in the middle followed by a save error
 
3023
    badId = id4;
 
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);
 
3030
 
 
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
 
3044
 
 
3045
    // 9 - A list with only a new contact, with some details in the mask
 
3046
    newContact = originalContacts[2];
 
3047
    newContact.setId(QContactId());
 
3048
    contacts2.clear();
 
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
 
3056
 
 
3057
    // 10 - A list with new a contact for the wrong manager, followed by a new contact with an
 
3058
    // invalid detail
 
3059
    newContact = originalContacts[2];
 
3060
    newContact.setId(QContactId());
 
3061
    contacts2.clear();
 
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);
 
3070
}
 
3071
#endif
 
3072
 
 
3073
void tst_QContactManager::lateDeletion()
 
3074
{
 
3075
    // Create some engines, but make them get deleted at shutdown
 
3076
    QFETCH(QString, uri);
 
3077
    QContactManager* cm = QContactManager::fromUri(uri);
 
3078
 
 
3079
    cm->setParent(qApp); // now do nothing
 
3080
}
 
3081
 
 
3082
void tst_QContactManager::lazyConnections()
 
3083
{
 
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");
 
3090
 
 
3091
    QCOMPARE(lazy1.managerName(), QString("lazy"));
 
3092
    QCOMPARE(lazy2.managerName(), QString("lazy2"));
 
3093
 
 
3094
    // Make sure the initial connection counts are empty
 
3095
    QCOMPARE(QContactLazyEngine::connectionCounts.count(), 0);
 
3096
    QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 0);
 
3097
 
 
3098
    // Lazy 1 first
 
3099
    {
 
3100
        QTestSignalSink casink(&lazy1, SIGNAL(contactsAdded(QList<QContactId>)));
 
3101
 
 
3102
        // See if we got one connection
 
3103
        QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 1);
 
3104
        QCOMPARE(QContactLazyEngine::connectionCounts.count(), 1);
 
3105
 
 
3106
        // Go out of scope, and see if disconnect is called
 
3107
    }
 
3108
    QCOMPARE(QContactLazyEngine::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine::contactsAdded)), 0);
 
3109
    QCOMPARE(QContactLazyEngine::connectionCounts.count(), 1);
 
3110
 
 
3111
    // Lazy2 second
 
3112
    {
 
3113
        QTestSignalSink casink(&lazy2, SIGNAL(contactsAdded(QList<QContactId>)));
 
3114
 
 
3115
        // See if we got one connection
 
3116
        QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 1);
 
3117
        QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 1);
 
3118
 
 
3119
        // Go out of scope, and see if disconnect is called
 
3120
    }
 
3121
    QCOMPARE(QContactLazyEngine2::connectionCounts.value(QMetaMethod::fromSignal(&QContactLazyEngine2::contactsAdded)), 0);
 
3122
    QCOMPARE(QContactLazyEngine2::connectionCounts.count(), 1);
 
3123
 
 
3124
    // Just make sure all the signals get connected correctly
 
3125
    {
 
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)));
 
3133
 
 
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);
 
3143
    }
 
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);
 
3152
 
 
3153
    // and for lazy2
 
3154
    {
 
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)));
 
3162
 
 
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);
 
3172
    }
 
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);
 
3181
}
 
3182
 
 
3183
void tst_QContactManager::compareVariant()
 
3184
{
 
3185
    // Exercise this function a bit
 
3186
    QFETCH(QVariant, a);
 
3187
    QFETCH(QVariant, b);
 
3188
    QFETCH(Qt::CaseSensitivity, cs);
 
3189
    QFETCH(int, expected);
 
3190
 
 
3191
    int comparison = QContactManagerEngine::compareVariant(a, b, cs);
 
3192
    // Since compareVariant is a little imprecise (just sign matters)
 
3193
    // convert that here.
 
3194
    if (comparison < 0)
 
3195
        comparison = -1;
 
3196
    else if (comparison > 0)
 
3197
        comparison = 1;
 
3198
 
 
3199
    QCOMPARE(comparison, expected);
 
3200
 
 
3201
    comparison = QContactManagerEngine::compareVariant(b, a, cs);
 
3202
    if (comparison < 0)
 
3203
        comparison = -1;
 
3204
    else if (comparison > 0)
 
3205
        comparison = 1;
 
3206
 
 
3207
    // The sign should be flipped now
 
3208
    QVERIFY((comparison + expected) == 0);
 
3209
}
 
3210
 
 
3211
void tst_QContactManager::compareVariant_data()
 
3212
{
 
3213
    QTest::addColumn<QVariant>("a");
 
3214
    QTest::addColumn<QVariant>("b");
 
3215
 
 
3216
    QTest::addColumn<Qt::CaseSensitivity>("cs");
 
3217
    QTest::addColumn<int>("expected");
 
3218
 
 
3219
    // bool
 
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;
 
3223
 
 
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;
 
3230
 
 
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;
 
3237
 
 
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;
 
3243
 
 
3244
    // Some numeric types
 
3245
    // uint
 
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
 
3253
 
 
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
 
3262
 
 
3263
    // ulonglong
 
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
 
3271
 
 
3272
    // longlong
 
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
 
3280
 
 
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;
 
3292
 
 
3293
    // strings
 
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;
 
3300
 
 
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;
 
3305
 
 
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;
 
3308
 
 
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;
 
3313
 
 
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;
 
3320
 
 
3321
    // Stringlists
 
3322
    // {} < {"a"} < {"aa"} < {"aa","bb"} < {"aa", "cc"} < {"bb"}
 
3323
 
 
3324
    QStringList empty;
 
3325
    QStringList listA("a");
 
3326
    QStringList listAA("aa");
 
3327
    QStringList listAABB;
 
3328
    listAABB << "aa" << "bb";
 
3329
    QStringList listAACC;
 
3330
    listAACC << "aa" << "cc";
 
3331
    QStringList listBB;
 
3332
    listBB << "bb";
 
3333
    QStringList listCCAA;
 
3334
    listCCAA << "cc" << "aa";
 
3335
    QStringList listA2("A");
 
3336
    QStringList listAA2("AA");
 
3337
 
 
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;
 
3342
 
 
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;
 
3347
 
 
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;
 
3352
 
 
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;
 
3355
 
 
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;
 
3358
 
 
3359
    // equality
 
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;
 
3365
 
 
3366
    // Times
 
3367
    QTime t0;
 
3368
    QTime t1(0,0,0,0);
 
3369
    QTime t2(0,59,0,0);
 
3370
    QTime t3(1,0,0,0);
 
3371
    QTime t4(23,59,59,999);
 
3372
 
 
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;
 
3379
 
 
3380
    // Dates
 
3381
    QDate d0;
 
3382
    QDate d1 = QDate::fromJulianDay(1);
 
3383
    QDate d2(1,1,1);
 
3384
    QDate d3(2011,6,9);
 
3385
    QDate d4 = QDate::fromJulianDay(0x7fffffff);
 
3386
    QDate d5 = QDate::fromJulianDay(0x80000000);
 
3387
    QDate d6 = QDate::fromJulianDay(0xffffffff);
 
3388
 
 
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;
 
3404
 
 
3405
    // DateTimes
 
3406
    // Somewhat limited testing here
 
3407
    QDateTime dt0;
 
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
 
3413
 
 
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;
 
3429
}
 
3430
 
 
3431
QTEST_MAIN(tst_QContactManager)
 
3432
#include "tst_qcontactmanager.moc"