Fixes: Show the reference query's variable names in unit tests.
[qtcontacts-tracker:hasselmms-qtcontacts-tracker.git] / tests / ut_qtcontacts_trackerplugin_common / ut_qtcontacts_trackerplugin_common.h
1 /*********************************************************************************
2  ** This file is part of QtContacts tracker storage plugin
3  **
4  ** Copyright (c) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
5  **
6  ** Contact:  Nokia Corporation (info@qt.nokia.com)
7  **
8  ** GNU Lesser General Public License Usage
9  ** This file may be used under the terms of the GNU Lesser General Public License
10  ** version 2.1 as published by the Free Software Foundation and appearing in the
11  ** file LICENSE.LGPL included in the packaging of this file.  Please review the
12  ** following information to ensure the GNU Lesser General Public License version
13  ** 2.1 requirements will be met:
14  ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
15  **
16  ** In addition, as a special exception, Nokia gives you certain additional rights.
17  ** These rights are described in the Nokia Qt LGPL Exception version 1.1, included
18  ** in the file LGPL_EXCEPTION.txt in this package.
19  **
20  ** Other Usage
21  ** Alternatively, this file may be used in accordance with the terms and
22  ** conditions contained in a signed written agreement between you and Nokia.
23  *********************************************************************************/
24
25 #ifndef UT_QTCONTACTS_TRACKERPLUGIN_COMMON_H
26 #define UT_QTCONTACTS_TRACKERPLUGIN_COMMON_H
27
28 #include <QContactAbstractRequest>
29 #include <QContactDetailFilter>
30
31 #include <QtSparql>
32 #include <QtTest/QtTest>
33
34 #include <engine/contactmanagerengine.h>
35
36 QTM_USE_NAMESPACE
37
38 // macro to be used if calling another test function from a test function
39 // there could have been a failing test in that function, so the current function
40 // also needs to return at once
41 // giving the file and line number is useful to get to know the call stack
42 #define CHECK_CURRENT_TEST_FAILED                                               \
43                                                                                 \
44 do {                                                                            \
45     if (QTest::currentTestFailed()) {                                           \
46         qWarning("failing test called from %s(%d)", __FILE__, __LINE__);        \
47         return;                                                                 \
48     }                                                                           \
49 } while (0)
50
51 // macros to deal with multiple contacts:
52 // * nickname works for both normal and group contacts
53 // * using the test run's uuid to namespace contacts from different tests in the same database,
54 // * using __func__ to identify contacts from a test
55 // * using an int index to identify the contacts by order of creation
56 // In the tests use SET_TESTNICKNAME_TO_CONTACT to mark created contacts
57 // and TESTNICKNAME_FILTER for fetch requests to limit to contacts from current test,
58 // add it with a QContactIntersectionFilter to the real filter, if used.
59 #define TESTNICKNAME_NICKNAME            makeUniqueName(QLatin1String(__func__))
60 #define SET_TESTNICKNAME_TO_CONTACT(c)   setTestNicknameToContact(c, QLatin1String(__func__))
61 #define TESTNICKNAME_FILTER              testNicknameFilter(QLatin1String(__func__))
62
63 // replacement for QTEST_MAIN which always uses QCoreApplication
64 #define QCT_TEST_MAIN(TestObject)                                               \
65 int main(int argc, char *argv[])                                                \
66 {                                                                               \
67     QCoreApplication app(argc, argv);                                           \
68     TestObject tc;                                                              \
69     return QTest::qExec(&tc, argc, argv);                                       \
70 }
71
72 typedef QList<QContactLocalId> QContactLocalIdList;
73 typedef QList<QContact> QContactList;
74 typedef QPair<QString, QString> PairOfStrings;
75
76 // create metadata so that those types can be used with QTest library
77 Q_DECLARE_METATYPE(QContact)
78 Q_DECLARE_METATYPE(QContactFilter)
79 Q_DECLARE_METATYPE(QContactLocalIdList)
80 Q_DECLARE_METATYPE(QContactList)
81
82 Q_DECLARE_METATYPE(QList<int>)
83
84 namespace QTest
85 {
86     template<> inline char *toString<QVariant::Type>(const QVariant::Type &type)
87     {
88         return qstrdup(QVariant::typeToName(type));
89     }
90
91     template<> inline char *toString<QContactManager::Error>(const QContactManager::Error &error)
92     {
93 #define DO_CASE(v) case (v): return qstrdup(#v)
94         switch(error) {
95             DO_CASE(QContactManager::NoError);
96             DO_CASE(QContactManager::DoesNotExistError);
97             DO_CASE(QContactManager::AlreadyExistsError);
98             DO_CASE(QContactManager::InvalidDetailError);
99             DO_CASE(QContactManager::InvalidRelationshipError);
100             DO_CASE(QContactManager::LockedError);
101             DO_CASE(QContactManager::DetailAccessError);
102             DO_CASE(QContactManager::PermissionsError);
103             DO_CASE(QContactManager::OutOfMemoryError);
104             DO_CASE(QContactManager::NotSupportedError);
105             DO_CASE(QContactManager::BadArgumentError);
106             DO_CASE(QContactManager::UnspecifiedError);
107             DO_CASE(QContactManager::VersionMismatchError);
108             DO_CASE(QContactManager::LimitReachedError);
109             DO_CASE(QContactManager::InvalidContactTypeError);
110             DO_CASE(QContactManager::TimeoutError);
111 #undef DO_CASE
112         }
113
114         return qstrdup(qPrintable(QString::fromLatin1("QContactManager::Error(%1)").arg(error)));
115     }
116
117     template<> inline char *toString< QVariantMap >(const QVariantMap &map)
118     {
119         QString result;
120
121         for(QVariantMap::ConstIterator i = map.constBegin(); i != map.constEnd(); ++i) {
122             if (result.length() > 0) {
123                 result += QLatin1String(", ");
124             }
125
126             char *str(toString(i.value()));
127
128             result +=
129                     QLatin1Char('(') % i.key() % QLatin1String(": ") %
130                     QString::fromLocal8Bit(str) % QLatin1Char(')');
131
132             qFree(str);
133         }
134
135         return qstrdup(qPrintable(QLatin1Char('(') + result + QLatin1Char(')')));
136     }
137
138     template<> inline char *toString< QVariantHash >(const QVariantHash &hash)
139     {
140         QString result;
141
142         for(QVariantHash::ConstIterator i = hash.constBegin(); i != hash.constEnd(); ++i) {
143             if (result.length() > 0) {
144                 result += QLatin1String(", ");
145             }
146
147             char *str(toString(i.value()));
148
149             result +=
150                     QLatin1Char('(') % i.key() % QLatin1String(": ") %
151                     QString::fromLocal8Bit(str) % QLatin1Char(')');
152
153             qFree(str);
154         }
155
156         return qstrdup(qPrintable(QLatin1Char('(') + result + QLatin1Char(')')));
157     }
158
159     template<> inline char *toString< QList<QString> >(const QList<QString> &list)
160     {
161         return qstrdup(qPrintable(QLatin1String("(\"") +
162                                   QStringList(list).join(QLatin1String("\", \"")) +
163                                   QLatin1String("\")")));
164     }
165
166     template<> inline char *toString< QSet<QString> >(const QSet<QString> &set)
167     {
168         return toString(set.toList());
169     }
170
171     template<> inline char *toString< QList<QUrl> >(const QList<QUrl> &list)
172     {
173         QStringList strList;
174
175         foreach(const QUrl &url, list) {
176             strList += url.toString();
177         }
178
179         return toString< QList<QString> >(strList);
180     }
181
182     template<> inline char *toString< QSet<QUrl> >(const QSet<QUrl> &set)
183     {
184         return toString(set.toList());
185     }
186
187     inline QTestData &newRow(const QString &dataTag)
188     {
189         return newRow(dataTag.toLatin1().constData());
190     }
191
192     inline void qFail(const QString &statementStr, const char *file, int line)
193     {
194         qFail(statementStr.toLatin1().constData(), file, line);
195     }
196 }
197
198 class ut_qtcontacts_trackerplugin_common : public QObject
199 {
200     Q_OBJECT
201
202 public:
203     static const QList<QContactSortOrder> NoSortOrders;
204     static const QContactFetchHint NoFetchHint;
205
206     explicit ut_qtcontacts_trackerplugin_common(const QDir &dataDir, const QDir &srcDir,
207                                                 QObject *parent = 0);
208     virtual ~ut_qtcontacts_trackerplugin_common();
209
210 private slots:
211     void testHostInfo();
212
213 protected slots:
214     void cleanup();
215
216 protected:
217     QSet<QString> findTestSlotNames();
218
219     void saveContact(QContact &contact);
220     void saveContacts(QList<QContact> &contacts);
221     void fetchContact(const QContactLocalId &id, QContact &result);
222     void fetchContact(const QContactFilter &filter, QContact &result);
223     void fetchContactLocalId(const QContactFilter &filter, QContactLocalId &result);
224     void fetchContacts(const QList<QContactLocalId> &ids, QList<QContact> &result);
225     void fetchContacts(const QContactFilter &filter, QList<QContact> &result);
226     void fetchContacts(const QContactFilter &filter, const QList<QContactSortOrder> &sorting, QList<QContact> &result);
227     void fetchContactLocalIds(const QContactFilter &filter, QList<QContactLocalId> &result);
228     void fetchContactLocalIds(const QContactFilter &filter, const QList<QContactSortOrder> &sorting, QList<QContactLocalId> &result);
229     void saveRelationship(const QContactRelationship &relationship);
230     void saveRelationships(const QList<QContactRelationship> &relationships);
231     void fetchRelationship(const QContactId &firstId, const QString &relationshipType, const QContactId &secondId, QContactRelationship &result);
232     void fetchRelationships(const QString &relationshipType, const QContactId &participantId, QContactRelationship::Role role, QList<QContactRelationship> &result);
233     void removeRelationship(const QContactRelationship &relationship);
234     void removeRelationships(const QList<QContactRelationship> &relationships);
235     uint insertIMContact(const QString &contactIri, const QString &imId, const QString &imPresence,
236                        const QString &statusMessage, const QString &accountPath,
237                        const QString &protocol = QLatin1String("jabber"),
238                        const QString &serviceProvider = QLatin1String("roads.desert"),
239                        const QString &nameGiven = QLatin1String("Speedy"),
240                        const QString &nameFamily = QLatin1String("Runner"));
241
242     QList<QContact> parseVCards(const QString &fileName, int limit = INT_MAX);
243     QList<QContact> parseVCards(const QByteArray &vcardData, int limit = INT_MAX);
244
245     virtual QMap<QString, QString> makeEngineParams() const;
246     QContactLocalIdList & localIds() { return m_localIds; }
247     void registerForCleanup(const QContact &contact) { m_localIds.append(contact.localId()); }
248     QctContactManagerEngine *engine() const;
249     void resetEngine();
250
251     QString referenceFileName(const QString &fileName);
252     QString loadReferenceFile(const QString &fileName);
253
254     QSparqlResult * executeQuery(const QString &queryString,
255                                  QSparqlQuery::StatementType type) const;
256
257     static QStringList extractResourceIris(const QString &text);
258
259     QStringList loadRawTuples(const QString &fileName);
260     QStringList loadRawTuples(const QString &fileName, const QRegExp &subjectFilter);
261     QStringList loadRawContacts(const QString &fileName = QLatin1String("000-contacts.ttl"));
262
263     enum ReferenceContactMode
264     {
265         IgnoreReferenceContactIris,
266         ResolveReferenceContactIris,
267         GenerateReferenceContactIds
268     };
269
270     QList<QContact> loadReferenceContacts(ReferenceContactMode mode,
271                                           const QString &fileName = QLatin1String("000-contacts.xml"));
272
273     void verifyContacts(QList<QContact> candidateContacts, QList<QContact> referenceContacts);
274     void verifyContacts(const QList<QContact> &candidateContacts,
275                         const QString &referenceFileName = QLatin1String("000-contacts.xml"));
276
277     /// returns the unique identifier of the testrun, extended by the given @p id, if not empty.
278     QString uniqueTestId(const QString& id = QString()) const;
279     /// returns a name which is unique and contains a custom identifier, the given @p id.
280     /// Uniqueness is created by the unique id of the testrun (mNamePrefix) and an increasing number,
281     /// starting from 0000 and ending with 99999 (i.e. ending being useful).
282     /// The number has fixed set of digits, with leading 0, to enable sorting by name in order of creation.
283     /// The created name has this pattern: testClassName:Uuid:idPassedByParameter_12345
284     QString makeUniqueName(const QString &id) const;
285     /// sets a nickname to the contact using the test uuid and the given @p id.
286     /// Use the macro SET_TESTNICKNAME_TO_CONTACT(c) to get the function name as id.
287     void setTestNicknameToContact(QContact &contact, const QString &id) const;
288     /// returns a filter on nicknames using the test uuid and the given @p id.
289     /// Use the macro TESTNICKNAME_FILTER to get a filter with the function name as id.
290     QContactDetailFilter testNicknameFilter(const QString &id) const;
291
292     uint resolveTrackerId(const QString &iri);
293     QList<uint> resolveTrackerIds(const QStringList &iris);
294     QString onlineAvatarPath(const QString &accountPath);
295
296     static QSet<QString> definitionNames(const QList<QContact> &contacts);
297     static QSet<QString> definitionNames(const QList<QContactDetail> &details);
298
299     static QContactLocalIdList localContactIds(const QList<QContact> &contacts);
300
301     /// creates a QContactLocalIdFilter with @p ids
302     static QContactLocalIdFilter
303     localIdFilter(const QList<QContactLocalId> &ids)
304     {
305         QContactLocalIdFilter filter;
306         filter.setIds(ids);
307         return filter;
308     }
309
310     /// creates a QContactLocalIdFilter with @p id
311     static QContactLocalIdFilter
312     localIdFilter(QContactLocalId id)
313     {
314         return localIdFilter(QList<QContactLocalId>() << id);
315     }
316
317     /// creates a QContactFetchHint with @p definitionNames
318     static QContactFetchHint
319     fetchHint(const QStringList &definitionNames)
320     {
321         QContactFetchHint fetchHint;
322         fetchHint.setDetailDefinitionsHint(definitionNames);
323         return fetchHint;
324     }
325
326     /// creates a QContactFetchHint with @p definitionName
327     static QContactFetchHint
328     fetchHint(const QString &definitionName)
329     {
330         return fetchHint(QStringList(definitionName));
331     }
332
333     /// creates a QContactFetchHint for the detail @p T
334     template<class T>
335     static QContactFetchHint
336     fetchHint()
337     {
338         return fetchHint(QStringList(T::DefinitionName));
339     }
340
341     QString qStringArg(const QString &format, const QStringList &tokens);
342
343     QVariant changeSetting(const QString &key, const QVariant &value);
344     void resetSettings();
345
346 private:
347     mutable QctContactManagerEngine *m_engine;
348     QContactLocalIdList m_localIds;
349     QDir m_dataDir, m_srcDir;
350     /// unique identifier for a testrun, used e.g. to mark contacts stored in tracker
351     QString m_uuid;
352
353     QVariantHash m_oldSettings;
354
355 protected: // fields
356     bool m_verbose : 1;
357 };
358
359 #endif /* UT_QTCONTACTS_TRACKERPLUGIN_COMMON_H */