1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL21$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 or version 3 as published by the Free |
20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and |
21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the |
22 | ** following information to ensure the GNU Lesser General Public License |
23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and |
24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
25 | ** |
26 | ** As a special exception, The Qt Company gives you certain additional |
27 | ** rights. These rights are described in The Qt Company LGPL Exception |
28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
29 | ** |
30 | ** $QT_END_LICENSE$ |
31 | ** |
32 | ****************************************************************************/ |
33 | |
34 | #include <QtTest/QtTest> |
35 | |
36 | #include <QtCore/qset.h> |
37 | |
38 | #include <QtOrganizer/qorganizer.h> |
39 | #include <QtOrganizer/qorganizeritemid.h> |
40 | |
41 | //TESTED_COMPONENT=src/organizer |
42 | |
43 | QTORGANIZER_USE_NAMESPACE |
44 | |
45 | static inline QOrganizerCollectionId makeId(const QString &managerName, uint id) |
46 | { |
47 | return QOrganizerCollectionId(QStringLiteral("qtorganizer:%1:" ).arg(a: managerName), QByteArray(reinterpret_cast<const char *>(&id), sizeof(uint))); |
48 | } |
49 | |
50 | |
51 | class tst_QOrganizerCollection: public QObject |
52 | { |
53 | Q_OBJECT |
54 | |
55 | public: |
56 | tst_QOrganizerCollection(); |
57 | virtual ~tst_QOrganizerCollection(); |
58 | |
59 | private slots: |
60 | void metaData(); |
61 | void compare(); |
62 | void idComparison(); |
63 | void idHash(); |
64 | void idStringFunctions(); |
65 | void hash(); |
66 | void datastream(); |
67 | void traits(); |
68 | void idTraits(); |
69 | }; |
70 | |
71 | tst_QOrganizerCollection::tst_QOrganizerCollection() |
72 | { |
73 | } |
74 | |
75 | tst_QOrganizerCollection::~tst_QOrganizerCollection() |
76 | { |
77 | } |
78 | |
79 | void tst_QOrganizerCollection::metaData() |
80 | { |
81 | QOrganizerCollection c; |
82 | QVERIFY(c.metaData().isEmpty()); |
83 | c.setExtendedMetaData(key: QString(QStringLiteral("test" )), value: 5); |
84 | QCOMPARE(c.extendedMetaData(QString(QStringLiteral("test" ))).toInt(), 5); |
85 | |
86 | QMap<QOrganizerCollection::MetaDataKey, QVariant> mdm; |
87 | mdm.insert(akey: QOrganizerCollection::KeyName, avalue: QString(QStringLiteral("test2" ))); |
88 | c.setMetaData(mdm); |
89 | QCOMPARE(c.metaData(), mdm); |
90 | QCOMPARE(c.metaData(QOrganizerCollection::KeyName).toString(), QString(QStringLiteral("test2" ))); |
91 | } |
92 | |
93 | void tst_QOrganizerCollection::compare() |
94 | { |
95 | QOrganizerCollection c, c2; |
96 | QVERIFY(c == c2); |
97 | c.setExtendedMetaData(QStringLiteral("test" ), value: 5); |
98 | QVERIFY(c != c2); |
99 | c2.setExtendedMetaData(QStringLiteral("test" ), value: 5); |
100 | QVERIFY(c == c2); |
101 | |
102 | QMap<QOrganizerCollection::MetaDataKey, QVariant> mdm; |
103 | mdm.insert(akey: QOrganizerCollection::KeyName, QStringLiteral("test2" )); |
104 | c.setMetaData(mdm); |
105 | QVERIFY(c != c2); |
106 | c2.setMetaData(mdm); |
107 | QVERIFY(c == c2); |
108 | |
109 | c2 = QOrganizerCollection(); |
110 | QVERIFY(c != c2); |
111 | c2 = c; |
112 | QVERIFY(c == c2); |
113 | |
114 | c.setId(makeId(QStringLiteral("a" ), id: 1)); |
115 | QVERIFY(c != c2); |
116 | c2.setId(makeId(QStringLiteral("a" ), id: 1)); |
117 | QVERIFY(c == c2); |
118 | c.setId(makeId(QStringLiteral("b" ), id: 1)); |
119 | QVERIFY(c != c2); |
120 | c2.setId(c.id()); |
121 | QVERIFY(c == c2); |
122 | c.setId(makeId(QStringLiteral("b" ), id: 2)); |
123 | } |
124 | |
125 | void tst_QOrganizerCollection::idComparison() |
126 | { |
127 | QOrganizerCollectionId id1(makeId(managerName: "a" , id: 1)); |
128 | QOrganizerCollectionId id2(makeId(managerName: "a" , id: 1)); |
129 | QVERIFY(!(id1 < id2)); |
130 | QVERIFY(!(id2 < id1)); |
131 | QVERIFY(id1 == id2); |
132 | |
133 | QOrganizerCollectionId id3(makeId(managerName: "a" , id: 2)); |
134 | QOrganizerCollectionId id4(makeId(managerName: "b" , id: 1)); |
135 | QOrganizerCollectionId id5(makeId(managerName: "b" , id: 2)); |
136 | QVERIFY((((id1 < id3) && !(id3 < id1)) || ((id3 < id1) && !(id1 < id3))) && (id1 != id3)); |
137 | QVERIFY((((id1 < id4) && !(id4 < id1)) || ((id4 < id1) && !(id1 < id4))) && (id1 != id4)); |
138 | QVERIFY((((id3 < id4) && !(id4 < id3)) || ((id4 < id3) && !(id3 < id4))) && (id3 != id4)); |
139 | QVERIFY((((id1 < id5) && !(id5 < id1)) || ((id5 < id1) && !(id1 < id5))) && (id3 != id4)); |
140 | |
141 | QOrganizerCollectionId id6; |
142 | QOrganizerCollectionId id7(QString(), "1" ); |
143 | QOrganizerCollectionId id8(QString(), "2" ); |
144 | QOrganizerCollectionId id9(QStringLiteral("qtorganizer:basic:" ), QByteArray()); |
145 | QVERIFY(id6.isNull()); |
146 | QVERIFY(id7.isNull()); |
147 | QVERIFY(id8.isNull()); |
148 | QVERIFY(id9.isNull()); |
149 | QVERIFY(id6 == id7); |
150 | QVERIFY(!(id6 < id7)); |
151 | QVERIFY(id7 == id6); |
152 | QVERIFY(!(id7 < id6)); |
153 | QVERIFY(id7 == id8); |
154 | QVERIFY(!(id7 < id8)); |
155 | QVERIFY(id8 == id7); |
156 | QVERIFY(!(id9 < id8)); |
157 | QVERIFY(id8 == id9); |
158 | QVERIFY(!(id8 < id9)); |
159 | QVERIFY(id9 == id8); |
160 | QVERIFY(!(id9 < id8)); |
161 | |
162 | QVERIFY(!(id1 == id6)); |
163 | QVERIFY(!(id1 < id6)); |
164 | QVERIFY(id6 < id1); |
165 | QVERIFY(!(id1 == id7)); |
166 | QVERIFY(!(id1 < id7)); |
167 | QVERIFY(id7 < id1); |
168 | QVERIFY(!(id1 == id8)); |
169 | QVERIFY(!(id1 < id8)); |
170 | QVERIFY(id8 < id1); |
171 | QVERIFY(!(id1 == id9)); |
172 | QVERIFY(!(id1 < id9)); |
173 | QVERIFY(id9 < id1); |
174 | } |
175 | |
176 | void tst_QOrganizerCollection::idHash() |
177 | { |
178 | QOrganizerCollectionId id1(makeId(managerName: "a" , id: 1)); |
179 | QOrganizerCollectionId id2(makeId(managerName: "a" , id: 1)); |
180 | QOrganizerCollectionId id3(makeId(managerName: "b" , id: 1)); |
181 | QOrganizerCollectionId id4(makeId(managerName: "a" , id: 2)); |
182 | // note that the hash function ignores the managerUri |
183 | QCOMPARE(qHash(id1), qHash(id2)); |
184 | QCOMPARE(qHash(id1), qHash(id3)); |
185 | QVERIFY(qHash(id1) != qHash(id4)); |
186 | |
187 | QSet<QOrganizerCollectionId> set; |
188 | set.insert(value: id1); |
189 | set.insert(value: id2); |
190 | set.insert(value: id3); |
191 | set.insert(value: id4); |
192 | QCOMPARE(set.size(), 3); |
193 | } |
194 | |
195 | void tst_QOrganizerCollection::idStringFunctions() |
196 | { |
197 | // TODO: review test |
198 | QOrganizerCollectionId id1(makeId(managerName: "a" , id: 1)); |
199 | QOrganizerCollectionId id2(makeId(managerName: "a" , id: 1)); |
200 | QOrganizerCollectionId id3(makeId(managerName: "b" , id: 1)); |
201 | QOrganizerCollectionId id4(makeId(managerName: "a" , id: 2)); |
202 | QVERIFY(qHash(id1) == qHash(id2)); |
203 | QVERIFY(qHash(id1) != qHash(id4)); |
204 | |
205 | // note that the toString and fromString functions are |
206 | // engine and id specific. This test merely checks that |
207 | // the API is hooked up correctly. |
208 | |
209 | QVERIFY(id1.toString() == id2.toString()); |
210 | QVERIFY(id1.toString() != id3.toString()); |
211 | QVERIFY(id1.toString() != id4.toString()); |
212 | QVERIFY(id3.toString() != id4.toString()); |
213 | |
214 | // this should "work" -- string of the correct format |
215 | const uint numericId2 = 2u; |
216 | const QByteArray localId2 = QByteArray(reinterpret_cast<const char *>(&numericId2), sizeof(uint)); |
217 | QString prebuiltidstring = QString("qtorganizer" ) + QString(":" ) + QString("a" ) + QString("::" ) + localId2.toHex(); |
218 | QOrganizerCollectionId rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
219 | QVERIFY(rebuiltid == id4); |
220 | QVERIFY(rebuiltid.localId() == id4.localId()); |
221 | |
222 | // this string has the right format and one parameter, but requires a working backend |
223 | prebuiltidstring = QString("qtorganizer" ) + QString(":" ) + QString("a" ) + QString(":" ) + QString("key=value" ) + QString(":" ) + localId2.toHex(); |
224 | rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
225 | QVERIFY(rebuiltid != id4); |
226 | QVERIFY(rebuiltid.localId() == id4.localId()); |
227 | |
228 | // this string has the right format and some parameters, but requires a working backend |
229 | prebuiltidstring = QString("qtorganizer" ) + QString(":" ) + QString("a" ) + QString(":" ) + QString("key=value&key2=value2" ) + QString(":" ) + localId2.toHex(); |
230 | rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
231 | QVERIFY(rebuiltid != id4); |
232 | QVERIFY(rebuiltid.localId() == id4.localId()); |
233 | |
234 | // this string has the right format but misses the value for a parameter |
235 | prebuiltidstring = QString("qtorganizer" ) + QString(":" ) + QString("a" ) + QString(":" ) + QString("key=value&key2=" ) + QString(":" ) + localId2.toHex(); |
236 | rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
237 | QVERIFY(rebuiltid != id4); |
238 | QVERIFY(rebuiltid.localId() == id4.localId()); |
239 | |
240 | // this string misses a field (the parameters) |
241 | prebuiltidstring = QString("qtorganizer" ) + QString(":" ) + QString("a" ) + QString(":" ) + localId2.toHex(); |
242 | rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
243 | QVERIFY(rebuiltid == QOrganizerCollectionId()); // invalid so should be null. |
244 | |
245 | // this string misses two fields (params plus manager uri) |
246 | prebuiltidstring = QString("qtorganizer" ) + QString(":" ) + QString::number(2); |
247 | rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
248 | QVERIFY(rebuiltid == QOrganizerCollectionId()); // invalid so should be null. |
249 | |
250 | // this string misses the prefix (qtorganizer) |
251 | prebuiltidstring = QString("notorganizer" ) + QString(":" ) + QString("a" ) + QString("::" ) + localId2.toHex(); |
252 | rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
253 | QVERIFY(rebuiltid == QOrganizerCollectionId()); // invalid so should be null. |
254 | |
255 | // this string misses the manager uri |
256 | prebuiltidstring = QString("notorganizer" ) + QString(":::" ) + localId2.toHex(); |
257 | rebuiltid = QOrganizerCollectionId::fromString(idString: prebuiltidstring); |
258 | QVERIFY(rebuiltid == QOrganizerCollectionId()); // invalid so should be null. |
259 | } |
260 | |
261 | void tst_QOrganizerCollection::hash() |
262 | { |
263 | // TODO: review tests |
264 | QOrganizerCollectionId id(makeId(managerName: "a" , id: 1)); |
265 | QOrganizerCollection c1; |
266 | c1.setId(id); |
267 | c1.setExtendedMetaData(key: "key" , value: "value" ); |
268 | QOrganizerCollection c2; |
269 | c2.setId(id); |
270 | c2.setExtendedMetaData(key: "key" , value: "value" ); |
271 | QOrganizerCollection c3; |
272 | c3.setId(id); |
273 | c3.setExtendedMetaData(key: "key" , value: "another value" ); |
274 | QOrganizerCollection c4; // no details |
275 | c4.setId(id); |
276 | QOrganizerCollection c5; |
277 | c5.setId(id); |
278 | c5.setExtendedMetaData(key: "key" , value: "value" ); |
279 | QVERIFY(qHash(c1) == qHash(c2)); |
280 | QVERIFY(qHash(c1) != qHash(c3)); |
281 | QVERIFY(qHash(c1) != qHash(c4)); |
282 | QVERIFY(qHash(c1) == qHash(c5)); |
283 | } |
284 | |
285 | void tst_QOrganizerCollection::datastream() |
286 | { |
287 | // collection datastreaming |
288 | QByteArray buffer; |
289 | QOrganizerCollection collectionIn; |
290 | collectionIn.setExtendedMetaData(key: "key" , value: "value" ); |
291 | QOrganizerCollection collectionOut; |
292 | QOrganizerCollectionId originalId; |
293 | |
294 | // first, stream an item with a complete id |
295 | { |
296 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
297 | QOrganizerManager om("memory" ); |
298 | QVERIFY(om.saveCollection(&collectionIn)); // fill in its ID |
299 | originalId = collectionIn.id(); |
300 | stream1 << collectionIn; |
301 | QVERIFY(buffer.size() > 0); |
302 | QDataStream stream2(buffer); |
303 | stream2 >> collectionOut; |
304 | QCOMPARE(collectionOut, collectionIn); // can use QCOMPARE for collections, since no detail keys. |
305 | } |
306 | |
307 | // second, stream an item with an id with the mgr uri set, local id null |
308 | { |
309 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
310 | collectionIn.setId(QOrganizerCollectionId()); |
311 | stream1 << collectionIn; |
312 | QVERIFY(buffer.size() > 0); |
313 | QDataStream stream2(buffer); |
314 | stream2 >> collectionOut; |
315 | QCOMPARE(collectionOut, collectionIn); // can use QCOMPARE for collections, since no detail keys. |
316 | } |
317 | |
318 | /* TODO: Review tests |
319 | // third, stream an item with an id with the mgr uri null, local id set |
320 | { |
321 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
322 | QOrganizerCollectionId modifiedId = originalId; |
323 | modifiedId.setManagerUri(QString()); // this will clear the local id! |
324 | modifiedId.setId(originalId.localId()); // so reset it and make sure nothing bad happens. |
325 | collectionIn.setId(modifiedId); |
326 | stream1 << collectionIn; |
327 | QVERIFY(buffer.size() > 0); |
328 | QDataStream stream2(buffer); |
329 | stream2 >> collectionOut; |
330 | QVERIFY(collectionOut.metaData() == collectionIn.metaData()); |
331 | QVERIFY(collectionOut.id() != collectionIn.id()); // no manager uri of input :. won't be serialized. |
332 | }*/ |
333 | |
334 | // fourth, stream an item with a null id |
335 | { |
336 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
337 | collectionIn.setId(QOrganizerCollectionId()); |
338 | stream1 << collectionIn; |
339 | QVERIFY(buffer.size() > 0); |
340 | QDataStream stream2(buffer); |
341 | stream2 >> collectionOut; |
342 | QVERIFY(collectionOut.metaData() == collectionIn.metaData()); |
343 | QVERIFY(collectionOut.id() == collectionIn.id()); // should both be null ids. |
344 | } |
345 | |
346 | // id datastreaming |
347 | buffer.clear(); |
348 | QOrganizerCollectionId inputId; |
349 | QOrganizerCollectionId outputId; |
350 | |
351 | // first, stream the whole id (mgr uri set, local id set) |
352 | { |
353 | inputId = originalId; |
354 | QString serializedId = inputId.toString(); |
355 | outputId = QOrganizerCollectionId::fromString(idString: serializedId); |
356 | QCOMPARE(inputId, outputId); |
357 | |
358 | inputId = originalId; |
359 | buffer.clear(); |
360 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
361 | stream1 << inputId; |
362 | QVERIFY(buffer.size() > 0); |
363 | QDataStream stream2(buffer); |
364 | stream2 >> outputId; |
365 | QCOMPARE(inputId, outputId); |
366 | } |
367 | |
368 | /* TODO: review test |
369 | // second, stream a partial id (mgr uri null, local id set) |
370 | { |
371 | inputId.setManagerUri(QString()); |
372 | inputId.setId(originalId.localId()); |
373 | buffer.clear(); |
374 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
375 | stream1 << inputId; |
376 | QVERIFY(buffer.size() > 0); |
377 | QDataStream stream2(buffer); |
378 | stream2 >> outputId; |
379 | |
380 | // because the manager uri is null, we cannot stream it in. |
381 | QVERIFY(outputId.isNull()); |
382 | QVERIFY(!inputId.isNull()); |
383 | } |
384 | |
385 | // third, stream a partial id (mgr uri set, local id null). |
386 | { |
387 | inputId.setManagerUri(originalId.managerUri()); |
388 | inputId.setId(QOrganizerCollectionId()); |
389 | buffer.clear(); |
390 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
391 | stream1 << inputId; |
392 | QVERIFY(buffer.size() > 0); |
393 | QDataStream stream2(buffer); |
394 | stream2 >> outputId; |
395 | QCOMPARE(inputId, outputId); |
396 | }*/ |
397 | |
398 | // fourth, stream a null id |
399 | { |
400 | inputId = QOrganizerCollectionId(); |
401 | QString serializedId = inputId.toString(); |
402 | outputId = QOrganizerCollectionId::fromString(idString: serializedId); |
403 | QCOMPARE(inputId, outputId); |
404 | |
405 | inputId = QOrganizerCollectionId(); |
406 | buffer.clear(); |
407 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
408 | stream1 << inputId; |
409 | QVERIFY(buffer.size() > 0); |
410 | QDataStream stream2(buffer); |
411 | stream2 >> outputId; |
412 | QCOMPARE(inputId, outputId); |
413 | } |
414 | |
415 | /* TODO: review test |
416 | // fifth, stream an id after changing it's manager uri. |
417 | { |
418 | inputId.setManagerUri(originalId.managerUri()); |
419 | inputId.setId(originalId.localId()); |
420 | inputId.setManagerUri("test manager uri"); // should clear the local id. |
421 | QVERIFY(inputId.localId() == QOrganizerCollectionId()); |
422 | buffer.clear(); |
423 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
424 | stream1 << inputId; |
425 | QVERIFY(buffer.size() > 0); |
426 | QDataStream stream2(buffer); |
427 | stream2 >> outputId; |
428 | QCOMPARE(inputId, outputId); |
429 | } |
430 | |
431 | // sixth, stream an id after changing it's manager uri and resetting the local id. |
432 | // this should cause great problems, because the manager doesn't exist so it shouldn't |
433 | // be able to deserialize. Make sure it's handled gracefully. |
434 | { |
435 | inputId.setManagerUri(originalId.managerUri()); |
436 | inputId.setManagerUri("test manager uri"); // should clear the local id. |
437 | inputId.setId(originalId.localId()); |
438 | buffer.clear(); |
439 | QDataStream stream1(&buffer, QIODevice::WriteOnly); |
440 | stream1 << inputId; |
441 | QVERIFY(buffer.size() > 0); |
442 | QDataStream stream2(buffer); |
443 | stream2 >> outputId; |
444 | QVERIFY(outputId.isNull()); |
445 | } */ |
446 | } |
447 | |
448 | void tst_QOrganizerCollection::traits() |
449 | { |
450 | QCOMPARE(sizeof(QOrganizerCollection), sizeof(void *)); |
451 | QVERIFY(QTypeInfo<QOrganizerCollection>::isComplex); |
452 | QVERIFY(!QTypeInfo<QOrganizerCollection>::isStatic); |
453 | QVERIFY(!QTypeInfo<QOrganizerCollection>::isLarge); |
454 | QVERIFY(!QTypeInfo<QOrganizerCollection>::isPointer); |
455 | QVERIFY(!QTypeInfo<QOrganizerCollection>::isDummy); |
456 | } |
457 | |
458 | void tst_QOrganizerCollection::idTraits() |
459 | { |
460 | QCOMPARE(sizeof(QOrganizerCollectionId), 2*sizeof(void *)); |
461 | QVERIFY(QTypeInfo<QOrganizerCollectionId>::isComplex); |
462 | QVERIFY(!QTypeInfo<QOrganizerCollectionId>::isStatic); |
463 | QVERIFY(QTypeInfo<QOrganizerCollectionId>::isLarge); |
464 | QVERIFY(!QTypeInfo<QOrganizerCollectionId>::isPointer); |
465 | QVERIFY(!QTypeInfo<QOrganizerCollectionId>::isDummy); |
466 | } |
467 | |
468 | QTEST_MAIN(tst_QOrganizerCollection) |
469 | #include "tst_qorganizercollection.moc" |
470 | |