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/QCoreApplication>
37#include <QtCore/QScopedPointer>
38
39#include <QtOrganizer/qorganizer.h>
40#include "../../qorganizermanagerdataholder.h" //QOrganizerManagerDataHolder
41
42Q_DECLARE_METATYPE(QTORGANIZER_PREPEND_NAMESPACE(QOrganizerAbstractRequest::State))
43
44QTORGANIZER_USE_NAMESPACE
45
46/* Define an innocuous request (fetch ie doesn't mutate) to "fill up" any queues */
47#define FILL_QUEUE_WITH_FETCH_REQUESTS(manager) QOrganizerItemFetchRequest fqifr1, fqifr2, fqifr3; \
48 fqifr1.setManager(manager); fqifr1.start(); \
49 fqifr2.setManager(manager); fqifr2.start(); \
50 fqifr3.setManager(manager); fqifr3.start();
51
52//TESTED_COMPONENT=src/organizer
53
54// Unfortunately the plumbing isn't in place to allow cancelling requests at arbitrary points
55// in their processing. So we do multiple loops until things work out.. or not
56#define MAX_OPTIMISTIC_SCHEDULING_LIMIT 100
57
58
59// Thread capable QThreadSignalSpy (to avoid data races with count/appendArgS)
60class QThreadSignalSpy: public QObject
61{
62public:
63 QThreadSignalSpy(QObject *obj, const char *aSignal)
64 {
65 QMutexLocker m(&lock);
66#ifdef Q_CC_BOR
67 const int memberOffset = QObject::staticMetaObject.methodCount();
68#else
69 static const int memberOffset = QObject::staticMetaObject.methodCount();
70#endif
71 Q_ASSERT(obj);
72 Q_ASSERT(aSignal);
73
74 if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE) {
75 qWarning(msg: "QThreadSignalSpy: Not a valid signal, use the SIGNAL macro");
76 return;
77 }
78
79 QByteArray ba = QMetaObject::normalizedSignature(method: aSignal + 1);
80 const QMetaObject *mo = obj->metaObject();
81 int sigIndex = mo->indexOfMethod(method: ba.constData());
82 if (sigIndex < 0) {
83 qWarning(msg: "QThreadSignalSpy: No such signal: '%s'", ba.constData());
84 return;
85 }
86
87 if (!QMetaObject::connect(sender: obj, signal_index: sigIndex, receiver: this, method_index: memberOffset,
88 type: Qt::DirectConnection, types: 0)) {
89 qWarning(msg: "QThreadSignalSpy: QMetaObject::connect returned false. Unable to connect.");
90 return;
91 }
92 sig = ba;
93 initArgs(member: mo->method(index: sigIndex));
94 }
95
96 inline bool isValid() const { return !sig.isEmpty(); }
97 inline QByteArray signal() const { return sig; }
98
99 int qt_metacall(QMetaObject::Call call, int methodId, void **a)
100 {
101 methodId = QObject::qt_metacall(call, methodId, a);
102 if (methodId < 0)
103 return methodId;
104
105 if (call == QMetaObject::InvokeMetaMethod) {
106 if (methodId == 0) {
107 appendArgs(a);
108 }
109 --methodId;
110 }
111 return methodId;
112 }
113
114 // The QList<QVariantList> API we actually use
115 int count() const
116 {
117 QMutexLocker m(&lock);
118 return savedArgs.count();
119 }
120 void clear()
121 {
122 QMutexLocker m(&lock);
123 savedArgs.clear();
124 }
125
126private:
127 void initArgs(const QMetaMethod &member)
128 {
129 QList<QByteArray> params = member.parameterTypes();
130 for (int i = 0; i < params.count(); ++i) {
131 int tp = QMetaType::type(typeName: params.at(i).constData());
132 if (tp == QMetaType::Void)
133 qWarning(msg: "Don't know how to handle '%s', use qRegisterMetaType to register it.",
134 params.at(i).constData());
135 args << tp;
136 }
137 }
138
139 void appendArgs(void **a)
140 {
141 QMutexLocker m(&lock);
142 QList<QVariant> list;
143 for (int i = 0; i < args.count(); ++i) {
144 QMetaType::Type type = static_cast<QMetaType::Type>(args.at(i));
145 list << QVariant(type, a[i + 1]);
146 }
147 savedArgs.append(t: list);
148 }
149
150 // the full, normalized signal name
151 QByteArray sig;
152 // holds the QMetaType types for the argument list of the signal
153 QList<int> args;
154
155 mutable QMutex lock;
156 // Different API
157 QList< QVariantList> savedArgs;
158};
159
160class tst_QOrganizerItemAsync : public QObject
161{
162 Q_OBJECT
163
164public:
165 tst_QOrganizerItemAsync();
166 virtual ~tst_QOrganizerItemAsync();
167
168public slots:
169 void initTestCase();
170 void cleanupTestCase();
171
172private:
173 void addManagers(QStringList includes = QStringList()); // add standard managers to the data
174
175private slots:
176 void testDestructor();
177 void testDestructor_data() { addManagers(includes: QStringList(QString("maliciousplugin"))); }
178
179 void itemFetch();
180 void itemFetch_data() { addManagers(); }
181 void itemFetchById();
182 void itemFetchById_data() { addManagers(); }
183 void itemIdFetch();
184 void itemIdFetch_data() { addManagers(); }
185 void itemOccurrenceFetch();
186 void itemOccurrenceFetch_data() { addManagers(); }
187 void itemFetchForExport();
188 void itemFetchForExport_data() { addManagers(); }
189 void itemRemove();
190 void itemRemove_data() { addManagers(); }
191 void itemRemoveById();
192 void itemRemoveById_data() { addManagers(); }
193 void itemSave();
194 void itemSave_data() { addManagers(); }
195 void itemListSave();
196 void itemListSave_data() { addManagers(); }
197 void itemPartialSave();
198 void itemPartialSave_data() { addManagers(); }
199
200 void collectionFetch();
201 void collectionFetch_data() { addManagers(); }
202 void collectionRemove();
203 void collectionRemove_data() { addManagers(); }
204 void collectionSave();
205 void collectionSave_data() { addManagers(); }
206
207 void testQuickDestruction();
208 void testQuickDestruction_data() { addManagers(includes: QStringList(QString("maliciousplugin"))); }
209
210 void threadDelivery();
211 void threadDelivery_data() { addManagers(includes: QStringList(QString("maliciousplugin"))); }
212 void testDebugStreamOut();
213
214protected slots:
215 void resultsAvailableReceived();
216
217private:
218 bool compareItemLists(QList<QOrganizerItem> lista, QList<QOrganizerItem> listb);
219 bool compareItems(QOrganizerItem ca, QOrganizerItem cb);
220 bool containsIgnoringTimestamps(const QList<QOrganizerItem>& list, const QOrganizerItem& c);
221 bool compareIgnoringTimestamps(const QOrganizerItem& ca, const QOrganizerItem& cb);
222 bool containsIgnoringDetailKeys(const QList<QOrganizerItem>& list, const QOrganizerItem& c);
223 bool compareIgnoringDetailKeys(const QOrganizerItem& ca, const QOrganizerItem& cb);
224 bool detailListContainsDetailIgnoringDetailKeys(const QList<QOrganizerItemDetail>& dets, const QOrganizerItemDetail& det);
225 bool containsAllCollectionIds(const QList<QOrganizerCollectionId>& target, const QList<QOrganizerCollectionId>& ids);
226 QOrganizerManager* prepareModel(const QString& uri);
227
228 Qt::HANDLE m_mainThreadId;
229 Qt::HANDLE m_resultsAvailableSlotThreadId;
230 QScopedPointer<QOrganizerManagerDataHolder> managerDataHolder;
231};
232
233tst_QOrganizerItemAsync::tst_QOrganizerItemAsync()
234{
235 // ensure we can load all of the plugins we need to.
236 QString path = QCoreApplication::applicationDirPath() + QStringLiteral("/dummyplugin/plugins");
237 QCoreApplication::addLibraryPath(path);
238
239 qRegisterMetaType<QOrganizerAbstractRequest::State>();
240}
241
242tst_QOrganizerItemAsync::~tst_QOrganizerItemAsync()
243{
244}
245
246void tst_QOrganizerItemAsync::initTestCase()
247{
248 managerDataHolder.reset(other: new QOrganizerManagerDataHolder());
249}
250
251void tst_QOrganizerItemAsync::cleanupTestCase()
252{
253 managerDataHolder.reset(other: 0);
254}
255
256bool tst_QOrganizerItemAsync::compareItemLists(QList<QOrganizerItem> lista, QList<QOrganizerItem> listb)
257{
258 // NOTE: This compare is item order insensitive.
259
260 // Remove matching items
261 foreach (QOrganizerItem a, lista) {
262 foreach (QOrganizerItem b, listb) {
263 if (compareItems(ca: a, cb: b)) {
264 lista.removeOne(t: a);
265 listb.removeOne(t: b);
266 break;
267 }
268 }
269 }
270 return (lista.count() == 0 && listb.count() == 0);
271}
272
273bool tst_QOrganizerItemAsync::compareItems(QOrganizerItem ca, QOrganizerItem cb)
274{
275 // NOTE: This compare is item detail order insensitive.
276
277 if (ca.id() != cb.id())
278 return false;
279
280 QList<QOrganizerItemDetail> aDetails = ca.details();
281 QList<QOrganizerItemDetail> bDetails = cb.details();
282
283 // Remove matching details
284 foreach (QOrganizerItemDetail ad, aDetails) {
285 foreach (QOrganizerItemDetail bd, bDetails) {
286 if (ad == bd) {
287 ca.removeDetail(detail: &ad);
288 cb.removeDetail(detail: &bd);
289 break;
290 }
291
292 // Special handling for timestamp
293 if (ad.type() == QOrganizerItemDetail::TypeTimestamp
294 && bd.type() == QOrganizerItemDetail::TypeTimestamp) {
295 QOrganizerItemTimestamp at = static_cast<QOrganizerItemTimestamp>(ad);
296 QOrganizerItemTimestamp bt = static_cast<QOrganizerItemTimestamp>(bd);
297 if (at.created().toString() == bt.created().toString() &&
298 at.lastModified().toString() == bt.lastModified().toString()) {
299 ca.removeDetail(detail: &ad);
300 cb.removeDetail(detail: &bd);
301 break;
302 }
303
304 }
305 }
306 }
307 return (ca == cb);
308}
309
310bool tst_QOrganizerItemAsync::containsIgnoringTimestamps(const QList<QOrganizerItem>& list, const QOrganizerItem& c)
311{
312 QList<QOrganizerItem> cl = list;
313 QOrganizerItem a(c);
314 for (int i = 0; i < cl.size(); i++) {
315 QOrganizerItem b(cl.at(i));
316 if (compareIgnoringTimestamps(ca: a, cb: b))
317 return true;
318 }
319
320 return false;
321}
322
323bool tst_QOrganizerItemAsync::compareIgnoringTimestamps(const QOrganizerItem& ca, const QOrganizerItem& cb)
324{
325 // Compares two items, ignoring any timestamp details
326 QOrganizerItem a(ca);
327 QOrganizerItem b(cb);
328 QList<QOrganizerItemDetail> aDetails = a.details();
329 QList<QOrganizerItemDetail> bDetails = b.details();
330
331 // They can be in any order, so loop
332 // First remove any matches, and any timestamps
333 foreach (QOrganizerItemDetail d, aDetails) {
334 foreach (QOrganizerItemDetail d2, bDetails) {
335 if (d == d2) {
336 a.removeDetail(detail: &d);
337 b.removeDetail(detail: &d2);
338 break;
339 }
340
341 if (d.type() == QOrganizerItemDetail::TypeTimestamp)
342 a.removeDetail(detail: &d);
343
344 if (d2.type() == QOrganizerItemDetail::TypeTimestamp)
345 b.removeDetail(detail: &d2);
346 }
347 }
348
349 if (a == b)
350 return true;
351 return false;
352}
353
354
355bool tst_QOrganizerItemAsync::containsIgnoringDetailKeys(const QList<QOrganizerItem>& list, const QOrganizerItem& c)
356{
357 QList<QOrganizerItem> cl = list;
358 QOrganizerItem a(c);
359 for (int i = 0; i < cl.size(); i++) {
360 QOrganizerItem b(cl.at(i));
361 if (compareIgnoringDetailKeys(ca: a, cb: b))
362 return true;
363 }
364
365 return false;
366}
367
368bool tst_QOrganizerItemAsync::compareIgnoringDetailKeys(const QOrganizerItem& ca, const QOrganizerItem& cb)
369{
370 // Compares two items, ignoring any timestamp details
371 QOrganizerItem a(ca);
372 QOrganizerItem b(cb);
373 QList<QOrganizerItemDetail> aDetails = a.details();
374 QList<QOrganizerItemDetail> bDetails = b.details();
375
376 // They can be in any order, so loop
377 // First remove any matches, and any timestamps
378 foreach (QOrganizerItemDetail d, aDetails) {
379 foreach (QOrganizerItemDetail d2, bDetails) {
380 if (d == d2) {
381 a.removeDetail(detail: &d);
382 b.removeDetail(detail: &d2);
383 break;
384 }
385
386 // equality without checking the detail key values.
387 if (d.type() == d2.type() && d.values() == d2.values()) {
388 a.removeDetail(detail: &d);
389 b.removeDetail(detail: &d2);
390 break;
391 }
392
393 // and we have to ignore timestamps
394 if (d.type() == QOrganizerItemDetail::TypeTimestamp)
395 a.removeDetail(detail: &d);
396
397 if (d2.type() == QOrganizerItemDetail::TypeTimestamp)
398 b.removeDetail(detail: &d2);
399 }
400 }
401
402 if (a == b)
403 return true;
404
405 // now compare the details, ignoring the keys.
406 aDetails = a.details();
407 bDetails = b.details();
408 foreach (QOrganizerItemDetail d, aDetails) {
409 bool foundCurrentDetail = false;
410 foreach (QOrganizerItemDetail d2, bDetails) {
411 if (d.type() == d2.type() && d.values() == d2.values()) {
412 foundCurrentDetail = true;
413 }
414
415 if (d.type() == d2.type() && d.type() == QOrganizerItemDetail::TypeParent) {
416 // XXX TODO: fix this properly in code. At the moment, doing d.values() == d2.values() doesn't work for ParentItem details.
417 QOrganizerItemParent p1 = d;
418 QOrganizerItemParent p2 = d2;
419 if (p1.parentId() == p2.parentId()) {
420 foundCurrentDetail = true;
421 }
422 }
423 }
424
425 if (!foundCurrentDetail) {
426 return false;
427 }
428 }
429
430 return true;
431}
432
433bool tst_QOrganizerItemAsync::detailListContainsDetailIgnoringDetailKeys(const QList<QOrganizerItemDetail>& dets, const QOrganizerItemDetail& det)
434{
435 bool foundCurrentDetail = false;
436 foreach (const QOrganizerItemDetail d2, dets) {
437 if (det == d2) {
438 foundCurrentDetail = true;
439 }
440
441 if (det.type() == d2.type() && det.values() == d2.values()) {
442 foundCurrentDetail = true;
443 }
444
445 if (det.type() == d2.type() && det.type() == QOrganizerItemDetail::TypeParent) {
446 // XXX TODO: fix this properly in code. At the moment, doing d.values() == d2.values() doesn't work for ParentItem details.
447 QOrganizerItemParent p1 = det;
448 QOrganizerItemParent p2 = d2;
449 if (p1.parentId() == p2.parentId()) {
450 foundCurrentDetail = true;
451 }
452 }
453 }
454
455 if (!foundCurrentDetail) {
456 return false;
457 }
458
459 return true;
460}
461
462bool tst_QOrganizerItemAsync::containsAllCollectionIds(const QList<QOrganizerCollectionId>& target, const QList<QOrganizerCollectionId>& ids)
463{
464 bool containsAllIds = true;
465 foreach(QOrganizerCollectionId id, ids) {
466 if (!target.contains(t: id)) {
467 containsAllIds = false;
468 break;
469 }
470 }
471 return containsAllIds;
472}
473
474void tst_QOrganizerItemAsync::testDestructor()
475{
476 QFETCH(QString, uri);
477 QOrganizerManager* cm = prepareModel(uri);
478 QOrganizerItemFetchRequest* req = new QOrganizerItemFetchRequest;
479 req->setManager(cm);
480
481 QOrganizerManager* cm2 = prepareModel(uri);
482 QOrganizerItemFetchRequest* req2 = new QOrganizerItemFetchRequest;
483 req2->setManager(cm2);
484
485 // first, delete manager then request
486 delete cm;
487 delete req;
488
489 // second, delete request then manager
490 delete req2;
491 delete cm2;
492}
493
494void tst_QOrganizerItemAsync::itemFetch()
495{
496 QFETCH(QString, uri);
497 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
498
499 QOrganizerItemFetchRequest ifr;
500 QVERIFY(ifr.type() == QOrganizerAbstractRequest::ItemFetchRequest);
501
502 // initial state - not started, no manager.
503 QVERIFY(!ifr.isActive());
504 QVERIFY(!ifr.isFinished());
505 QVERIFY(!ifr.start());
506 QVERIFY(!ifr.cancel());
507 QVERIFY(!ifr.waitForFinished());
508
509 // "all items" retrieval
510 QOrganizerItemFilter fil;
511 ifr.setManager(oim.data());
512 QCOMPARE(ifr.manager(), oim.data());
513 QVERIFY(!ifr.isActive());
514 QVERIFY(!ifr.isFinished());
515 QVERIFY(!ifr.cancel());
516 QVERIFY(!ifr.waitForFinished());
517 qRegisterMetaType<QOrganizerItemFetchRequest*>(typeName: "QOrganizerItemFetchRequest*");
518 QThreadSignalSpy spy(&ifr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
519 ifr.setFilter(fil);
520 QCOMPARE(ifr.filter(), fil);
521 QVERIFY(!ifr.cancel()); // not started
522
523 QVERIFY(ifr.start());
524 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
525 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
526 QVERIFY(ifr.waitForFinished());
527 QVERIFY(ifr.isFinished());
528
529 QVERIFY(spy.count() >= 1); // active + finished progress signals
530 spy.clear();
531
532 QList<QOrganizerItem> mitems = oim->items();
533 QList<QOrganizerItem> items = ifr.items();
534 QCOMPARE(mitems.size(), items.size());
535 for (int i = 0; i < items.size(); i++) {
536 QVERIFY(containsIgnoringDetailKeys(mitems, items.at(i)));
537 }
538
539 // asynchronous detail field filtering
540 QOrganizerItemDetailFieldFilter dfil;
541 dfil.setDetail(detailType: QOrganizerItemDetail::TypeLocation, field: QOrganizerItemLocation::FieldLabel);
542 ifr.setFilter(dfil);
543 QVERIFY(ifr.filter() == dfil);
544 QVERIFY(!ifr.cancel()); // not started
545
546 QVERIFY(ifr.start());
547 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
548 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
549 QVERIFY(ifr.waitForFinished());
550 QVERIFY(ifr.isFinished());
551 QVERIFY(spy.count() >= 1); // active + finished progress signals
552 spy.clear();
553
554 mitems = oim->items(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: dfil);
555 items = ifr.items();
556 QVERIFY(!mitems.isEmpty());
557 QCOMPARE(mitems.size(), items.size());
558 for (int i = 0; i < items.size(); i++) {
559 QVERIFY(containsIgnoringDetailKeys(mitems, items.at(i)));
560 }
561
562 // sort order
563 QOrganizerItemSortOrder sortOrder;
564 sortOrder.setDetail(detailType: QOrganizerItemDetail::TypePriority, field: QOrganizerItemPriority::FieldPriority);
565 QList<QOrganizerItemSortOrder> sorting;
566 sorting.append(t: sortOrder);
567 ifr.setFilter(fil);
568 ifr.setSorting(sorting);
569 QCOMPARE(ifr.sorting(), sorting);
570 QVERIFY(!ifr.cancel()); // not started
571 QVERIFY(ifr.start());
572 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
573 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
574 QVERIFY(ifr.waitForFinished());
575 QVERIFY(ifr.isFinished());
576
577 QVERIFY(spy.count() >= 1); // active + finished progress signals
578 spy.clear();
579
580 mitems = oim->items(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: QOrganizerItemFilter(), maxCount: -1, sortOrders: sorting);
581 items = ifr.items();
582 QCOMPARE(mitems.size(), items.size());
583 for (int i = 0; i < items.size(); i++) {
584 QVERIFY(containsIgnoringDetailKeys(mitems, items.at(i)));
585 }
586
587 // restrictions
588 sorting.clear();
589 ifr.setFilter(fil);
590 ifr.setSorting(sorting);
591 QOrganizerItemFetchHint fetchHint;
592 fetchHint.setDetailTypesHint(QList<QOrganizerItemDetail::DetailType>() << QOrganizerItemDetail::TypeDescription);
593 ifr.setFetchHint(fetchHint);
594 QCOMPARE(ifr.fetchHint().detailTypesHint(), QList<QOrganizerItemDetail::DetailType>() << QOrganizerItemDetail::TypeDescription);
595 QVERIFY(!ifr.cancel()); // not started
596 QVERIFY(ifr.start());
597 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
598 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
599 QVERIFY(ifr.waitForFinished());
600 QVERIFY(ifr.isFinished());
601
602 QVERIFY(spy.count() >= 1); // active + finished progress signals
603 spy.clear();
604
605 mitems = oim->items(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: QOrganizerItemFilter(), maxCount: -1, sortOrders: sorting);
606 items = ifr.items();
607 QCOMPARE(mitems.size(), items.size());
608 for (int i = 0; i < mitems.size(); i++) {
609 // create a item from the restricted data only (id + display label)
610 QOrganizerItem currFull = mitems.at(i);
611 QOrganizerItem currRestricted; // in prepare model, the items are all events.
612 if (currFull.type() == QOrganizerItemType::TypeEvent) {
613 currRestricted = QOrganizerEvent(); // therefore, the returned items will either be events
614 } else if (currFull.type() == QOrganizerItemType::TypeEventOccurrence) {
615 currRestricted = QOrganizerEventOccurrence(); // or event occurrences.
616 }
617 currRestricted.setId(currFull.id());
618 QList<QOrganizerItemDetail> descriptions = currFull.details(detailType: QOrganizerItemDetail::TypeDescription);
619 foreach (const QOrganizerItemDescription& description, descriptions) {
620 QOrganizerItemDescription descr = description;
621 if (!descr.isEmpty()) {
622 currRestricted.saveDetail(detail: &descr);
623 }
624 }
625
626 // now find the item in the retrieved list which our restricted item mimics
627 QOrganizerItem retrievedRestricted;
628 bool found = false;
629 foreach (const QOrganizerItem& retrieved, items) {
630 if (retrieved.id() == currRestricted.id()) {
631 retrievedRestricted = retrieved;
632 found = true;
633 }
634 }
635
636 QVERIFY(found); // must exist or fail.
637
638 // ensure that the item is the same (except synth fields)
639 QList<QOrganizerItemDetail> retrievedDetails = retrievedRestricted.details();
640 QList<QOrganizerItemDetail> expectedDetails = currRestricted.details();
641 foreach (const QOrganizerItemDetail& det, expectedDetails) {
642 // ignore backend synthesised details
643 // again, this requires a "default item details" function to work properly.
644 if (det.type() == QOrganizerItemDetail::TypeTimestamp)
645 continue;
646
647 // everything else in the expected item should be in the retrieved one.
648 QVERIFY(detailListContainsDetailIgnoringDetailKeys(retrievedDetails, det));
649 }
650 }
651
652 // cancelling
653 sorting.clear();
654 ifr.setFilter(fil);
655 ifr.setSorting(sorting);
656 ifr.setFetchHint(QOrganizerItemFetchHint());
657
658 int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
659 while (true) {
660 QVERIFY(!ifr.cancel()); // not started
661 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
662 QVERIFY(ifr.start());
663 if (!ifr.cancel()) {
664 // due to thread scheduling, async cancel might be attempted
665 // after the request has already finished.. so loop and try again.
666 spy.clear();
667 ifr.waitForFinished();
668 sorting.clear();
669 ifr.setFilter(fil);
670 ifr.setSorting(sorting);
671 ifr.setFetchHint(QOrganizerItemFetchHint());
672 ifr.setFetchHint(QOrganizerItemFetchHint());
673 bailoutCount -= 1;
674 if (!bailoutCount) {
675// qWarning("Unable to test cancelling due to thread scheduling!");
676 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
677 break;
678 }
679 continue;
680 }
681
682 // if we get here, then we are cancelling the request.
683 QVERIFY(ifr.waitForFinished());
684 QVERIFY(ifr.isCanceled());
685
686 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
687 spy.clear();
688 break;
689 }
690
691 // restart, and wait for progress after cancel.
692 while (true) {
693 QVERIFY(!ifr.cancel()); // not started
694 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
695 QVERIFY(ifr.start());
696 if (!ifr.cancel()) {
697 // due to thread scheduling, async cancel might be attempted
698 // after the request has already finished.. so loop and try again.
699 ifr.waitForFinished();
700 sorting.clear();
701 ifr.setFilter(fil);
702 ifr.setSorting(sorting);
703 ifr.setFetchHint(QOrganizerItemFetchHint());
704 bailoutCount -= 1;
705 spy.clear();
706 if (!bailoutCount) {
707 //qWarning("Unable to test cancelling due to thread scheduling!");
708 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
709 break;
710 }
711 continue;
712 }
713 ifr.waitForFinished();
714 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
715 spy.clear();
716 QVERIFY(!ifr.isActive());
717 QVERIFY(ifr.state() == QOrganizerAbstractRequest::CanceledState);
718 break;
719 }
720}
721
722void tst_QOrganizerItemAsync::itemFetchById()
723{
724 QFETCH(QString, uri);
725 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
726
727 // XXX TODO: fetchbyid request for items as well as items!!!
728
729 QOrganizerItemFetchByIdRequest ifr;
730 QVERIFY(ifr.type() == QOrganizerAbstractRequest::ItemFetchByIdRequest);
731
732 // initial state - not started, no manager.
733 QVERIFY(!ifr.isActive());
734 QVERIFY(!ifr.isFinished());
735 QVERIFY(!ifr.start());
736 QVERIFY(!ifr.cancel());
737 QVERIFY(!ifr.waitForFinished());
738
739 // get all item ids
740 QList<QOrganizerItemId> itemIds(oim->itemIds());
741
742 // "all items" retrieval
743 ifr.setManager(oim.data());
744 ifr.setIds(itemIds);
745 QCOMPARE(ifr.manager(), oim.data());
746 QVERIFY(!ifr.isActive());
747 QVERIFY(!ifr.isFinished());
748 QVERIFY(!ifr.cancel());
749 QVERIFY(!ifr.waitForFinished());
750 qRegisterMetaType<QOrganizerItemFetchByIdRequest*>(typeName: "QOrganizerItemFetchByIdRequest*");
751 QThreadSignalSpy spy(&ifr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
752 QVERIFY(!ifr.cancel()); // not started
753
754 QVERIFY(ifr.start());
755 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
756 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
757 QVERIFY(ifr.waitForFinished());
758 QVERIFY(ifr.isFinished());
759
760 QVERIFY(spy.count() >= 1); // active + finished progress signals
761 spy.clear();
762
763 QList<QOrganizerItem> items = ifr.items();
764 QCOMPARE(itemIds.size(), items.size());
765 for (int i = 0; i < itemIds.size(); i++) {
766 QOrganizerItem curr = oim->item(itemId: itemIds.at(i));
767 QVERIFY(items.at(i) == curr);
768 }
769 // save empty list
770 QList<QOrganizerItemId> itemIdList;
771 QOrganizerItemFetchByIdRequest ifr1;
772 ifr1.setManager(oim.data());
773 ifr1.setIds(itemIdList);
774 ifr1.start();
775 ifr1.waitForFinished();
776 QVERIFY(ifr1.isFinished());
777 QVERIFY(ifr1.error() == QOrganizerManager::NoError);
778
779 // XXX TODO: fetchbyid request for items as well as items!!!
780}
781
782
783void tst_QOrganizerItemAsync::itemIdFetch()
784{
785 QFETCH(QString, uri);
786 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
787 QOrganizerItemIdFetchRequest ifr;
788 QVERIFY(ifr.type() == QOrganizerAbstractRequest::ItemIdFetchRequest);
789
790 // initial state - not started, no manager.
791 QVERIFY(!ifr.isActive());
792 QVERIFY(!ifr.isFinished());
793 QVERIFY(!ifr.start());
794 QVERIFY(!ifr.cancel());
795 QVERIFY(!ifr.waitForFinished());
796
797 // "all items" retrieval
798 QOrganizerItemFilter fil;
799 ifr.setManager(oim.data());
800 QCOMPARE(ifr.manager(), oim.data());
801 QVERIFY(!ifr.isActive());
802 QVERIFY(!ifr.isFinished());
803 QVERIFY(!ifr.cancel());
804 QVERIFY(!ifr.waitForFinished());
805 qRegisterMetaType<QOrganizerItemIdFetchRequest*>(typeName: "QOrganizerItemIdFetchRequest*");
806
807 QThreadSignalSpy spy(&ifr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
808 ifr.setFilter(fil);
809 QCOMPARE(ifr.filter(), fil);
810 QVERIFY(!ifr.cancel()); // not started
811 QVERIFY(ifr.start());
812
813 QVERIFY((ifr.isActive() &&ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
814 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
815 QVERIFY(ifr.waitForFinished());
816 QVERIFY(ifr.isFinished());
817
818 QVERIFY(spy.count() >= 1); // active + finished progress signals
819 spy.clear();
820
821 QList<QOrganizerItemId> itemIds = oim->itemIds();
822 QList<QOrganizerItemId> result = ifr.itemIds();
823 QCOMPARE(itemIds, result);
824
825 // asynchronous detail field filtering
826 QOrganizerItemDetailFieldFilter dfil;
827 dfil.setDetail(detailType: QOrganizerItemDetail::TypeLocation, field: QOrganizerItemLocation::FieldLabel);
828 ifr.setFilter(dfil);
829 QVERIFY(ifr.filter() == dfil);
830 QVERIFY(!ifr.cancel()); // not started
831
832 QVERIFY(ifr.start());
833 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
834 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
835 QVERIFY(ifr.waitForFinished());
836 QVERIFY(ifr.isFinished());
837
838 QVERIFY(spy.count() >= 1); // active + finished progress signals
839 spy.clear();
840
841 itemIds = oim->itemIds(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: dfil);
842 result = ifr.itemIds();
843 QVERIFY(!itemIds.isEmpty());
844 QCOMPARE(itemIds, result);
845
846 // sort order
847 QOrganizerItemSortOrder sortOrder;
848 sortOrder.setDetail(detailType: QOrganizerItemDetail::TypePriority, field: QOrganizerItemPriority::FieldPriority);
849 QList<QOrganizerItemSortOrder> sorting;
850 sorting.append(t: sortOrder);
851 ifr.setFilter(fil);
852 ifr.setSorting(sorting);
853 QCOMPARE(ifr.sorting(), sorting);
854 QVERIFY(!ifr.cancel()); // not started
855 QVERIFY(ifr.start());
856 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
857 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
858 QVERIFY(ifr.waitForFinished());
859 QVERIFY(ifr.isFinished());
860
861 QVERIFY(spy.count() >= 1); // active + finished progress signals
862 spy.clear();
863
864 itemIds = oim->itemIds(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: QOrganizerItemFilter(), sortOrders: sorting);
865 result = ifr.itemIds();
866 QCOMPARE(itemIds, result);
867
868 // cancelling
869 sorting.clear();
870 ifr.setFilter(fil);
871 ifr.setSorting(sorting);
872
873 int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
874 while (true) {
875 QVERIFY(!ifr.cancel()); // not started
876 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
877 QVERIFY(ifr.start());
878 if (!ifr.cancel()) {
879 // due to thread scheduling, async cancel might be attempted
880 // after the request has already finished.. so loop and try again.
881 ifr.waitForFinished();
882 sorting.clear();
883 ifr.setFilter(fil);
884 ifr.setSorting(sorting);
885 bailoutCount -= 1;
886 spy.clear();
887 if (!bailoutCount) {
888// qWarning("Unable to test cancelling due to thread scheduling!");
889 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
890 break;
891 }
892 continue;
893 }
894
895 // if we get here, then we are cancelling the request.
896 QVERIFY(ifr.waitForFinished());
897 QVERIFY(ifr.isCanceled());
898
899 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
900 spy.clear();
901
902 break;
903 }
904
905 // restart, and wait for progress after cancel.
906 while (true) {
907 QVERIFY(!ifr.cancel()); // not started
908 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
909 QVERIFY(ifr.start());
910 if (!ifr.cancel()) {
911 // due to thread scheduling, async cancel might be attempted
912 // after the request has already finished.. so loop and try again.
913 ifr.waitForFinished();
914 sorting.clear();
915 ifr.setFilter(fil);
916 ifr.setSorting(sorting);
917 bailoutCount -= 1;
918 if (!bailoutCount) {
919// qWarning("Unable to test cancelling due to thread scheduling!");
920 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
921 break;
922 }
923 continue;
924 }
925 ifr.waitForFinished();
926 QVERIFY(ifr.isCanceled());
927
928 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
929 spy.clear();
930 break;
931 }
932}
933
934void tst_QOrganizerItemAsync::itemOccurrenceFetch()
935{
936 QFETCH(QString, uri);
937 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
938
939 QOrganizerItemOccurrenceFetchRequest ifr;
940 QVERIFY(ifr.type() == QOrganizerAbstractRequest::ItemOccurrenceFetchRequest);
941
942 // retrieve a parent event from the backend.
943 QOrganizerItem parent;
944 bool foundParent = false;
945 QList<QOrganizerItem> allItems = oim->itemsForExport();
946 for (int i = 0; i < allItems.size(); ++i) {
947 QOrganizerItem curr = allItems.at(i);
948 if (curr.type() == QOrganizerItemType::TypeEvent) {
949 QOrganizerEvent evt = curr;
950 if (evt.recurrenceDates().size() > 0) {
951 parent = evt;
952 foundParent = true;
953 }
954 }
955 }
956 if (!foundParent) {
957 QSKIP("Manager has no valid recurring events; skipping.");
958 }
959 // initial state - not started, no manager.
960 QVERIFY(!ifr.isActive());
961 QVERIFY(!ifr.isFinished());
962 QVERIFY(!ifr.start());
963 QVERIFY(!ifr.cancel());
964 QVERIFY(!ifr.waitForFinished());
965
966 // "all items" retrieval
967 ifr.setManager(oim.data());
968 QCOMPARE(ifr.manager(), oim.data());
969 QVERIFY(!ifr.isActive());
970 QVERIFY(!ifr.isFinished());
971 QVERIFY(!ifr.cancel());
972 QVERIFY(!ifr.waitForFinished());
973 qRegisterMetaType<QOrganizerItemFetchRequest*>(typeName: "QOrganizerItemFetchRequest*");
974 QThreadSignalSpy spy(&ifr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
975 ifr.setParentItem(parent);
976 QCOMPARE(ifr.parentItem(), parent);
977 QVERIFY(!ifr.cancel()); // not started
978
979 QVERIFY(ifr.start());
980 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
981 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
982 QVERIFY(ifr.waitForFinished());
983 QVERIFY(ifr.isFinished());
984
985 QVERIFY(spy.count() >= 1); // active + finished progress signals
986 spy.clear();
987
988 QList<QOrganizerItem> itemOccs = oim->itemOccurrences(parentItem: parent, startDateTime: QDateTime(), endDateTime: QDateTime(), maxCount: -1);
989 QList<QOrganizerItem> items = ifr.itemOccurrences();
990 QCOMPARE(items.size(), itemOccs.size());
991 for (int i = 0; i < items.size(); ++i) {
992 QVERIFY(containsIgnoringDetailKeys(itemOccs, items.at(i)));
993 }
994
995
996 // do it again, make sure it doesn't mutate the result set.
997 ifr.setParentItem(parent);
998 QVERIFY(ifr.parentItem() == parent);
999 QVERIFY(!ifr.cancel()); // not started
1000
1001 QVERIFY(ifr.start());
1002 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
1003 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
1004 QVERIFY(ifr.waitForFinished());
1005 QVERIFY(ifr.isFinished());
1006 QVERIFY(spy.count() >= 1); // active + finished progress signals
1007 spy.clear();
1008
1009 itemOccs = oim->itemOccurrences(parentItem: parent, startDateTime: QDateTime(), endDateTime: QDateTime(), maxCount: -1);
1010 items = ifr.itemOccurrences();
1011 QCOMPARE(items.size(), itemOccs.size());
1012 for (int i = 0; i < items.size(); ++i) {
1013 QVERIFY(containsIgnoringDetailKeys(itemOccs, items.at(i)));
1014 }
1015
1016// // restrictions
1017// ifr.setParentItem(parent);
1018// QOrganizerItemFetchHint fetchHint;
1019// fetchHint.setDetailTypesHint(QList<QOrganizerItemDetail::DetailType>() << QOrganizerItemDetail::TypeDescription);
1020// ifr.setFetchHint(fetchHint);
1021// QCOMPARE(ifr.fetchHint().detailTypesHint(), QList<QOrganizerItemDetail::DetailType>() << QOrganizerItemDetail::TypeDescription);
1022// QVERIFY(!ifr.cancel()); // not started
1023// QVERIFY(ifr.start());
1024// QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
1025// //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
1026// QVERIFY(ifr.waitForFinished());
1027// QVERIFY(ifr.isFinished());
1028// QVERIFY(spy.count() >= 1); // active + finished progress signals
1029// spy.clear();
1030
1031// itemOccs = oim->itemOccurrences(parent, QDateTime(), QDateTime(), -1);
1032// items = ifr.itemOccurrences();
1033// QCOMPARE(itemOccs.size(), items.size());
1034// for (int i = 0; i < itemOccs.size(); i++) {
1035// // create a item from the restricted data only (id + display label)
1036// QOrganizerItem currFull = itemOccs.at(i);
1037// QOrganizerItem currRestricted; // in prepare model, the items are all events.
1038// if (currFull.type() == QOrganizerItemType::TypeEvent) {
1039// currRestricted = QOrganizerEvent(); // therefore, the returned items will either be events
1040// } else if (currFull.type() == QOrganizerItemType::TypeEventOccurrence) {
1041// currRestricted = QOrganizerEventOccurrence(); // or event occurrences.
1042// }
1043// currRestricted.setId(currFull.id());
1044// QList<QOrganizerItemDescription> descriptions = currFull.details<QOrganizerItemDescription>();
1045// foreach (const QOrganizerItemDescription& description, descriptions) {
1046// QOrganizerItemDescription descr = description;
1047// if (!descr.isEmpty()) {
1048// currRestricted.saveDetail(&descr);
1049// }
1050// }
1051
1052// // now find the item in the retrieved list which our restricted item mimics
1053// QOrganizerItem retrievedRestricted;
1054// bool found = false;
1055// foreach (const QOrganizerItem& retrieved, items) {
1056// if (retrieved.id() == currRestricted.id()) {
1057// retrievedRestricted = retrieved;
1058// found = true;
1059// }
1060// }
1061
1062// QVERIFY(found); // must exist or fail.
1063// // ensure that the item is the same (except synth fields)
1064// QList<QOrganizerItemDetail> retrievedDetails = retrievedRestricted.details();
1065// QList<QOrganizerItemDetail> expectedDetails = currRestricted.details();
1066// foreach (const QOrganizerItemDetail& det, expectedDetails) {
1067// // ignore backend synthesised details
1068// // again, this requires a "default item details" function to work properly.
1069// if (det.type() == QOrganizerItemDetail::TypeTimestamp) {
1070// continue;
1071// }
1072// // everything else in the expected item should be in the retrieved one.
1073// QVERIFY(detailListContainsDetailIgnoringDetailKeys(retrievedDetails, det));
1074// }
1075// }
1076
1077// // cancelling
1078// ifr.setParentItem(parent);
1079// ifr.setFetchHint(QOrganizerItemFetchHint());
1080
1081// int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
1082// while (true) {
1083// QVERIFY(!ifr.cancel()); // not started
1084// FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1085// QVERIFY(ifr.start());
1086// if (!ifr.cancel()) {
1087// // due to thread scheduling, async cancel might be attempted
1088// // after the request has already finished.. so loop and try again.
1089// spy.clear();
1090// ifr.waitForFinished();
1091// ifr.setParentItem(parent);
1092// ifr.setFetchHint(QOrganizerItemFetchHint());
1093// bailoutCount -= 1;
1094// if (!bailoutCount) {
1095//// qWarning("Unable to test cancelling due to thread scheduling!");
1096// bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1097// break;
1098// }
1099// continue;
1100// }
1101
1102// // if we get here, then we are cancelling the request.
1103// QVERIFY(ifr.waitForFinished());
1104// QVERIFY(ifr.isCanceled());
1105
1106// QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1107// spy.clear();
1108// break;
1109// }
1110
1111// // restart, and wait for progress after cancel.
1112// while (true) {
1113// QVERIFY(!ifr.cancel()); // not started
1114// FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1115// QVERIFY(ifr.start());
1116// if (!ifr.cancel()) {
1117// // due to thread scheduling, async cancel might be attempted
1118// // after the request has already finished.. so loop and try again.
1119// ifr.waitForFinished();
1120// ifr.setParentItem(parent);
1121// ifr.setFetchHint(QOrganizerItemFetchHint());
1122// bailoutCount -= 1;
1123// spy.clear();
1124// if (!bailoutCount) {
1125// //qWarning("Unable to test cancelling due to thread scheduling!");
1126// bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1127// break;
1128// }
1129// continue;
1130// }
1131// ifr.waitForFinished();
1132// QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1133// spy.clear();
1134// QVERIFY(!ifr.isActive());
1135// QVERIFY(ifr.state() == QOrganizerAbstractRequest::CanceledState);
1136// break;
1137// }
1138}
1139
1140void tst_QOrganizerItemAsync::itemFetchForExport()
1141{
1142 QFETCH(QString, uri);
1143 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
1144
1145 QOrganizerItemFetchForExportRequest ifr;
1146 QVERIFY(ifr.type() == QOrganizerAbstractRequest::ItemFetchForExportRequest);
1147
1148 // initial state - not started, no manager.
1149 QVERIFY(!ifr.isActive());
1150 QVERIFY(!ifr.isFinished());
1151 QVERIFY(!ifr.start());
1152 QVERIFY(!ifr.cancel());
1153 QVERIFY(!ifr.waitForFinished());
1154
1155 // "all items" retrieval
1156 QOrganizerItemFilter fil;
1157 ifr.setManager(oim.data());
1158 QCOMPARE(ifr.manager(), oim.data());
1159 QVERIFY(!ifr.isActive());
1160 QVERIFY(!ifr.isFinished());
1161 QVERIFY(!ifr.cancel());
1162 QVERIFY(!ifr.waitForFinished());
1163 qRegisterMetaType<QOrganizerItemFetchRequest*>(typeName: "QOrganizerItemFetchRequest*");
1164 QThreadSignalSpy spy(&ifr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
1165 ifr.setFilter(fil);
1166 QCOMPARE(ifr.filter(), fil);
1167 QVERIFY(!ifr.cancel()); // not started
1168
1169 QVERIFY(ifr.start());
1170 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
1171 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
1172 QVERIFY(ifr.waitForFinished());
1173 QVERIFY(ifr.isFinished());
1174
1175 QVERIFY(spy.count() >= 1); // active + finished progress signals
1176 spy.clear();
1177
1178 QList<QOrganizerItem> itemsfe = oim->itemsForExport(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: fil);
1179 QList<QOrganizerItem> items = ifr.items();
1180 QCOMPARE(itemsfe.size(), items.size());
1181 for (int i = 0; i < itemsfe.size(); i++) {
1182 QOrganizerItem curr = itemsfe.at(i);
1183 QVERIFY(items.contains(curr));
1184 }
1185
1186 // asynchronous detail field filtering
1187 QOrganizerItemDetailFieldFilter dfil;
1188 dfil.setDetail(detailType: QOrganizerItemDetail::TypeLocation, field: QOrganizerItemLocation::FieldLabel);
1189 ifr.setFilter(dfil);
1190 QVERIFY(ifr.filter() == dfil);
1191 QVERIFY(!ifr.cancel()); // not started
1192
1193 QVERIFY(ifr.start());
1194 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
1195 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
1196 QVERIFY(ifr.waitForFinished());
1197 QVERIFY(ifr.isFinished());
1198 QVERIFY(spy.count() >= 1); // active + finished progress signals
1199 spy.clear();
1200
1201 itemsfe = oim->itemsForExport(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: dfil);
1202 items = ifr.items();
1203 QCOMPARE(itemsfe.size(), items.size());
1204 for (int i = 0; i < itemsfe.size(); i++) {
1205 QOrganizerItem curr = itemsfe.at(i);
1206 QVERIFY(items.contains(curr));
1207 }
1208
1209 // sort order
1210 QOrganizerItemSortOrder sortOrder;
1211 sortOrder.setDetail(detailType: QOrganizerItemDetail::TypePriority, field: QOrganizerItemPriority::FieldPriority);
1212 QList<QOrganizerItemSortOrder> sorting;
1213 sorting.append(t: sortOrder);
1214 ifr.setFilter(fil);
1215 ifr.setSorting(sorting);
1216 ifr.setStartDate(QDateTime());
1217 ifr.setEndDate(QDateTime());
1218 QCOMPARE(ifr.sorting(), sorting);
1219 QVERIFY(!ifr.cancel()); // not started
1220 QVERIFY(ifr.start());
1221 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
1222 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
1223 QVERIFY(ifr.waitForFinished());
1224 QVERIFY(ifr.isFinished());
1225
1226 QVERIFY(spy.count() >= 1); // active + finished progress signals
1227 spy.clear();
1228
1229 itemsfe = oim->itemsForExport(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: fil, sortOrders: sorting);
1230 items = ifr.items();
1231 QCOMPARE(itemsfe.size(), items.size());
1232 for (int i = 0; i < itemsfe.size(); i++) {
1233 QOrganizerItem curr = itemsfe.at(i);
1234 QVERIFY(items.contains(curr));
1235 }
1236
1237 // restrictions
1238 sorting.clear();
1239 ifr.setFilter(fil);
1240 ifr.setSorting(sorting);
1241 QOrganizerItemFetchHint fetchHint;
1242 fetchHint.setDetailTypesHint(QList<QOrganizerItemDetail::DetailType>() << QOrganizerItemDetail::TypeDescription);
1243 ifr.setFetchHint(fetchHint);
1244 QCOMPARE(ifr.fetchHint().detailTypesHint(), QList<QOrganizerItemDetail::DetailType>() << QOrganizerItemDetail::TypeDescription);
1245 QVERIFY(!ifr.cancel()); // not started
1246 QVERIFY(ifr.start());
1247 QVERIFY((ifr.isActive() && ifr.state() == QOrganizerAbstractRequest::ActiveState) || ifr.isFinished());
1248 //QVERIFY(ifr.isFinished() || !ifr.start()); // already started. // thread scheduling means this is untestable
1249 QVERIFY(ifr.waitForFinished());
1250 QVERIFY(ifr.isFinished());
1251
1252 QVERIFY(spy.count() >= 1); // active + finished progress signals
1253 spy.clear();
1254
1255 itemsfe = oim->itemsForExport(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: QOrganizerItemFilter(), sortOrders: sorting);
1256 items = ifr.items();
1257 QCOMPARE(itemsfe.size(), items.size());
1258 for (int i = 0; i < itemsfe.size(); i++) {
1259 // create a item from the restricted data only (id + display label)
1260 QOrganizerItem currFull = itemsfe.at(i);
1261 QOrganizerEvent currRestricted; // in prepare model, the item types were "Event"
1262 currRestricted.setId(currFull.id());
1263 QList<QOrganizerItemDetail> descriptions = currFull.details(detailType: QOrganizerItemDetail::TypeDescription);
1264 foreach (const QOrganizerItemDescription& description, descriptions) {
1265 QOrganizerItemDescription descr = description;
1266 if (!descr.isEmpty())
1267 currRestricted.saveDetail(detail: &descr);
1268 }
1269
1270 // now find the item in the retrieved list which our restricted item mimics
1271 QOrganizerItem retrievedRestricted;
1272 bool found = false;
1273 foreach (const QOrganizerItem& retrieved, items) {
1274 if (retrieved.id() == currRestricted.id()) {
1275 retrievedRestricted = retrieved;
1276 found = true;
1277 }
1278 }
1279
1280 QVERIFY(found); // must exist or fail.
1281
1282 // ensure that the item is the same (except synth fields)
1283 QList<QOrganizerItemDetail> retrievedDetails = retrievedRestricted.details();
1284 QList<QOrganizerItemDetail> expectedDetails = currRestricted.details();
1285 foreach (const QOrganizerItemDetail& det, expectedDetails) {
1286 // ignore backend synthesised details
1287 // again, this requires a "default item details" function to work properly.
1288 if (det.type() == QOrganizerItemDetail::TypeTimestamp)
1289 continue;
1290
1291 // everything else in the expected item should be in the retrieved one.
1292 QVERIFY(retrievedDetails.contains(det));
1293 }
1294 }
1295
1296 // cancelling
1297 sorting.clear();
1298 ifr.setFilter(fil);
1299 ifr.setSorting(sorting);
1300 ifr.setFetchHint(QOrganizerItemFetchHint());
1301
1302 int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
1303 while (true) {
1304 QVERIFY(!ifr.cancel()); // not started
1305 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1306 QVERIFY(ifr.start());
1307 if (!ifr.cancel()) {
1308 // due to thread scheduling, async cancel might be attempted
1309 // after the request has already finished.. so loop and try again.
1310 spy.clear();
1311 ifr.waitForFinished();
1312 sorting.clear();
1313 ifr.setFilter(fil);
1314 ifr.setSorting(sorting);
1315 ifr.setFetchHint(QOrganizerItemFetchHint());
1316 ifr.setFetchHint(QOrganizerItemFetchHint());
1317 bailoutCount -= 1;
1318 if (!bailoutCount) {
1319// qWarning("Unable to test cancelling due to thread scheduling!");
1320 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1321 break;
1322 }
1323 continue;
1324 }
1325
1326 // if we get here, then we are cancelling the request.
1327 QVERIFY(ifr.waitForFinished());
1328 QVERIFY(ifr.isCanceled());
1329
1330 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1331 spy.clear();
1332 break;
1333 }
1334
1335 // restart, and wait for progress after cancel.
1336 while (true) {
1337 QVERIFY(!ifr.cancel()); // not started
1338 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1339 QVERIFY(ifr.start());
1340 if (!ifr.cancel()) {
1341 // due to thread scheduling, async cancel might be attempted
1342 // after the request has already finished.. so loop and try again.
1343 ifr.waitForFinished();
1344 sorting.clear();
1345 ifr.setFilter(fil);
1346 ifr.setSorting(sorting);
1347 ifr.setFetchHint(QOrganizerItemFetchHint());
1348 bailoutCount -= 1;
1349 spy.clear();
1350 if (!bailoutCount) {
1351 //qWarning("Unable to test cancelling due to thread scheduling!");
1352 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1353 break;
1354 }
1355 continue;
1356 }
1357 ifr.waitForFinished();
1358 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1359 spy.clear();
1360 QVERIFY(!ifr.isActive());
1361 QVERIFY(ifr.state() == QOrganizerAbstractRequest::CanceledState);
1362 break;
1363 }
1364}
1365
1366void tst_QOrganizerItemAsync::itemRemove()
1367{
1368 QFETCH(QString, uri);
1369 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
1370 qRegisterMetaType<QList<QOrganizerItemId> >(typeName: "QList<QOrganizerItemId>");
1371
1372 QOrganizerItemRemoveRequest irr;
1373 QVERIFY(irr.type() == QOrganizerAbstractRequest::ItemRemoveRequest);
1374
1375 // initial state - not started, no manager.
1376 QVERIFY(!irr.isActive());
1377 QVERIFY(!irr.isFinished());
1378 QVERIFY(!irr.start());
1379 QVERIFY(!irr.cancel());
1380 QVERIFY(!irr.waitForFinished());
1381
1382 // fill manager with test data
1383 QOrganizerTodo testTodo1;
1384 QOrganizerItemDisplayLabel label;
1385 label.setLabel("Test todo 1");
1386 testTodo1.saveDetail(detail: &label);
1387 QVERIFY(oim->saveItem(&testTodo1));
1388
1389 testTodo1.setId(QOrganizerItemId());
1390 label.setLabel("Test todo 2");
1391 testTodo1.saveDetail(detail: &label);
1392 QOrganizerItemComment comment;
1393 comment.setComment("todo comment");
1394 testTodo1.saveDetail(detail: &comment);
1395 QVERIFY(oim->saveItem(&testTodo1));
1396
1397 QList<QOrganizerItem> allItems(oim->items());
1398 QVERIFY(!allItems.isEmpty());
1399 QOrganizerItem removableItem(allItems.first());
1400
1401 // specific item set
1402 irr.setItem(removableItem);
1403 QVERIFY(irr.items() == QList<QOrganizerItem>() << removableItem);
1404
1405 // remove empty list
1406 QList<QOrganizerItem> itemList;
1407 QOrganizerItemRemoveRequest irr1;
1408 irr1.setManager(oim.data());
1409 irr1.setItems(itemList);
1410 irr1.start();
1411 irr1.waitForFinished();
1412 QVERIFY(irr1.isFinished());
1413 QVERIFY(irr1.error() == QOrganizerManager::NoError);
1414
1415 // specific item removal via detail field filter
1416 int originalCount = oim->itemIds().size();
1417 QOrganizerItemDetailFieldFilter dfil;
1418 dfil.setDetail(detailType: QOrganizerItemDetail::TypeComment, field: QOrganizerItemComment::FieldComment);
1419 irr.setItems(oim->items(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: dfil));
1420 irr.setManager(oim.data());
1421 QCOMPARE(irr.manager(), oim.data());
1422 QVERIFY(!irr.isActive());
1423 QVERIFY(!irr.isFinished());
1424 QVERIFY(!irr.cancel());
1425 QVERIFY(!irr.waitForFinished());
1426 qRegisterMetaType<QOrganizerItemRemoveRequest*>(typeName: "QOrganizerItemRemoveRequest*");
1427 QThreadSignalSpy spy(&irr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
1428 QVERIFY(!irr.cancel()); // not started
1429
1430 QVERIFY(!oim->items(QDateTime(), QDateTime(), dfil).isEmpty());
1431
1432 QVERIFY(irr.start());
1433
1434 QVERIFY((irr.isActive() &&irr.state() == QOrganizerAbstractRequest::ActiveState) || irr.isFinished());
1435 //QVERIFY(irr.isFinished() || !irr.start()); // already started. // thread scheduling means this is untestable
1436 QVERIFY(irr.waitForFinished());
1437 QVERIFY(irr.isFinished());
1438
1439 QVERIFY(spy.count() >= 1); // active + finished progress signals
1440 spy.clear();
1441
1442 QCOMPARE(oim->itemIds().size(), originalCount - 1);
1443 QVERIFY(oim->itemIds(QDateTime(), QDateTime(), dfil).isEmpty());
1444
1445 // remove all items
1446
1447 irr.setManager(oim.data());
1448
1449 irr.setItems(oim->items());
1450
1451 QVERIFY(!irr.isActive());
1452 QVERIFY(irr.isFinished());
1453 QVERIFY(irr.waitForFinished());
1454 QVERIFY(!irr.cancel()); // not started
1455 QVERIFY(irr.start());
1456 // This removes test events and also initial events which include one recurring event
1457 // without start and end dates (with recurrence date list)
1458 QVERIFY((irr.isActive() && irr.state() == QOrganizerAbstractRequest::ActiveState) || irr.isFinished());
1459 //QVERIFY(irr.isFinished() || !irr.start()); // already started. // thread scheduling means this is untestable
1460 QVERIFY(irr.waitForFinished());
1461 QVERIFY(irr.isFinished());
1462
1463 QCOMPARE(oim->items().size(), 0); // no items should be left.
1464 QVERIFY(spy.count() >= 1); // active + finished progress signals
1465 spy.clear();
1466
1467// // cancelling
1468// QOrganizerTodo temp;
1469// QOrganizerItemDescription description;
1470// description.setDescription("Should not be removed");
1471// temp.saveDetail(&description);
1472// oim->saveItem(&temp);
1473// QCOMPARE(oim->itemIds().size(), 1);
1474// irr.setItemIds(oim->itemIds());
1475
1476// int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
1477// while (true) {
1478// QVERIFY(!irr.cancel()); // not started
1479// FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1480// QVERIFY(spy.count() == 0);
1481// QVERIFY(irr.start());
1482// if (!irr.cancel()) {
1483// // due to thread scheduling, async cancel might be attempted
1484// // after the request has already finished.. so loop and try again.
1485// irr.waitForFinished();
1486// temp.setId(QOrganizerItemId());
1487// if (!oim->saveItem(&temp)) {
1488// QSKIP("Unable to save temporary item for remove request cancellation test!");
1489// }
1490// irr.setItemIds(oim->itemIds());
1491// bailoutCount -= 1;
1492// if (!bailoutCount) {
1493//// QSKIP("Unable to test cancelling due to thread scheduling!");
1494// bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1495// break;
1496// }
1497// spy.clear();
1498// continue;
1499// }
1500
1501// // if we get here, then we are cancelling the request.
1502// QVERIFY(irr.waitForFinished());
1503// QVERIFY(irr.isCanceled());
1504// QCOMPARE(oim->itemIds().size(), 1);
1505// QCOMPARE(oim->itemIds(), irr.itemIds());
1506// QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1507// spy.clear();
1508// break;
1509// }
1510
1511// // restart, and wait for progress after cancel.
1512// while (true) {
1513// QVERIFY(!irr.cancel()); // not started
1514// FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1515// QVERIFY(irr.start());
1516// if (!irr.cancel()) {
1517// // due to thread scheduling, async cancel might be attempted
1518// // after the request has already finished.. so loop and try again.
1519// irr.waitForFinished();
1520// temp.setId(QOrganizerItemId());
1521// oim->saveItem(&temp);
1522// irr.setItemIds(oim->itemIds());
1523// bailoutCount -= 1;
1524// if (!bailoutCount) {
1525//// qWarning("Unable to test cancelling due to thread scheduling!");
1526// bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1527// break;
1528// }
1529// spy.clear();
1530// continue;
1531// }
1532// irr.waitForFinished();
1533// QVERIFY(irr.isCanceled());
1534// QCOMPARE(oim->itemIds().size(), 1);
1535// QCOMPARE(oim->itemIds(), irr.itemIds());
1536// QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1537// spy.clear();
1538// break;
1539// }
1540}
1541
1542void tst_QOrganizerItemAsync::itemRemoveById()
1543{
1544 QFETCH(QString, uri);
1545 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
1546
1547 qRegisterMetaType<QList<QOrganizerItemId> >(typeName: "QList<QOrganizerItemId>");
1548
1549 QOrganizerItemRemoveByIdRequest irr;
1550 QVERIFY(irr.type() == QOrganizerAbstractRequest::ItemRemoveByIdRequest);
1551
1552 // initial state - not started, no manager.
1553 QVERIFY(!irr.isActive());
1554 QVERIFY(!irr.isFinished());
1555 QVERIFY(!irr.start());
1556 QVERIFY(!irr.cancel());
1557 QVERIFY(!irr.waitForFinished());
1558
1559 // fill manager with test data
1560 QOrganizerTodo testTodo1;
1561 QOrganizerItemDisplayLabel label;
1562 label.setLabel("Test todo 1");
1563 testTodo1.saveDetail(detail: &label);
1564 QVERIFY(oim->saveItem(&testTodo1));
1565
1566 testTodo1.setId(QOrganizerItemId());
1567 label.setLabel("Test todo 2");
1568 testTodo1.saveDetail(detail: &label);
1569 QOrganizerItemComment comment;
1570 comment.setComment("todo comment");
1571 testTodo1.saveDetail(detail: &comment);
1572 QVERIFY(oim->saveItem(&testTodo1));
1573
1574 QList<QOrganizerItemId> allIds(oim->itemIds());
1575 QVERIFY(!allIds.isEmpty());
1576 QOrganizerItemId removableId(allIds.first());
1577
1578 // specific item set
1579 irr.setItemId(removableId);
1580 QVERIFY(irr.itemIds() == QList<QOrganizerItemId>() << removableId);
1581
1582 // remove empty list
1583 QList<QOrganizerItemId> itemIdList;
1584 QOrganizerItemRemoveByIdRequest irr1;
1585 irr1.setManager(oim.data());
1586 irr1.setItemIds(itemIdList);
1587 irr1.start();
1588 irr1.waitForFinished();
1589 QVERIFY(irr1.isFinished());
1590 QVERIFY(irr1.error() == QOrganizerManager::NoError);
1591
1592 // specific item removal via detail field filter
1593 int originalCount = oim->itemIds().size();
1594 QOrganizerItemDetailFieldFilter dfil;
1595 dfil.setDetail(detailType: QOrganizerItemDetail::TypeComment, field: QOrganizerItemComment::FieldComment);
1596 irr.setItemIds(oim->itemIds(startDateTime: QDateTime(), endDateTime: QDateTime(), filter: dfil));
1597 irr.setManager(oim.data());
1598 QCOMPARE(irr.manager(), oim.data());
1599 QVERIFY(!irr.isActive());
1600 QVERIFY(!irr.isFinished());
1601 QVERIFY(!irr.cancel());
1602 QVERIFY(!irr.waitForFinished());
1603 qRegisterMetaType<QOrganizerItemRemoveByIdRequest*>(typeName: "QOrganizerItemRemoveByIdRequest*");
1604 QThreadSignalSpy spy(&irr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
1605 QVERIFY(!irr.cancel()); // not started
1606
1607 QVERIFY(!oim->itemIds(QDateTime(), QDateTime(), dfil).isEmpty());
1608
1609 QVERIFY(irr.start());
1610
1611 QVERIFY((irr.isActive() &&irr.state() == QOrganizerAbstractRequest::ActiveState) || irr.isFinished());
1612 //QVERIFY(irr.isFinished() || !irr.start()); // already started. // thread scheduling means this is untestable
1613 QVERIFY(irr.waitForFinished());
1614 QVERIFY(irr.isFinished());
1615
1616 QVERIFY(spy.count() >= 1); // active + finished progress signals
1617 spy.clear();
1618
1619 QCOMPARE(oim->itemIds().size(), originalCount - 1);
1620 QVERIFY(oim->itemIds(QDateTime(), QDateTime(), dfil).isEmpty());
1621
1622 // remove all items
1623//// dfil.setDetail(QOrganizerItemDetail::TypeDisplayLabel); // delete everything.
1624 irr.setManager(oim.data());
1625
1626 irr.setItemIds(oim->itemIds());
1627
1628 QVERIFY(!irr.isActive());
1629 QVERIFY(irr.isFinished());
1630 QVERIFY(irr.waitForFinished());
1631 QVERIFY(!irr.cancel()); // not started
1632 QVERIFY(irr.start());
1633
1634 QVERIFY((irr.isActive() && irr.state() == QOrganizerAbstractRequest::ActiveState) || irr.isFinished());
1635 //QVERIFY(irr.isFinished() || !irr.start()); // already started. // thread scheduling means this is untestable
1636 QVERIFY(irr.waitForFinished());
1637 QVERIFY(irr.isFinished());
1638
1639 QCOMPARE(oim->itemIds().size(), 0); // no items should be left.
1640 QVERIFY(spy.count() >= 1); // active + finished progress signals
1641 spy.clear();
1642
1643// // cancelling
1644// QOrganizerTodo temp;
1645// QOrganizerItemDescription description;
1646// description.setDescription("Should not be removed");
1647// temp.saveDetail(&description);
1648// oim->saveItem(&temp);
1649// QCOMPARE(oim->itemIds().size(), 1);
1650// irr.setItemIds(oim->itemIds());
1651
1652// int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
1653// while (true) {
1654// QVERIFY(!irr.cancel()); // not started
1655// FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1656// QVERIFY(spy.count() == 0);
1657// QVERIFY(irr.start());
1658// if (!irr.cancel()) {
1659// // due to thread scheduling, async cancel might be attempted
1660// // after the request has already finished.. so loop and try again.
1661// irr.waitForFinished();
1662// temp.setId(QOrganizerItemId());
1663// if (!oim->saveItem(&temp)) {
1664// QSKIP("Unable to save temporary item for remove request cancellation test!");
1665// }
1666// irr.setItemIds(oim->itemIds());
1667// bailoutCount -= 1;
1668// if (!bailoutCount) {
1669//// QSKIP("Unable to test cancelling due to thread scheduling!");
1670// bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1671// break;
1672// }
1673// spy.clear();
1674// continue;
1675// }
1676
1677// // if we get here, then we are cancelling the request.
1678// QVERIFY(irr.waitForFinished());
1679// QVERIFY(irr.isCanceled());
1680// QCOMPARE(oim->itemIds().size(), 1);
1681// QCOMPARE(oim->itemIds(), irr.itemIds());
1682// QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1683// spy.clear();
1684// break;
1685// }
1686
1687// // restart, and wait for progress after cancel.
1688// while (true) {
1689// QVERIFY(!irr.cancel()); // not started
1690// FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1691// QVERIFY(irr.start());
1692// if (!irr.cancel()) {
1693// // due to thread scheduling, async cancel might be attempted
1694// // after the request has already finished.. so loop and try again.
1695// irr.waitForFinished();
1696// temp.setId(QOrganizerItemId());
1697// oim->saveItem(&temp);
1698// irr.setItemIds(oim->itemIds());
1699// bailoutCount -= 1;
1700// if (!bailoutCount) {
1701//// qWarning("Unable to test cancelling due to thread scheduling!");
1702// bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1703// break;
1704// }
1705// spy.clear();
1706// continue;
1707// }
1708// irr.waitForFinished();
1709// QVERIFY(irr.isCanceled());
1710// QCOMPARE(oim->itemIds().size(), 1);
1711// QCOMPARE(oim->itemIds(), irr.itemIds());
1712// QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1713// spy.clear();
1714// break;
1715// }
1716}
1717
1718void tst_QOrganizerItemAsync::itemSave()
1719{
1720 QFETCH(QString, uri);
1721 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
1722 QOrganizerItemSaveRequest isr;
1723 QVERIFY(isr.type() == QOrganizerAbstractRequest::ItemSaveRequest);
1724
1725 // initial state - not started, no manager.
1726 QVERIFY(!isr.isActive());
1727 QVERIFY(!isr.isFinished());
1728 QVERIFY(!isr.start());
1729 QVERIFY(!isr.cancel());
1730 QVERIFY(!isr.waitForFinished());
1731
1732 // save a new item
1733 int originalCount = oim->itemIds().size();
1734 QOrganizerTodo testTodo;
1735 QOrganizerItemDescription description;
1736 description.setDescription("Test todo");
1737 testTodo.saveDetail(detail: &description);
1738
1739 QList<QOrganizerItem> saveList;
1740 saveList << testTodo;
1741 isr.setManager(oim.data());
1742 QCOMPARE(isr.manager(), oim.data());
1743 QVERIFY(!isr.isActive());
1744 QVERIFY(!isr.isFinished());
1745 QVERIFY(!isr.cancel());
1746 QVERIFY(!isr.waitForFinished());
1747 qRegisterMetaType<QOrganizerItemSaveRequest*>(typeName: "QOrganizerItemSaveRequest*");
1748 QThreadSignalSpy spy(&isr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
1749 isr.setItem(testTodo);
1750 QCOMPARE(isr.items(), saveList);
1751 QVERIFY(!isr.cancel()); // not started
1752 QVERIFY(isr.start());
1753
1754 QVERIFY((isr.isActive() && isr.state() == QOrganizerAbstractRequest::ActiveState) || isr.isFinished());
1755 //QVERIFY(isr.isFinished() || !isr.start()); // already started. // thread scheduling means this is untestable
1756 QVERIFY(isr.waitForFinished());
1757 QVERIFY(isr.isFinished());
1758 QVERIFY(spy.count() >= 1); // active + finished progress signals
1759 spy.clear();
1760
1761 QList<QOrganizerItem> expected = isr.items();
1762 QCOMPARE(expected.size(), 1);
1763 QList<QOrganizerItem> result;
1764 result << oim->item(itemId: expected.first().id());
1765 //some backends add extra fields, so this doesn't work:
1766 //QCOMPARE(result, expected);
1767 // XXX: really, we should use isSuperset() from tst_QOrganizerManager, but this will do for now:
1768 QVERIFY(result.first().detail(QOrganizerItemDetail::TypeDescription) == description);
1769 QCOMPARE(oim->itemIds().size(), originalCount + 1);
1770
1771 // update a previously saved item
1772 QOrganizerItemPriority priority = result.first().detail(detailType: QOrganizerItemDetail::TypePriority);
1773 priority.setPriority(QOrganizerItemPriority::LowestPriority);
1774 testTodo = result.first();
1775 testTodo.saveDetail(detail: &priority);
1776 saveList.clear();
1777 saveList << testTodo;
1778 isr.setItems(saveList);
1779 QCOMPARE(isr.items(), saveList);
1780 QVERIFY(!isr.cancel()); // not started
1781 QVERIFY(isr.start());
1782
1783 QVERIFY((isr.isActive() && isr.state() == QOrganizerAbstractRequest::ActiveState) || isr.isFinished());
1784 //QVERIFY(isr.isFinished() || !isr.start()); // already started. // thread scheduling means this is untestable
1785 QVERIFY(isr.waitForFinished());
1786 QVERIFY(isr.error() == QOrganizerManager::NoError); // if this fails, it means that the backend doesn't support Priority...
1787 QVERIFY(isr.isFinished());
1788 QVERIFY(spy.count() >= 1); // active + finished progress signals
1789 spy.clear();
1790
1791 expected = isr.items();
1792 result.clear();
1793 result << oim->item(itemId: expected.first().id());
1794
1795 QVERIFY(compareItemLists(result, expected));
1796
1797 // save empty list
1798 QList<QOrganizerItem> itemList;
1799 QOrganizerItemSaveRequest isr1;
1800 isr1.setManager(oim.data());
1801 isr1.setItems(itemList);
1802 isr1.start();
1803 isr1.waitForFinished();
1804 QVERIFY(isr1.isFinished());
1805 QVERIFY(isr1.error() == QOrganizerManager::NoError);
1806
1807 //here we can't compare the whole item details, testTodo would be updated by async call because we just use QThreadSignalSpy to receive signals.
1808 //QVERIFY(containsIgnoringTimestamps(result, testTodo));
1809 // XXX: really, we should use isSuperset() from tst_QOrganizerManager, but this will do for now:
1810 QVERIFY(result.first().detail(QOrganizerItemDetail::TypePriority).value(QOrganizerItemPriority::FieldPriority) == priority.priority());
1811 QCOMPARE(oim->itemIds().size(), originalCount + 1);
1812 // cancelling
1813 QOrganizerItem temp = testTodo;
1814 temp.setDisplayLabel("should not get saved");
1815 saveList.clear();
1816 saveList << temp;
1817 isr.setItems(saveList);
1818
1819 int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
1820 while (true) {
1821 QVERIFY(!isr.cancel()); // not started
1822 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1823 QVERIFY(isr.start());
1824 if (!isr.cancel()) {
1825 // due to thread scheduling, async cancel might be attempted
1826 // after the request has already finished.. so loop and try again.
1827 isr.waitForFinished();
1828 saveList = isr.items();
1829 if (oim->itemIds().size() > (originalCount + 1) && !oim->removeItem(itemId: saveList.at(i: 0).id())) {
1830 QSKIP("Unable to remove saved item to test cancellation of item save request");
1831 }
1832 saveList.clear();
1833 saveList << temp;
1834 isr.setItems(saveList);
1835 bailoutCount -= 1;
1836 if (!bailoutCount) {
1837// qWarning("Unable to test cancelling due to thread scheduling!");
1838 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1839 break;
1840 }
1841 spy.clear();
1842 continue;
1843 }
1844
1845 // if we get here, then we are cancelling the request.
1846 QVERIFY(isr.waitForFinished());
1847 QVERIFY(isr.isCanceled());
1848 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1849 spy.clear();
1850
1851 // verify that the changes were not saved
1852 expected.clear();
1853 QList<QOrganizerItemId> allItems = oim->itemIds();
1854 for (int i = 0; i < allItems.size(); i++) {
1855 expected.append(t: oim->item(itemId: allItems.at(i)));
1856 }
1857 QVERIFY(!expected.contains(temp));
1858 QCOMPARE(oim->itemIds().size(), originalCount + 1);
1859 break;
1860 }
1861 // restart, and wait for progress after cancel.
1862
1863 while (true) {
1864 QVERIFY(!isr.cancel()); // not started
1865 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
1866 QVERIFY(isr.start());
1867 if (!isr.cancel()) {
1868 // due to thread scheduling, async cancel might be attempted
1869 // after the request has already finished.. so loop and try again.
1870 isr.waitForFinished();
1871 saveList = isr.items();
1872 if (oim->itemIds().size() > (originalCount + 1) && !oim->removeItem(itemId: saveList.at(i: 0).id())) {
1873 QSKIP("Unable to remove saved item to test cancellation of item save request");
1874 }
1875 saveList.clear();
1876 saveList << temp;
1877 isr.setItems(saveList);
1878 bailoutCount -= 1;
1879 if (!bailoutCount) {
1880// qWarning("Unable to test cancelling due to thread scheduling!");
1881 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
1882 break;
1883 }
1884 spy.clear();
1885 continue;
1886 }
1887 isr.waitForFinished(); // now wait until finished (if it hasn't already).
1888 QVERIFY(isr.isCanceled());
1889 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
1890 spy.clear();
1891
1892 // verify that the changes were not saved
1893 expected.clear();
1894 QList<QOrganizerItemId> allItems = oim->itemIds();
1895 for (int i = 0; i < allItems.size(); i++) {
1896 expected.append(t: oim->item(itemId: allItems.at(i)));
1897 }
1898 QVERIFY(!expected.contains(temp));
1899 QCOMPARE(oim->itemIds().size(), originalCount + 1);
1900 break;
1901 }
1902}
1903
1904void tst_QOrganizerItemAsync::itemListSave()
1905{
1906 QFETCH(QString, uri);
1907 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
1908 QOrganizerItemSaveRequest isr;
1909 QVERIFY(isr.type() == QOrganizerAbstractRequest::ItemSaveRequest);
1910
1911 // item with invalid collection id cannot be saved
1912 QOrganizerCollection collection;
1913 oim->saveCollection(collection: &collection);
1914 QOrganizerCollectionId invalidCollectionId = collection.id();
1915 oim->removeCollection(collectionId: invalidCollectionId);
1916
1917 // initial state - not started, no manager.
1918 QVERIFY(!isr.isActive());
1919 QVERIFY(!isr.isFinished());
1920 QVERIFY(!isr.start());
1921 QVERIFY(!isr.cancel());
1922 QVERIFY(!isr.waitForFinished());
1923
1924 // save a list of items where one in the middle is invalid
1925 QOrganizerEvent e0, e1, e2, e3, e4;
1926 e0.setDisplayLabel("Test Event 0");
1927 e1.setDisplayLabel("Test Event 1");
1928 e2.setDisplayLabel("Test Event 2");
1929 e3.setDisplayLabel("Test Event 3");
1930 e4.setDisplayLabel("Test Event 4");
1931
1932 e2.setCollectionId(invalidCollectionId);
1933
1934 QList<QOrganizerItem> saveList;
1935 saveList << e0 << e1 << e2 << e3 << e4;
1936 isr.setManager(oim.data());
1937 QCOMPARE(isr.manager(), oim.data());
1938 QVERIFY(!isr.isActive());
1939 QVERIFY(!isr.isFinished());
1940 QVERIFY(!isr.cancel());
1941 QVERIFY(!isr.waitForFinished());
1942 qRegisterMetaType<QOrganizerItemSaveRequest*>(typeName: "QOrganizerItemSaveRequest*");
1943 QThreadSignalSpy spy(&isr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
1944 isr.setItems(saveList);
1945 QVERIFY(!isr.cancel()); // not started
1946 QVERIFY(isr.start());
1947
1948 QVERIFY((isr.isActive() && isr.state() == QOrganizerAbstractRequest::ActiveState) || isr.isFinished());
1949 //QVERIFY(isr.isFinished() || !isr.start()); // already started. // thread scheduling means this is untestable
1950 QVERIFY(isr.waitForFinished());
1951 QVERIFY(isr.isFinished());
1952 QVERIFY(spy.count() >= 1); // active + finished progress signals
1953 spy.clear();
1954
1955 QList<QOrganizerItem> expected = isr.items();
1956 QCOMPARE(expected.size(), 5);
1957 QVERIFY(isr.error() != QOrganizerManager::NoError);
1958 QVERIFY(isr.errorMap().contains(2));
1959 QVERIFY(!expected[0].id().isNull());
1960 QVERIFY(!expected[1].id().isNull());
1961 QVERIFY(expected[2].id().isNull()); // Should not have been saved
1962 QVERIFY(!expected[3].id().isNull());
1963 QVERIFY(!expected[4].id().isNull());
1964
1965 QVERIFY(oim->item(expected[0].id()).displayLabel() == expected[0].displayLabel());
1966 QVERIFY(oim->item(expected[1].id()).displayLabel() == expected[1].displayLabel());
1967 QVERIFY(oim->item(expected[3].id()).displayLabel() == expected[3].displayLabel());
1968 QVERIFY(oim->item(expected[4].id()).displayLabel() == expected[4].displayLabel());
1969
1970
1971 // save a list of items where all items are invalid
1972 QOrganizerTodo t0, t1;
1973 t0.setDisplayLabel("Test Todo 0");
1974 t1.setDisplayLabel("Test Todo 1");
1975
1976 t0.setCollectionId(invalidCollectionId);
1977 t1.setCollectionId(invalidCollectionId);
1978
1979 QList<QOrganizerItem> invalidSaveList;
1980 invalidSaveList << t0 << t1;
1981 isr.setManager(oim.data());
1982 QCOMPARE(isr.manager(), oim.data());
1983 QVERIFY(!isr.isInactive());
1984 QVERIFY(!isr.isActive());
1985 QVERIFY(isr.isFinished());
1986 QVERIFY(!isr.cancel());
1987 QVERIFY(isr.waitForFinished());
1988 //qRegisterMetaType<QOrganizerItemSaveRequest*>("QOrganizerItemSaveRequest*");
1989 isr.setItems(invalidSaveList);
1990 QVERIFY(!isr.cancel()); // not started
1991 QVERIFY(isr.start());
1992
1993 QVERIFY((isr.isActive() && isr.state() == QOrganizerAbstractRequest::ActiveState) || isr.isFinished());
1994 //QVERIFY(isr.isFinished() || !isr.start()); // already started. // thread scheduling means this is untestable
1995 QVERIFY(isr.waitForFinished());
1996 QVERIFY(isr.isFinished());
1997 QVERIFY(spy.count() >= 1); // active + finished progress signals
1998 spy.clear();
1999
2000 expected = isr.items();
2001 QCOMPARE(expected.size(), 2);
2002 QVERIFY(isr.error() != QOrganizerManager::NoError);
2003 QVERIFY(isr.errorMap().contains(0));
2004 QVERIFY(isr.errorMap().contains(1));
2005 QVERIFY(expected[0].id().isNull());
2006 QVERIFY(expected[1].id().isNull());
2007}
2008
2009void tst_QOrganizerItemAsync::itemPartialSave()
2010{
2011// QFETCH(QString, uri);
2012// QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
2013
2014// // XXX TODO: partial save for organizer items as well as items!!!
2015
2016// QList<QOrganizerItem> items(oim->items());
2017// QList<QOrganizerItem> originalItems(items);
2018// QCOMPARE(items.count(), 3);
2019
2020// QOrganizerItemId aId = items[0].id();
2021// QOrganizerItemId bId = items[1].id();
2022// QOrganizerItemId cId = items[2].id();
2023
2024// // Test 1: saving a item with a changed detail masked out does nothing
2025// QOrganizerItemPriority priority(items[0].detail<QOrganizerItemPriority>());
2026// priority.setPriority(QOrganizerItemPriority::LowPriority);
2027// items[0].saveDetail(&priority);
2028
2029// QOrganizerItemSaveRequest isr;
2030// isr.setManager(oim.data());
2031// isr.setItems(items);
2032// isr.setDefinitionMask(QStringList(QOrganizerItemEmailAddress::DefinitionName));
2033// qRegisterMetaType<QOrganizerItemSaveRequest*>("QOrganizerItemSaveRequest*");
2034// QThreadSignalSpy spy(&isr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
2035// QVERIFY(isr.start());
2036// QVERIFY((isr.isActive() && isr.state() == QOrganizerAbstractRequest::ActiveState) || isr.isFinished());
2037// QVERIFY(isr.waitForFinished());
2038// QVERIFY(isr.isFinished());
2039// QVERIFY(spy.count() >= 1); // active + finished progress signals
2040// spy.clear();
2041
2042// QCOMPARE(isr.error(), QOrganizerManager::NoError);
2043// QVERIFY(isr.errorMap().isEmpty());
2044// items[0] = oim->item(aId);
2045// QCOMPARE(items[0].detail<QOrganizerItemPriority>().priority(),
2046// originalContacts[0].detail<QOrganizerItemPriority>().priority());
2047
2048// // Test 2: saving a item with a changed detail in the mask changes it
2049// QOrganizerItemEmailAddress email;
2050// email.setEmailAddress("me@example.com");
2051// items[1].saveDetail(&email);
2052// isr.setItems(items);
2053// isr.setDefinitionMask(QStringList(QOrganizerItemEmailAddress::DefinitionName));
2054// QVERIFY(isr.start());
2055// QVERIFY(isr.waitForFinished());
2056// QCOMPARE(isr.error(), QOrganizerManager::NoError);
2057// QVERIFY(isr.errorMap().isEmpty());
2058// items[1] = oim->item(bId);
2059// QCOMPARE(items[1].detail<QOrganizerItemEmailAddress>().emailAddress(), QString("me@example.com"));
2060
2061// // 3) Remove an email address and a phone number
2062// QCOMPARE(items[1].details<QOrganizerItemPriority>().count(), 1);
2063// QCOMPARE(items[1].details<QOrganizerItemEmailAddress>().count(), 1);
2064// QVERIFY(items[1].removeDetail(&email));
2065// phn = items[1].detail<QOrganizerItemPriority>();
2066// QVERIFY(items[1].removeDetail(&priority));
2067// QVERIFY(items[1].details<QOrganizerItemEmailAddress>().count() == 0);
2068// QVERIFY(items[1].details<QOrganizerItemPriority>().count() == 0);
2069// isr.setItems(items);
2070// isr.setDefinitionMask(QStringList(QOrganizerItemEmailAddress::DefinitionName));
2071// QVERIFY(isr.start());
2072// QVERIFY(isr.waitForFinished());
2073// QCOMPARE(isr.error(), QOrganizerManager::NoError);
2074// QVERIFY(isr.errorMap().isEmpty());
2075// items[1] = oim->item(bId);
2076// QCOMPARE(items[1].details<QOrganizerItemEmailAddress>().count(), 0);
2077// QCOMPARE(items[1].details<QOrganizerItemPriority>().count(), 1);
2078
2079// // 4 - New item, no details in the mask
2080// QOrganizerItem newContact;
2081// newContact.saveDetail(&email);
2082// newContact.saveDetail(&priority);
2083// items.append(newContact);
2084// isr.setItems(items);
2085// isr.setDefinitionMask(QStringList(QOrganizerItemOnlineAccount::DefinitionName));
2086// QVERIFY(isr.start());
2087// QVERIFY(isr.waitForFinished());
2088// QCOMPARE(isr.error(), QOrganizerManager::NoError);
2089// QVERIFY(isr.errorMap().isEmpty());
2090// items = isr.items();
2091// QCOMPARE(items.size()-1, 3); // Just check that we are dealing with the item at index 3
2092// QOrganizerItemId dId = items[3].id();
2093// items[3] = oim->item(dId);
2094// QVERIFY(items[3].details<QOrganizerItemEmailAddress>().count() == 0); // not saved
2095// QVERIFY(items[3].details<QOrganizerItemPriority>().count() == 0); // not saved
2096
2097// // 5 - New item, some details in the mask
2098// QVERIFY(newContact.id() == 0);
2099// QVERIFY(newContact.details<QOrganizerItemEmailAddress>().count() == 1);
2100// QVERIFY(newContact.details<QOrganizerItemPriority>().count() == 1);
2101// items.append(newContact);
2102// isr.setItems(items);
2103// isr.setDefinitionMask(QStringList(QOrganizerItemPriority::DefinitionName));
2104// QVERIFY(isr.start());
2105// QVERIFY(isr.waitForFinished());
2106// QCOMPARE(isr.error(), QOrganizerManager::NoError);
2107// QVERIFY(isr.errorMap().isEmpty());
2108// items = isr.items();
2109// QCOMPARE(items.size()-1, 4); // Just check that we are dealing with the item at index 4
2110// QOrganizerItemId eId = items[4].id();
2111// items[4] = oim->item(eId);
2112// QCOMPARE(items[4].details<QOrganizerItemEmailAddress>().count(), 0); // not saved
2113// QCOMPARE(items[4].details<QOrganizerItemPriority>().count(), 1); // saved
2114
2115// // 6) Have a bad manager uri in the middle followed by a save error
2116// QOrganizerItemId id3(items[3].id());
2117// QOrganizerItemId badId(id3);
2118// badId.setManagerUri(QString());
2119// items[3].setId(badId);
2120// QOrganizerItemDetail badDetail("BadDetail");
2121// badDetail.setValue("BadField", "BadValue");
2122// items[4].saveDetail(&badDetail);
2123// isr.setItems(items);
2124// isr.setDefinitionMask(QStringList("BadDetail"));
2125// QVERIFY(isr.start());
2126// QVERIFY(isr.waitForFinished());
2127// QVERIFY(isr.error() != QOrganizerManager::NoError);
2128// QMap<int, QOrganizerManager::Error> errorMap(isr.errorMap());
2129// QCOMPARE(errorMap.count(), 2);
2130// QCOMPARE(errorMap[3], QOrganizerManager::DoesNotExistError);
2131// QCOMPARE(errorMap[4], QOrganizerManager::InvalidDetailError);
2132
2133// // 7) Have a non existing item in the middle followed by a save error
2134// badId = id3;
2135// badId.setLocalId(987234); // something nonexistent (hopefully)
2136// items[3].setId(badId);
2137// isr.setItems(items);
2138// isr.setDefinitionMask(QStringList("BadDetail"));
2139// QVERIFY(isr.start());
2140// QVERIFY(isr.waitForFinished());
2141// QVERIFY(isr.error() != QOrganizerManager::NoError);
2142// errorMap = isr.errorMap();
2143// QCOMPARE(errorMap.count(), 2);
2144// QCOMPARE(errorMap[3], QOrganizerManager::DoesNotExistError);
2145// QCOMPARE(errorMap[4], QOrganizerManager::InvalidDetailError);
2146
2147// // XXX TODO: partial save for organizer items as well as items!!!
2148}
2149
2150void tst_QOrganizerItemAsync::collectionFetch()
2151{
2152 QFETCH(QString, uri);
2153 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
2154
2155 QOrganizerCollectionFetchRequest cfr;
2156 QVERIFY(cfr.type() == QOrganizerAbstractRequest::CollectionFetchRequest);
2157
2158 // initial state - not started, no manager.
2159 QVERIFY(!cfr.isActive());
2160 QVERIFY(!cfr.isFinished());
2161 QVERIFY(!cfr.start());
2162 QVERIFY(!cfr.cancel());
2163 QVERIFY(!cfr.waitForFinished());
2164
2165 // retrieve all collections.
2166 cfr.setManager(oim.data());
2167 QCOMPARE(cfr.manager(), oim.data());
2168 QVERIFY(!cfr.isActive());
2169 QVERIFY(!cfr.isFinished());
2170 QVERIFY(!cfr.cancel());
2171 QVERIFY(!cfr.waitForFinished());
2172 qRegisterMetaType<QOrganizerCollectionFetchRequest*>(typeName: "QOrganizerCollectionFetchRequest*");
2173 QThreadSignalSpy spy(&cfr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
2174 QVERIFY(!cfr.cancel()); // not started
2175
2176 QVERIFY(cfr.start());
2177 //QVERIFY(cfr.isFinished() || !cfr.start()); // already started. // thread scheduling means this is untestable
2178 QVERIFY((cfr.isActive() && cfr.state() == QOrganizerAbstractRequest::ActiveState) || cfr.isFinished());
2179 QVERIFY(cfr.waitForFinished());
2180 QVERIFY(cfr.isFinished());
2181
2182 QVERIFY(spy.count() >= 1); // active + finished progress signals
2183 spy.clear();
2184
2185 QList<QOrganizerCollection> syncCols = oim->collections();
2186 QList<QOrganizerCollection> cols = cfr.collections();
2187 QCOMPARE(cols.size(), syncCols.size());
2188 for (int i = 0; i < cols.size(); i++) {
2189 QOrganizerCollection curr = cols.at(i);
2190 QVERIFY(syncCols.contains(curr));
2191 }
2192
2193 // cancelling
2194 int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
2195 while (true) {
2196 QVERIFY(!cfr.cancel()); // not started
2197 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
2198 QVERIFY(cfr.start());
2199 if (!cfr.cancel()) {
2200 // due to thread scheduling, async cancel might be attempted
2201 // after the request has already finished.. so loop and try again.
2202 spy.clear();
2203 cfr.waitForFinished();
2204 bailoutCount -= 1;
2205 if (!bailoutCount) {
2206// qWarning("Unable to test cancelling due to thread scheduling!");
2207 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
2208 break;
2209 }
2210 continue;
2211 }
2212
2213 // if we get here, then we are cancelling the request.
2214 QVERIFY(cfr.waitForFinished());
2215 QVERIFY(cfr.isCanceled());
2216
2217 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
2218 spy.clear();
2219 break;
2220 }
2221
2222 // restart, and wait for progress after cancel.
2223 while (true) {
2224 QVERIFY(!cfr.cancel()); // not started
2225 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
2226 QVERIFY(cfr.start());
2227 if (!cfr.cancel()) {
2228 // due to thread scheduling, async cancel might be attempted
2229 // after the request has already finished.. so loop and try again.
2230 cfr.waitForFinished();
2231 bailoutCount -= 1;
2232 spy.clear();
2233 if (!bailoutCount) {
2234 //qWarning("Unable to test cancelling due to thread scheduling!");
2235 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
2236 break;
2237 }
2238 continue;
2239 }
2240 cfr.waitForFinished();
2241 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
2242 spy.clear();
2243 QVERIFY(!cfr.isActive());
2244 QVERIFY(cfr.state() == QOrganizerAbstractRequest::CanceledState);
2245 break;
2246 }
2247}
2248
2249void tst_QOrganizerItemAsync::collectionRemove()
2250{
2251 QFETCH(QString, uri);
2252 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
2253 QOrganizerCollectionRemoveRequest crr;
2254 QVERIFY(crr.type() == QOrganizerAbstractRequest::CollectionRemoveRequest);
2255
2256 // initial state - not started, no manager.
2257 QVERIFY(!crr.isActive());
2258 QVERIFY(!crr.isFinished());
2259 QVERIFY(!crr.start());
2260 QVERIFY(!crr.cancel());
2261 QVERIFY(!crr.waitForFinished());
2262
2263 // specific collection set
2264 QOrganizerCollectionId removeId = oim->collections().last().id();
2265 if (oim->defaultCollectionId() == removeId)
2266 removeId = oim->collections().first().id();
2267 crr.setCollectionId(removeId);
2268 QVERIFY(crr.collectionIds() == QList<QOrganizerCollectionId>() << removeId);
2269 int originalCount = oim->collections().size();
2270 crr.setManager(oim.data());
2271 QCOMPARE(crr.manager(), oim.data());
2272 QVERIFY(!crr.isActive());
2273 QVERIFY(!crr.isFinished());
2274 QVERIFY(!crr.cancel());
2275 QVERIFY(!crr.waitForFinished());
2276 qRegisterMetaType<QOrganizerCollectionRemoveRequest*>(typeName: "QOrganizerCollectionRemoveRequest*");
2277 QThreadSignalSpy spy(&crr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
2278 QVERIFY(!crr.cancel()); // not started
2279 QVERIFY(crr.start());
2280 QVERIFY((crr.isActive() &&crr.state() == QOrganizerAbstractRequest::ActiveState) || crr.isFinished());
2281 //QVERIFY(crr.isFinished() || !crr.start()); // already started. // thread scheduling means this is untestable
2282 QVERIFY(crr.waitForFinished());
2283 QVERIFY(crr.isFinished());
2284
2285 QVERIFY(spy.count() >= 1); // active + finished progress signals
2286 spy.clear();
2287
2288 QCOMPARE(oim->collections().size(), originalCount - 1); // should have removed that particular collection.
2289 QVERIFY(crr.error() == QOrganizerManager::NoError);
2290 QVERIFY(crr.errorMap().isEmpty());
2291
2292 // remove all collections
2293 QList<QOrganizerCollectionId> allCollectionIds;
2294 QList<QOrganizerCollection> allCollections = oim->collections();
2295 for (int i = 0; i < allCollections.size(); ++i)
2296 allCollectionIds << allCollections.at(i).id();
2297 crr.setCollectionIds(allCollectionIds);
2298
2299 QVERIFY(!crr.cancel()); // not started
2300 QVERIFY(crr.start());
2301
2302 QVERIFY((crr.isActive() && crr.state() == QOrganizerAbstractRequest::ActiveState) || crr.isFinished());
2303 //QVERIFY(crr.isFinished() || !crr.start()); // already started. // thread scheduling means this is untestable
2304 QVERIFY(crr.waitForFinished());
2305 QVERIFY(crr.isFinished());
2306
2307 QVERIFY(oim->collections().size() >= 1); // at least one collection must be left, since default collection cannot be removed.
2308 QVERIFY(spy.count() >= 1); // active + finished progress signals
2309 spy.clear();
2310
2311 // remove empty list
2312 QList<QOrganizerCollectionId> collectionIdList;
2313 QOrganizerCollectionRemoveRequest crr1;
2314 crr1.setManager(oim.data());
2315 crr1.setCollectionIds(collectionIdList);
2316 crr1.start();
2317 crr1.waitForFinished();
2318 QVERIFY(crr1.isFinished());
2319 QVERIFY(crr1.error() == QOrganizerManager::NoError);
2320
2321 // cancelling
2322 QOrganizerCollection temp;
2323 temp.setMetaData(key: QOrganizerCollection::KeyDescription, value: "Should not be removed!");
2324 oim->saveCollection(collection: &temp);
2325 crr.setCollectionId(temp.id());
2326
2327 int collectionCount = oim->collections().size();
2328 int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
2329 while (true) {
2330 QVERIFY(!crr.cancel()); // not started
2331 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
2332 QVERIFY(spy.count() == 0);
2333 QVERIFY(crr.start());
2334 if (!crr.cancel()) {
2335 // due to thread scheduling, async cancel might be attempted
2336 // after the request has already finished.. so loop and try again.
2337 crr.waitForFinished();
2338 temp.setId(QOrganizerCollectionId());
2339 if (!oim->saveCollection(collection: &temp)) {
2340 QSKIP("Unable to save temporary item for remove request cancellation test!");
2341 }
2342 crr.setCollectionId(temp.id());
2343 bailoutCount -= 1;
2344 if (!bailoutCount) {
2345// qWarning("Unable to test cancelling due to thread scheduling!");
2346 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
2347 break;
2348 }
2349 spy.clear();
2350 continue;
2351 }
2352
2353 // if we get here, then we are cancelling the request.
2354 QVERIFY(crr.waitForFinished());
2355 QVERIFY(crr.isCanceled());
2356 QCOMPARE(oim->collections().size(), collectionCount); // temp collection should not have been removed
2357 QList<QOrganizerCollectionId> removeCollectionIds;
2358 QList<QOrganizerCollection> removeCollections = oim->collections();
2359 for (int i = 0; i < removeCollections.size(); ++i)
2360 removeCollectionIds << removeCollections.at(i).id();
2361 QVERIFY(containsAllCollectionIds(removeCollectionIds, crr.collectionIds()));
2362 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
2363 spy.clear();
2364 break;
2365 }
2366
2367 // restart, and wait for progress after cancel.
2368 while (true) {
2369 QVERIFY(!crr.cancel()); // not started
2370 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
2371 QVERIFY(crr.start());
2372 if (!crr.cancel()) {
2373 // due to thread scheduling, async cancel might be attempted
2374 // after the request has already finished.. so loop and try again.
2375 crr.waitForFinished();
2376 temp.setId(QOrganizerCollectionId());
2377 if (!oim->saveCollection(collection: &temp)) {
2378 QSKIP("Unable to save temporary item for remove request cancellation test!");
2379 }
2380 crr.setCollectionId(temp.id());
2381 bailoutCount -= 1;
2382 if (!bailoutCount) {
2383// qWarning("Unable to test cancelling due to thread scheduling!");
2384 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
2385 break;
2386 }
2387 spy.clear();
2388 continue;
2389 }
2390 crr.waitForFinished();
2391 QVERIFY(crr.isCanceled());
2392 QCOMPARE(oim->collections().size(), collectionCount); // temp collection should not have been removed
2393 QList<QOrganizerCollectionId> removeCollectionIds;
2394 QList<QOrganizerCollection> removeCollections = oim->collections();
2395 for (int i = 0; i < removeCollections.size(); ++i)
2396 removeCollectionIds << removeCollections.at(i).id();
2397 QVERIFY(containsAllCollectionIds(removeCollectionIds, crr.collectionIds()));
2398 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
2399 spy.clear();
2400 break;
2401 }
2402
2403 // now clean up our temp collection.
2404 oim->removeCollection(collectionId: temp.id());
2405}
2406
2407void tst_QOrganizerItemAsync::collectionSave()
2408{
2409 QFETCH(QString, uri);
2410 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
2411 QOrganizerCollectionSaveRequest csr;
2412 QVERIFY(csr.type() == QOrganizerAbstractRequest::CollectionSaveRequest);
2413
2414 // initial state - not started, no manager.
2415 QVERIFY(!csr.isActive());
2416 QVERIFY(!csr.isFinished());
2417 QVERIFY(!csr.start());
2418 QVERIFY(!csr.cancel());
2419 QVERIFY(!csr.waitForFinished());
2420
2421 // save a new item
2422 int originalCount = oim->collections().size();
2423 QOrganizerCollection testCollection;
2424 testCollection.setMetaData(key: QOrganizerCollection::KeyDescription, value: "test description");
2425 testCollection.setMetaData(key: QOrganizerCollection::KeyName, value: "New collection");
2426 QList<QOrganizerCollection> saveList;
2427 saveList << testCollection;
2428 csr.setManager(oim.data());
2429 QCOMPARE(csr.manager(), oim.data());
2430 QVERIFY(!csr.isActive());
2431 QVERIFY(!csr.isFinished());
2432 QVERIFY(!csr.cancel());
2433 QVERIFY(!csr.waitForFinished());
2434 qRegisterMetaType<QOrganizerCollectionSaveRequest*>(typeName: "QOrganizerCollectionSaveRequest*");
2435 QThreadSignalSpy spy(&csr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
2436 csr.setCollection(testCollection);
2437 QCOMPARE(csr.collections(), saveList);
2438 QVERIFY(!csr.cancel()); // not started
2439 QVERIFY(csr.start());
2440
2441 QVERIFY((csr.isActive() && csr.state() == QOrganizerAbstractRequest::ActiveState) || csr.isFinished());
2442 //QVERIFY(csr.isFinished() || !csr.start()); // already started. // thread scheduling means this is untestable
2443 QVERIFY(csr.waitForFinished());
2444 QVERIFY(csr.isFinished());
2445 QVERIFY(spy.count() >= 1); // active + finished progress signals
2446 spy.clear();
2447
2448 QList<QOrganizerCollection> expected = csr.collections();
2449 QCOMPARE(expected.size(), 1);
2450 QList<QOrganizerCollection> result;
2451 result << oim->collection(collectionId: csr.collections().at(i: 0).id());
2452
2453 // find the saved one, compare.
2454 foreach (const QOrganizerCollection &col, result)
2455 QVERIFY(col.id() == expected.at(0).id());
2456
2457 // update a previously saved collection
2458 QVERIFY(!result.isEmpty()); // make sure that we were able to retrieve the required collection.
2459 testCollection = result.first();
2460 testCollection.setMetaData(key: QOrganizerCollection::KeyName, value: "test name");
2461 saveList.clear();
2462 saveList << testCollection;
2463 csr.setCollections(saveList);
2464 QCOMPARE(csr.collections(), saveList);
2465 QVERIFY(!csr.cancel()); // not started
2466 QVERIFY(csr.start());
2467
2468 QVERIFY((csr.isActive() && csr.state() == QOrganizerAbstractRequest::ActiveState) || csr.isFinished());
2469 //QVERIFY(csr.isFinished() || !csr.start()); // already started. // thread scheduling means this is untestable
2470 QVERIFY(csr.waitForFinished());
2471
2472 QVERIFY(csr.isFinished());
2473 QVERIFY(spy.count() >= 1); // active + finished progress signals
2474 spy.clear();
2475
2476 expected = csr.collections();
2477 result.clear();
2478 result = oim->collections();
2479 // find the saved one, compare.
2480 foreach (const QOrganizerCollection& col, result) {
2481 if (col.id() == expected.at(i: 0).id()) {
2482 QVERIFY(col == expected.at(0)); // XXX TODO: if we change the semantic so that save merely updates the id...?
2483 }
2484 }
2485 QCOMPARE(oim->collections().size(), originalCount + 1); // ie shouldn't have added an extra one (would be +2)
2486 QVERIFY(csr.error() == QOrganizerManager::NoError);
2487 QVERIFY(csr.errorMap().isEmpty());
2488
2489 // save empty list
2490 QList<QOrganizerCollection> collectionList;
2491 QOrganizerCollectionSaveRequest csr1;
2492 csr1.setManager(oim.data());
2493 csr1.setCollections(collectionList);
2494 csr1.start();
2495 csr1.waitForFinished();
2496 QVERIFY(csr1.isFinished());
2497 QVERIFY(csr1.error() == QOrganizerManager::NoError);
2498
2499 // cancelling
2500 QOrganizerCollection temp;
2501 temp.setMetaData(testCollection.metaData());
2502 temp.setExtendedMetaData(key: "test", value: "shouldn't be saved");
2503 saveList.clear();
2504 saveList << temp;
2505 csr.setCollections(saveList);
2506
2507 int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times. If it doesn't work due to threading, bail out.
2508 while (true) {
2509 QVERIFY(!csr.cancel()); // not started
2510 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
2511 QVERIFY(csr.start());
2512 if (!csr.cancel()) {
2513 // due to thread scheduling, async cancel might be attempted
2514 // after the request has already finished.. so loop and try again.
2515 csr.waitForFinished();
2516 saveList = csr.collections();
2517 if (oim->collections().size() > (originalCount + 1) && !oim->removeCollection(collectionId: saveList.at(i: 0).id())) {
2518 QSKIP("Unable to remove saved collection to test cancellation of collection save request");
2519 }
2520 saveList.clear();
2521 saveList << temp;
2522 csr.setCollections(saveList);
2523 bailoutCount -= 1;
2524 if (!bailoutCount) {
2525// qWarning("Unable to test cancelling due to thread scheduling!");
2526 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
2527 break;
2528 }
2529 spy.clear();
2530 continue;
2531 }
2532
2533 // if we get here, then we are cancelling the request.
2534 QVERIFY(csr.waitForFinished());
2535 QVERIFY(csr.isCanceled());
2536 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
2537 spy.clear();
2538
2539 // verify that the changes were not saved
2540 expected.clear();
2541 QList<QOrganizerCollection> allCollections = oim->collections();
2542 QVERIFY(!allCollections.contains(temp)); // should NOT contain it since it was cancelled.
2543 QCOMPARE(allCollections.size(), originalCount + 1);
2544 break;
2545 }
2546 // restart, and wait for progress after cancel.
2547
2548 while (true) {
2549 QVERIFY(!csr.cancel()); // not started
2550 FILL_QUEUE_WITH_FETCH_REQUESTS(oim.data());
2551 QVERIFY(csr.start());
2552 if (!csr.cancel()) {
2553 // due to thread scheduling, async cancel might be attempted
2554 // after the request has already finished.. so loop and try again.
2555 csr.waitForFinished();
2556 saveList = csr.collections();
2557 if (oim->collections().size() > (originalCount + 1) && !oim->removeCollection(collectionId: saveList.at(i: 0).id())) {
2558 QSKIP("Unable to remove saved item to test cancellation of item save request");
2559 }
2560 saveList.clear();
2561 saveList << temp;
2562 csr.setCollections(saveList);
2563 bailoutCount -= 1;
2564 if (!bailoutCount) {
2565// qWarning("Unable to test cancelling due to thread scheduling!");
2566 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
2567 break;
2568 }
2569 spy.clear();
2570 continue;
2571 }
2572 csr.waitForFinished(); // now wait until finished (if it hasn't already).
2573 QVERIFY(csr.isCanceled());
2574 QVERIFY(spy.count() >= 1); // active + cancelled progress signals
2575 spy.clear();
2576
2577 // verify that the changes were not saved
2578 expected.clear();
2579 QList<QOrganizerCollection> allCollections = oim->collections();
2580 QVERIFY(!allCollections.contains(temp));
2581 QCOMPARE(oim->collections().size(), originalCount + 1);
2582 break;
2583 }
2584}
2585
2586
2587void tst_QOrganizerItemAsync::testQuickDestruction()
2588{
2589 QFETCH(QString, uri);
2590
2591 // in this test, we create a manager, fire off a request, and delete the manager, all in quick succession
2592 // this is to test for segfaults etc.
2593 for (int i = 0; i < 10; i++) {
2594 QOrganizerItemFetchRequest ifr;
2595 QOrganizerManager *cm = prepareModel(uri);
2596 ifr.setManager(cm);
2597 ifr.start();
2598 delete cm;
2599 }
2600 // in this test, we create a manager, fire off a request, delete the request, then delete the manager, all in quick succession
2601 // this is to test for segfaults, etc.
2602 for (int i = 0; i < 10; i++) {
2603 QOrganizerItemFetchRequest *ifr = new QOrganizerItemFetchRequest;
2604 QOrganizerManager *cm = prepareModel(uri);
2605 ifr->setManager(cm);
2606 ifr->start();
2607 delete ifr;
2608 delete cm;
2609 }
2610 // in this test, we create a manager, fire off a request, delete the manager, then delete the request, all in quick succession
2611 // this is to test for segfaults, etc.
2612 for (int i = 0; i < 10; i++) {
2613 QOrganizerItemFetchRequest *ifr = new QOrganizerItemFetchRequest;
2614 QOrganizerManager *cm = prepareModel(uri);
2615 ifr->setManager(cm);
2616 ifr->start();
2617 delete cm;
2618 delete ifr;
2619 }
2620 // in this test, we create a manager, fire off a request, and delete the request, all in quick succession
2621 // this is to test for segfaults, etc.
2622 QOrganizerManager *cm = prepareModel(uri);
2623 for (int i = 0; i < 10; i++) {
2624 QOrganizerItemFetchRequest *ifr = new QOrganizerItemFetchRequest;
2625 ifr->setManager(cm);
2626 ifr->start();
2627 delete ifr;
2628 }
2629 delete cm;
2630}
2631
2632void tst_QOrganizerItemAsync::threadDelivery()
2633{
2634 QFETCH(QString, uri);
2635 QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
2636 m_mainThreadId = oim->thread()->currentThreadId();
2637 m_resultsAvailableSlotThreadId = m_mainThreadId;
2638
2639 // now perform a fetch request and check that the progress is delivered to the correct thread.
2640 QOrganizerItemFetchRequest *req = new QOrganizerItemFetchRequest;
2641 req->setManager(oim.data());
2642 connect(sender: req, SIGNAL(resultsAvailable()), receiver: this, SLOT(resultsAvailableReceived()));
2643 req->start();
2644
2645 int totalWaitTime = 0;
2646 QTest::qWait(ms: 1); // force it to process events at least once.
2647 while (req->state() != QOrganizerAbstractRequest::FinishedState) {
2648 // ensure that the progress signal was delivered to the main thread.
2649 QCOMPARE(m_mainThreadId, m_resultsAvailableSlotThreadId);
2650
2651 QTest::qWait(ms: 5); // spin until done
2652 totalWaitTime += 5;
2653
2654 // break after 30 seconds.
2655 if (totalWaitTime > 30000) {
2656 delete req;
2657 QSKIP("Asynchronous request not complete after 30 seconds!");
2658 }
2659 }
2660
2661 // ensure that the progress signal was delivered to the main thread.
2662 QCOMPARE(m_mainThreadId, m_resultsAvailableSlotThreadId);
2663 delete req;
2664}
2665
2666void tst_QOrganizerItemAsync::testDebugStreamOut()
2667{
2668// QOrganizerItemFetchHint fetchHint;
2669
2670// // Testing the empty case
2671// QTest::ignoreMessage(QtDebugMsg, "QOrganizerItemFetchHint(detailDefinitionsHint=() ,optimizationHints=0)");
2672// qDebug() << fetchHint;
2673
2674// // Testing the completely filled case
2675// fetchHint.setDetailDefinitionsHint(QStringList(QOrganizerItemDescription::DefinitionName));
2676// fetchHint.setOptimizationHints(QOrganizerItemFetchHint::NoBinaryBlobs);
2677// QTest::ignoreMessage(QtDebugMsg, "QOrganizerItemFetchHint(detailDefinitionsHint=(\"Description\") ,optimizationHints=4)");
2678// qDebug() << fetchHint;
2679
2680
2681
2682// // Testing QOrganizerItemSaveRequest
2683
2684// QOrganizerItemSaveRequest isr;
2685
2686// // Testing the empty case
2687// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemSaveRequest(\n* items=() ,\n* definitionMask=() ,\n* errorMap=QMap() \n))");
2688// qDebug() << isr;
2689
2690// // Testing the filled-in case
2691// isr.setDefinitionMask(QStringList("BadDetail"));
2692// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemSaveRequest(\n* items=() ,\n* definitionMask=(\"BadDetail\") ,\n* errorMap=QMap() \n))");
2693// qDebug() << isr;
2694
2695
2696// // Testing QOrganizerItemSaveRequest
2697
2698// QOrganizerItemFetchRequest ifr;
2699
2700// // Testing the empty case
2701// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemFetchRequest(\n* items=() ,\n* filter=QOrganizerItemFilter((null)),\n* sorting=() ,\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=() ,optimizationHints=0),\n* maxCount=-1\n))");
2702// qDebug() << ifr;
2703
2704// // Testing the filled-in case
2705// QOrganizerItemFilter fil;
2706// ifr.setFilter(fil);
2707// QOrganizerItemSortOrder sortOrder;
2708// sortOrder.setDetailDefinitionName(QOrganizerItemPriority::DefinitionName, QOrganizerItemPriority::FieldPriority);
2709// QList<QOrganizerItemSortOrder> sorting;
2710// sorting.append(sortOrder);
2711// ifr.setSorting(sorting);
2712// fetchHint.setDetailDefinitionsHint(QStringList(QOrganizerItemDescription::DefinitionName));
2713// ifr.setFetchHint(fetchHint);
2714// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemFetchRequest(\n* items=() ,\n* filter=QOrganizerItemFilter((null)),\n* sorting=(QOrganizerItemSortOrder(detailDefinitionName=\"Priority\",detailFieldName=\"Priority\",blankPolicy=1,direction=0,caseSensitivity=1)) ,\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=(\"Description\") ,optimizationHints=4),\n* maxCount=-1\n))");
2715// qDebug() << ifr;
2716
2717
2718
2719// // Testing QOrganizerItemFetchForExportRequest
2720
2721// QOrganizerItemFetchForExportRequest ifer;
2722
2723// // Testing the empty case
2724// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemFetchForExportRequest(\n* items=() ,\n* filter=QOrganizerItemFilter((null)),\n* sorting=() ,\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=() ,optimizationHints=0)\n))");
2725// qDebug() << ifer;
2726
2727// // Testing the filled-in case
2728// ifer.setFilter(fil);
2729// ifer.setSorting(sorting);
2730// ifer.setStartDate(QDateTime());
2731// ifer.setEndDate(QDateTime());
2732// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemFetchForExportRequest(\n* items=() ,\n* filter=QOrganizerItemFilter((null)),\n* sorting=(QOrganizerItemSortOrder(detailDefinitionName=\"Priority\",detailFieldName=\"Priority\",blankPolicy=1,direction=0,caseSensitivity=1)) ,\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=() ,optimizationHints=0)\n))");
2733// qDebug() << ifer;
2734
2735
2736// // Testing QOrganizerItemFetchByIdRequest
2737// QOrganizerItemFetchByIdRequest ifbidr;
2738
2739// // Testing the empty case
2740// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemFetchByIdRequest(\n* items=() ,\n* ids=() ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=() ,optimizationHints=0),\n* errorMap=QMap() \n))");
2741// qDebug() << ifbidr;
2742
2743// // Test the filled-in case
2744// fetchHint.setDetailDefinitionsHint(QStringList(QOrganizerItemDescription::DefinitionName));
2745// ifbidr.setFetchHint(fetchHint);
2746// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemFetchByIdRequest(\n* items=() ,\n* ids=() ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=(\"Description\") ,optimizationHints=4),\n* errorMap=QMap() \n))");
2747// qDebug() << ifbidr;
2748
2749
2750
2751// // Testing QOrganizerItemOccurrenceFetchRequest
2752
2753// QOrganizerItemOccurrenceFetchRequest iofr;
2754
2755// // Testing the empty case
2756// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemOccurrenceFetchRequest(\n* itemOccurrences=() ,\n* parentItem=QOrganizerItem(QOrganizerItemId((null))) in collection(QOrganizerCollectionId((null))) \n QOrganizerItemDetail(name=\"Type\", key=201754, \"Type\"=QVariant(QString, \"Note\") ),\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=() ,optimizationHints=0),\n* maxOccurrences=-1\n))");
2757// qDebug() << iofr;
2758
2759// // Testing the filled-in case
2760// QOrganizerItem parent;
2761// iofr.setParentItem(parent);
2762// iofr.setFetchHint(fetchHint);
2763// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemOccurrenceFetchRequest(\n* itemOccurrences=() ,\n* parentItem=QOrganizerItem(QOrganizerItemId((null))) in collection(QOrganizerCollectionId((null))) \n QOrganizerItemDetail(name=\"Type\", key=201756, \"Type\"=QVariant(QString, \"Note\") ),\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") ,\n* fetchHint=QOrganizerItemFetchHint(detailDefinitionsHint=(\"Description\") ,optimizationHints=4),\n* maxOccurrences=-1\n))");
2764// qDebug() << iofr;
2765
2766
2767// // Testing QOrganizerItemRemoveRequest
2768
2769// QOrganizerItemRemoveRequest irr;
2770
2771// // Testing the empty case
2772// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemRemoveRequest(itemIds=() ,errorMap=QMap() \n))");
2773// qDebug() << irr;
2774
2775// // Testing the filled-in case
2776// QString mgr = "memory";
2777// QMap<QString, QString> params;
2778// params.insert("id", "tst_QOrganizerManager");
2779// QString uri = QOrganizerManager::buildUri(mgr, params);
2780// QScopedPointer<QOrganizerManager> oim(prepareModel(uri));
2781
2782// qRegisterMetaType<QList<QOrganizerItemId> >("QList<QOrganizerItemId>");
2783
2784// QVERIFY(irr.type() == QOrganizerAbstractRequest::ItemRemoveRequest);
2785
2786// // initial state - not started, no manager.
2787// QVERIFY(!irr.isActive());
2788// QVERIFY(!irr.isFinished());
2789// QVERIFY(!irr.start());
2790// QVERIFY(!irr.cancel());
2791// QVERIFY(!irr.waitForFinished());
2792
2793// // fill manager with test data
2794
2795// QOrganizerTodo testTodo1;
2796// QOrganizerItemDisplayLabel label;
2797// label.setLabel("Test todo 1");
2798// testTodo1.saveDetail(&label);
2799// QVERIFY(oim->saveItem(&testTodo1));
2800
2801// testTodo1.setId(QOrganizerItemId());
2802// label.setLabel("Test todo 2");
2803// testTodo1.saveDetail(&label);
2804// QOrganizerItemComment comment;
2805// comment.setComment("todo comment");
2806// testTodo1.saveDetail(&comment);
2807// QVERIFY(oim->saveItem(&testTodo1));
2808
2809// QList<QOrganizerItemId> allIds(oim->itemIds());
2810// QVERIFY(!allIds.isEmpty());
2811// QOrganizerItemId removableId(allIds.first());
2812
2813// // specific item set
2814// irr.setItemId(removableId);
2815// QVERIFY(irr.itemIds() == QList<QOrganizerItemId>() << removableId);
2816
2817// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemRemoveRequest(itemIds=(QOrganizerItemId(QOrganizerItemMemoryEngineId(1, 2,\"qtorganizer:memory:id=tst_QOrganizerManager\"))) ,errorMap=QMap() \n))");
2818// qDebug() << irr;
2819
2820
2821
2822// // Testing ItemIdFetchRequest
2823
2824// // Testing the empty case
2825// QOrganizerItemIdFetchRequest iidfr;
2826// QVERIFY(iidfr.type() == QOrganizerAbstractRequest::ItemIdFetchRequest);
2827
2828// // initial state - not started, no manager.
2829// QVERIFY(!iidfr.isActive());
2830// QVERIFY(!iidfr.isFinished());
2831// QVERIFY(!iidfr.start());
2832// QVERIFY(!iidfr.cancel());
2833// QVERIFY(!iidfr.waitForFinished());
2834
2835// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemIdFetchRequest(\n* itemIds=() ,\n* filter=QOrganizerItemFilter((null)),\n* sorting=() ,\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") \n))");
2836// qDebug() << iidfr;
2837
2838// // Testing the filled-in case
2839
2840// // "all items" retrieval
2841// iidfr.setManager(oim.data());
2842// QCOMPARE(iidfr.manager(), oim.data());
2843// QVERIFY(!iidfr.isActive());
2844// QVERIFY(!iidfr.isFinished());
2845// QVERIFY(!iidfr.cancel());
2846// QVERIFY(!iidfr.waitForFinished());
2847// qRegisterMetaType<QOrganizerItemIdFetchRequest*>("QOrganizerItemIdFetchRequest*");
2848
2849// QThreadSignalSpy spy(&iidfr, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)));
2850// iidfr.setFilter(fil);
2851// QCOMPARE(iidfr.filter(), fil);
2852// QVERIFY(!iidfr.cancel()); // not started
2853// QVERIFY(iidfr.start());
2854
2855// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemIdFetchRequest(\n* itemIds=(QOrganizerItemId(QOrganizerItemMemoryEngineId(1, 2,\"qtorganizer:memory:id=tst_QOrganizerManager\")), QOrganizerItemId(QOrganizerItemMemoryEngineId(1, 3,\"qtorganizer:memory:id=tst_QOrganizerManager\")), QOrganizerItemId(QOrganizerItemMemoryEngineId(1, 4,\"qtorganizer:memory:id=tst_QOrganizerManager\")), QOrganizerItemId(QOrganizerItemMemoryEngineId(1, 5,\"qtorganizer:memory:id=tst_QOrganizerManager\")), QOrganizerItemId(QOrganizerItemMemoryEngineId(1, 6,\"qtorganizer:memory:id=tst_QOrganizerManager\"))) ,\n* filter=QOrganizerItemFilter((null)),\n* sorting=() ,\n* startDate=QDateTime(\"\") ,\n* endDate=QDateTime(\"\") \n))");
2856// qDebug() << iidfr;
2857
2858
2859// // Testing QOrganizerItemDetailDefinitionFetchRequest
2860
2861// // Testing the empty case
2862// QOrganizerItemDetailDefinitionFetchRequest dfr;
2863// QVERIFY(dfr.type() == QOrganizerAbstractRequest::DetailDefinitionFetchRequest);
2864// QVERIFY(dfr.itemType() == QString(QLatin1String(QOrganizerItemType::TypeNote))); // ensure ctor sets item type correctly.
2865// dfr.setItemType(QOrganizerItemType::TypeEvent);
2866// QVERIFY(dfr.itemType() == QString(QLatin1String(QOrganizerItemType::TypeEvent)));
2867
2868// // initial state - not started, no manager.
2869// QVERIFY(!dfr.isActive());
2870// QVERIFY(!dfr.isFinished());
2871// QVERIFY(!dfr.start());
2872// QVERIFY(!dfr.cancel());
2873// QVERIFY(!dfr.waitForFinished());
2874
2875// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemDetailDefinitionFetchRequest(\n* definitionNames=() ,\n* definitions=QMap() ,\n* itemType=\"Event\",\n* errorMap=QMap() \n))");
2876// qDebug() << dfr;
2877
2878// // Note: testing of the filled-in case has been removed due to issues (expected-message string gets truncated after 1000 characters)
2879
2880
2881// // Testing QOrganizerItemDetailDefinitionSaveRequest
2882
2883// // Testing the empty case
2884// QOrganizerItemDetailDefinitionSaveRequest dsr;
2885// QVERIFY(dsr.type() == QOrganizerAbstractRequest::DetailDefinitionSaveRequest);
2886// QVERIFY(dsr.itemType() == QString(QLatin1String(QOrganizerItemType::TypeNote))); // ensure ctor sets item type correctly
2887// dsr.setItemType(QOrganizerItemType::TypeEvent);
2888// QVERIFY(dsr.itemType() == QString(QLatin1String(QOrganizerItemType::TypeEvent)));
2889
2890// // initial state - not started, no manager.
2891// QVERIFY(!dsr.isActive());
2892// QVERIFY(!dsr.isFinished());
2893// QVERIFY(!dsr.start());
2894// QVERIFY(!dsr.cancel());
2895// QVERIFY(!dsr.waitForFinished());
2896
2897// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemDetailDefinitionSaveRequest(\n* definitions=() ,\n* itemType=\"Event\",\n* errorMap=QMap() \n))");
2898// qDebug() << dsr;
2899
2900// // Testing the filled-in case
2901
2902// // save a new detail definition
2903// int originalCount = oim->detailDefinitions(QOrganizerItemType::TypeEvent).keys().size();
2904// QOrganizerItemDetailDefinition testDef;
2905// testDef.setName("TestDefinitionId");
2906// QMap<QString, QOrganizerItemDetailFieldDefinition> fields;
2907// QOrganizerItemDetailFieldDefinition f;
2908// f.setDataType(QVariant::String);
2909// fields.insert("TestDefinitionField", f);
2910// testDef.setFields(fields);
2911// QList<QOrganizerItemDetailDefinition> saveList;
2912// saveList << testDef;
2913// dsr.setManager(oim.data());
2914// QCOMPARE(dsr.manager(), oim.data());
2915// QVERIFY(!dsr.isActive());
2916// QVERIFY(!dsr.isFinished());
2917// QVERIFY(!dsr.cancel());
2918// QVERIFY(!dsr.waitForFinished());
2919// qRegisterMetaType<QOrganizerItemDetailDefinitionSaveRequest*>("QOrganizerItemDetailDefinitionSaveRequest*");
2920// dsr.setDefinition(testDef);
2921// QCOMPARE(dsr.definitions(), saveList);
2922// QVERIFY(!dsr.cancel()); // not started
2923// QVERIFY(dsr.start());
2924
2925
2926// QVERIFY((dsr.isActive() && dsr.state() == QOrganizerAbstractRequest::ActiveState) || dsr.isFinished());
2927// //QVERIFY(dsr.isFinished() || !dsr.start()); // already started. // thread scheduling means this is untestable
2928// QVERIFY(dsr.waitForFinished());
2929// QVERIFY(dsr.isFinished());
2930// QVERIFY(spy.count() >= 1); // active + finished progress signals
2931// spy.clear();
2932
2933// QList<QOrganizerItemDetailDefinition> expected;
2934// expected << oim->detailDefinition("TestDefinitionId", QOrganizerItemType::TypeEvent);
2935// QList<QOrganizerItemDetailDefinition> result = dsr.definitions();
2936// QCOMPARE(expected, result);
2937// QVERIFY(expected.contains(testDef));
2938// QCOMPARE(oim->detailDefinitions(QOrganizerItemType::TypeEvent).values().size(), originalCount + 1);
2939
2940// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemDetailDefinitionSaveRequest(\n* definitions=(QOrganizerItemDetailDefinition(name=\"TestDefinitionId\",isUnique=false,isEmpty=false,fields=QMap((\"TestDefinitionField\", QOrganizerItemDetailFieldDefinition(dataType=10,allowableValues=() ))) )) ,\n* itemType=\"Event\",\n* errorMap=QMap() \n))");
2941// qDebug() << dsr;
2942
2943
2944// // Testing QOrganizerItemDetailDefinitionRemoveRequest
2945
2946// // Testing the empty case
2947// QOrganizerItemDetailDefinitionRemoveRequest drr;
2948// QVERIFY(drr.type() == QOrganizerAbstractRequest::DetailDefinitionRemoveRequest);
2949// QVERIFY(drr.itemType() == QString(QLatin1String(QOrganizerItemType::TypeNote))); // ensure ctor sets item type correctly.
2950// drr.setItemType(QOrganizerItemType::TypeEvent);
2951// drr.setDefinitionNames(QStringList());
2952// QVERIFY(drr.itemType() == QString(QLatin1String(QOrganizerItemType::TypeEvent)));
2953
2954// // initial state - not started, no manager.
2955// QVERIFY(!drr.isActive());
2956// QVERIFY(!drr.isFinished());
2957// QVERIFY(!drr.start());
2958// QVERIFY(!drr.cancel());
2959// QVERIFY(!drr.waitForFinished());
2960
2961// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemDetailDefinitionRemoveRequest(\n* definitionNames=() ,\n* itemType=\"Event\",\n* errorMap=QMap() \n))");
2962// qDebug() << drr;
2963
2964
2965// // Testing the filled-in case
2966
2967// // specific definition removal
2968// QStringList removeIds;
2969// removeIds << oim->detailDefinitions(QOrganizerItemType::TypeEvent).keys().first();
2970// drr.setDefinitionName(oim->detailDefinitions(QOrganizerItemType::TypeEvent).keys().first());
2971// drr.setManager(oim.data());
2972// QCOMPARE(drr.manager(), oim.data());
2973// QVERIFY(!drr.isActive());
2974// QVERIFY(!drr.isFinished());
2975// QVERIFY(!drr.cancel());
2976// QVERIFY(!drr.waitForFinished());
2977// qRegisterMetaType<QOrganizerItemDetailDefinitionRemoveRequest*>("QOrganizerItemDetailDefinitionRemoveRequest*");
2978// QVERIFY(drr.definitionNames() == removeIds);
2979// QVERIFY(!drr.cancel()); // not started
2980// QVERIFY(drr.start());
2981
2982// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerItemDetailDefinitionRemoveRequest(\n* definitionNames=(\"AudibleReminder\") ,\n* itemType=\"Event\",\n* errorMap=QMap() \n))");
2983// qDebug() << drr;
2984
2985
2986// // Testing QOrganizerCollectionFetchRequest
2987
2988// // Testing the empty case
2989// QOrganizerCollectionFetchRequest cfr;
2990// QVERIFY(cfr.type() == QOrganizerAbstractRequest::CollectionFetchRequest);
2991
2992// // initial state - not started, no manager.
2993// QVERIFY(!cfr.isActive());
2994// QVERIFY(!cfr.isFinished());
2995// QVERIFY(!cfr.start());
2996// QVERIFY(!cfr.cancel());
2997// QVERIFY(!cfr.waitForFinished());
2998
2999// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerCollectionFetchRequest(collections=() ))");
3000// qDebug() << cfr;
3001
3002// // Testing the filled-in case
3003
3004// // retrieve all collections.
3005// cfr.setManager(oim.data());
3006// QCOMPARE(cfr.manager(), oim.data());
3007// QVERIFY(!cfr.isActive());
3008// QVERIFY(!cfr.isFinished());
3009// QVERIFY(!cfr.cancel());
3010// QVERIFY(!cfr.waitForFinished());
3011// qRegisterMetaType<QOrganizerCollectionFetchRequest*>("QOrganizerCollectionFetchRequest*");
3012// QVERIFY(!cfr.cancel()); // not started
3013
3014// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerCollectionFetchRequest(collections=() ))");
3015// qDebug() << cfr;
3016
3017
3018// // Testing QOrganizerCollectionRemoveRequest
3019
3020// // Testing the empty case
3021// QOrganizerCollectionRemoveRequest crr;
3022// QVERIFY(crr.type() == QOrganizerAbstractRequest::CollectionRemoveRequest);
3023
3024// // initial state - not started, no manager.
3025// QVERIFY(!crr.isActive());
3026// QVERIFY(!crr.isFinished());
3027// QVERIFY(!crr.start());
3028// QVERIFY(!crr.cancel());
3029// QVERIFY(!crr.waitForFinished());
3030
3031// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerCollectionRemoveRequest(collectionIds=() ,errorMap=QMap() ))");
3032// qDebug() << crr;
3033
3034// //Testing the filled-in case
3035
3036// // specific collection set
3037// QOrganizerCollectionId removeId = oim->collections().last().id();
3038// crr.setCollectionId(removeId);
3039// QVERIFY(crr.collectionIds() == QList<QOrganizerCollectionId>() << removeId);
3040// crr.setManager(oim.data());
3041// QCOMPARE(crr.manager(), oim.data());
3042// QVERIFY(!crr.isActive());
3043// QVERIFY(!crr.isFinished());
3044// QVERIFY(!crr.cancel());
3045// QVERIFY(!crr.waitForFinished());
3046// qRegisterMetaType<QOrganizerCollectionRemoveRequest*>("QOrganizerCollectionRemoveRequest*");
3047// QVERIFY(!crr.cancel()); // not started
3048// QVERIFY(crr.start());
3049// QVERIFY((crr.isActive() &&crr.state() == QOrganizerAbstractRequest::ActiveState) || crr.isFinished());
3050// //QVERIFY(crr.isFinished() || !crr.start()); // already started. // thread scheduling means this is untestable
3051// QVERIFY(crr.waitForFinished());
3052// QVERIFY(crr.isFinished());
3053
3054// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerCollectionRemoveRequest(collectionIds=(QOrganizerCollectionId(QOrganizerCollectionMemoryEngineId(2,\"qtorganizer:memory:id=tst_QOrganizerManager\"))) ,errorMap=QMap() ))");
3055// qDebug() << crr;
3056
3057
3058
3059// // Testing QOrganizerCollectionSaveRequest
3060
3061// // Testing the empty case
3062// QOrganizerCollectionSaveRequest csr;
3063// QVERIFY(csr.type() == QOrganizerAbstractRequest::CollectionSaveRequest);
3064
3065// // initial state - not started, no manager.
3066// QVERIFY(!csr.isActive());
3067// QVERIFY(!csr.isFinished());
3068// QVERIFY(!csr.start());
3069// QVERIFY(!csr.cancel());
3070// QVERIFY(!csr.waitForFinished());
3071
3072// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerCollectionSaveRequest(collections=() ,errorMap=QMap() ))");
3073// qDebug() << csr;
3074
3075// // Testing the filled-in case
3076
3077// // save a new item
3078// QOrganizerCollection testCollection;
3079// testCollection.setMetaData("description", "test description");
3080// testCollection.setMetaData(QOrganizerCollection::KeyName, "New collection");
3081// //saveList << testCollection;
3082// csr.setManager(oim.data());
3083// QCOMPARE(csr.manager(), oim.data());
3084// QVERIFY(!csr.isActive());
3085// QVERIFY(!csr.isFinished());
3086// QVERIFY(!csr.cancel());
3087// QVERIFY(!csr.waitForFinished());
3088// qRegisterMetaType<QOrganizerCollectionSaveRequest*>("QOrganizerCollectionSaveRequest*");
3089// csr.setCollection(testCollection);
3090
3091// QTest::ignoreMessage(QtDebugMsg, "QOrganizerAbstractRequest(QOrganizerCollectionSaveRequest(collections=(QOrganizerCollection(id=QOrganizerCollectionId((null)), \"Name\"=QVariant(QString, \"New collection\") , \"description\"=QVariant(QString, \"test description\") )) ,errorMap=QMap() ))");
3092// qDebug() << csr;
3093}
3094
3095void tst_QOrganizerItemAsync::resultsAvailableReceived()
3096{
3097 QOrganizerItemFetchRequest *req = qobject_cast<QOrganizerItemFetchRequest *>(object: QObject::sender());
3098 Q_ASSERT(req);
3099 m_resultsAvailableSlotThreadId = req->thread()->currentThreadId();
3100}
3101
3102void tst_QOrganizerItemAsync::addManagers(QStringList stringlist)
3103{
3104 QTest::addColumn<QString>(name: "uri");
3105
3106 // retrieve the list of available managers
3107 QStringList managers = QOrganizerManager::availableManagers();
3108
3109 // remove ones that we know will not pass
3110 if (!stringlist.contains(str: "invalid"))
3111 managers.removeAll(t: "invalid");
3112 if (!stringlist.contains(str: "maliciousplugin"))
3113 managers.removeAll(t: "maliciousplugin");
3114 if (!stringlist.contains(str: "testdummy"))
3115 managers.removeAll(t: "testdummy");
3116 if (!stringlist.contains(str: "skeleton"))
3117 managers.removeAll(t: "skeleton");
3118
3119 foreach(QString mgr, managers) {
3120 QMap<QString, QString> params;
3121 QTest::newRow(dataTag: QString("mgr='%1'").arg(a: mgr).toLatin1().constData()) << QOrganizerManager::buildUri(managerName: mgr, params);
3122 if (mgr == "memory") {
3123 params.insert(key: "id", value: "tst_QOrganizerManager");
3124 QTest::newRow(dataTag: QString("mgr='%1', params").arg(a: mgr).toLatin1().constData()) << QOrganizerManager::buildUri(managerName: mgr, params);
3125 }
3126 }
3127}
3128
3129QOrganizerManager* tst_QOrganizerItemAsync::prepareModel(const QString& managerUri)
3130{
3131 QOrganizerManager* oim = QOrganizerManager::fromUri(uri: managerUri);
3132
3133 // XXX TODO: ensure that this is the case:
3134 // there should be no items in the database.
3135 QList<QOrganizerItemId> toRemove = oim->itemIds();
3136 foreach (const QOrganizerItemId& removeId, toRemove)
3137 oim->removeItem(itemId: removeId);
3138
3139 QOrganizerEvent a, b, c;
3140 a.setDisplayLabel("event a");
3141 b.setDisplayLabel("event b");
3142 c.setDisplayLabel("event c");
3143
3144 QOrganizerItemDescription aDescriptionDetail;
3145 aDescriptionDetail.setDescription("A Description");
3146 a.saveDetail(detail: &aDescriptionDetail);
3147 QOrganizerItemDescription bDescriptionDetail;
3148 bDescriptionDetail.setDescription("B Description");
3149 b.saveDetail(detail: &bDescriptionDetail);
3150 QOrganizerItemDescription cDescriptionDetail;
3151 cDescriptionDetail.setDescription("C Description");
3152 c.saveDetail(detail: &cDescriptionDetail);
3153
3154 QOrganizerItemType aTypeDetail;
3155 aTypeDetail.setType(QOrganizerItemType::TypeEvent);
3156 a.saveDetail(detail: &aTypeDetail);
3157 QOrganizerItemType bTypeDetail;
3158 bTypeDetail.setType(QOrganizerItemType::TypeEvent);
3159 b.saveDetail(detail: &bTypeDetail);
3160 QOrganizerItemType cTypeDetail;
3161 cTypeDetail.setType(QOrganizerItemType::TypeEvent);
3162 c.saveDetail(detail: &cTypeDetail);
3163
3164 QOrganizerItemPriority priority;
3165 priority.setPriority(QOrganizerItemPriority::HighestPriority);
3166 c.saveDetail(detail: &priority);
3167 priority.setPriority(QOrganizerItemPriority::VeryHighPriority);
3168 b.saveDetail(detail: &priority);
3169 priority.setPriority(QOrganizerItemPriority::HighPriority);
3170 a.saveDetail(detail: &priority);
3171
3172 QOrganizerItemLocation loc;
3173 loc.setLabel("test location label");
3174 a.saveDetail(detail: &loc);
3175
3176 QSet<QDate> recurrenceDates;
3177 QDate currentDate = QDate::currentDate();
3178 recurrenceDates << currentDate << currentDate.addDays(days: 2) << currentDate.addDays(days: 4);
3179 b.setRecurrenceDates(recurrenceDates);
3180
3181 oim->saveItem(item: &a);
3182 oim->saveItem(item: &b);
3183 oim->saveItem(item: &c);
3184
3185 QOrganizerCollection testCollection;
3186 testCollection.setMetaData(key: QOrganizerCollection::KeyName, value: "Test Collection");
3187 testCollection.setMetaData(key: QOrganizerCollection::KeyDescription, value: "test collection");
3188 oim->saveCollection(collection: &testCollection);
3189
3190 return oim;
3191
3192 // TODO: cleanup once test is complete
3193}
3194
3195QTEST_MAIN(tst_QOrganizerItemAsync)
3196#include "tst_qorganizeritemasync.moc"
3197

source code of qtpim/tests/auto/organizer/qorganizeritemasync/unittest/tst_qorganizeritemasync.cpp