~ubuntu-branches/ubuntu/oneiric/kdepim/oneiric-updates

« back to all changes in this revision

Viewing changes to calendarsupport/next/tests/incidencechangertest.cpp

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2011-06-28 19:33:24 UTC
  • mfrom: (0.2.13) (0.1.13 sid)
  • Revision ID: package-import@ubuntu.com-20110628193324-8yvjs8sdv9rdoo6c
Tags: 4:4.7.0-0ubuntu1
* New upstream release
  - update install files
  - add missing kdepim-doc package to control file
  - Fix Vcs lines
  - kontact breaks/replaces korganizer << 4:4.6.80
  - tighten the dependency of kdepim-dev on libkdepim4 to fix lintian error

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (c) 2010 Sérgio Martins <iamsergio@gmail.com>
 
3
 
 
4
    This library is free software; you can redistribute it and/or modify it
 
5
    under the terms of the GNU Library General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or (at your
 
7
    option) any later version.
 
8
 
 
9
    This library is distributed in the hope that it will be useful, but WITHOUT
 
10
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
 
12
    License for more details.
 
13
 
 
14
    You should have received a copy of the GNU Library General Public License
 
15
    along with this library; see the file COPYING.LIB.  If not, write to the
 
16
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
    02110-1301, USA.
 
18
*/
 
19
 
 
20
#include <calendarsupport/utils.h>
 
21
#include <calendarsupport/calendar.h>
 
22
#include <calendarsupport/calendarmodel.h>
 
23
#include <calendarsupport/next/incidencechanger2.h>
 
24
 
 
25
#include <Akonadi/ChangeRecorder>
 
26
#include <Akonadi/Session>
 
27
#include <Akonadi/ItemFetchScope>
 
28
#include <akonadi/entitydisplayattribute.h>
 
29
#include <akonadi/agentinstance.h>
 
30
#include <akonadi/agentmanager.h>
 
31
#include <akonadi/collection.h>
 
32
#include <akonadi/collectionstatistics.h>
 
33
#include <akonadi/control.h>
 
34
#include <akonadi/itemcreatejob.h>
 
35
#include <akonadi/itemmodifyjob.h>
 
36
#include <akonadi/itemdeletejob.h>
 
37
#include <akonadi/collectionfetchjob.h>
 
38
#include <akonadi/collectionfetchscope.h>
 
39
#include <akonadi/qtest_akonadi.h>
 
40
 
 
41
#include <Akonadi/Item>
 
42
#include <Akonadi/Collection>
 
43
 
 
44
#include <KCalCore/Event>
 
45
#include <KCalCore/Journal>
 
46
#include <KCalCore/Todo>
 
47
 
 
48
#include <KSystemTimeZone>
 
49
 
 
50
#include <QtCore/QObject>
 
51
#include <QPushButton>
 
52
 
 
53
using namespace Akonadi;
 
54
using namespace KCalCore;
 
55
using namespace CalendarSupport;
 
56
 
 
57
class IncidenceChangerTest : public QObject
 
58
{
 
59
  Q_OBJECT
 
60
  Collection mCollection;
 
61
  CalendarModel *mCalendarModel;
 
62
  CalendarSupport::Calendar *mCalendar;
 
63
 
 
64
  // List of incidence uids.
 
65
  QStringList mPendingInsertsInETM;
 
66
  QStringList mPendingUpdatesInETM;
 
67
  QStringList mPendingDeletesInETM;
 
68
 
 
69
  bool mWaitingForIncidenceChangerSignals;
 
70
  IncidenceChanger2::ResultCode mExpectedResult;
 
71
  IncidenceChanger2 *mChanger;
 
72
 
 
73
  QSet<int> mKnownChangeIds;
 
74
 
 
75
  private slots:
 
76
    void initTestCase()
 
77
    {
 
78
      mWaitingForIncidenceChangerSignals = false;
 
79
      mExpectedResult = IncidenceChanger2::ResultCodeSuccess;
 
80
      //Control::start(); //TODO: uncomment when using testrunner
 
81
      qRegisterMetaType<CalendarSupport::IncidenceChanger2::ResultCode>("CalendarSupport::IncidenceChanger2::ResultCode");
 
82
      CollectionFetchJob *job = new CollectionFetchJob( Collection::root(),
 
83
                                                        CollectionFetchJob::Recursive,
 
84
                                                        this );
 
85
      // Get list of collections
 
86
      job->fetchScope().setContentMimeTypes( QStringList() << "application/x-vnd.akonadi.calendar.event" );
 
87
      AKVERIFYEXEC( job );
 
88
 
 
89
      // Find our collection
 
90
      Collection::List collections = job->collections();
 
91
      foreach( Collection collection, collections ) {
 
92
        if ( collection.name().startsWith( QLatin1String( "akonadi_ical_resource" ) ) ) {
 
93
          mCollection = collection;
 
94
          break;
 
95
        }
 
96
      }
 
97
 
 
98
      QVERIFY( mCollection.isValid() );
 
99
 
 
100
      // Setup our ETM
 
101
      Akonadi::Session *session = new Akonadi::Session( "KOrganizerETM", this );
 
102
      Akonadi::ChangeRecorder *monitor = new Akonadi::ChangeRecorder( this );
 
103
      Akonadi::ItemFetchScope scope;
 
104
      scope.fetchFullPayload( true );
 
105
      scope.fetchAttribute<Akonadi::EntityDisplayAttribute>();
 
106
      monitor->setSession( session );
 
107
      monitor->setCollectionMonitored( Akonadi::Collection::root() );
 
108
      monitor->fetchCollection( true );
 
109
      monitor->setItemFetchScope( scope );
 
110
      monitor->setMimeTypeMonitored( "text/calendar", true );
 
111
      monitor->setMimeTypeMonitored( KCalCore::Event::eventMimeType(), true );
 
112
      monitor->setMimeTypeMonitored( KCalCore::Todo::todoMimeType(), true );
 
113
      monitor->setMimeTypeMonitored( KCalCore::Journal::journalMimeType(), true );
 
114
      mCalendarModel = new CalendarSupport::CalendarModel( monitor, this );
 
115
 
 
116
      mCalendar = new CalendarSupport::Calendar( mCalendarModel,
 
117
                                                 mCalendarModel,
 
118
                                                 KSystemTimeZones::local() );
 
119
 
 
120
      mChanger = new IncidenceChanger2();
 
121
      mChanger->setShowDialogsOnError( false );
 
122
 
 
123
      connect( mChanger, SIGNAL(createFinished(int,Akonadi::Item,CalendarSupport::IncidenceChanger2::ResultCode,QString)),
 
124
               SLOT(createFinished(int,Akonadi::Item,CalendarSupport::IncidenceChanger2::ResultCode,QString)) );
 
125
 
 
126
      connect( mChanger, SIGNAL(deleteFinished(int,QVector<Akonadi::Item::Id>,CalendarSupport::IncidenceChanger2::ResultCode,QString)),
 
127
               SLOT(deleteFinished(int,QVector<Akonadi::Item::Id>,CalendarSupport::IncidenceChanger2::ResultCode,QString)) );
 
128
 
 
129
      connect( mChanger,SIGNAL(modifyFinished(int,Akonadi::Item,CalendarSupport::IncidenceChanger2::ResultCode,QString)),
 
130
               SLOT(modifyFinished(int,Akonadi::Item,CalendarSupport::IncidenceChanger2::ResultCode,QString)) );
 
131
 
 
132
      connect( mCalendarModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
 
133
               SLOT(rowsInserted(QModelIndex,int,int)) );
 
134
 
 
135
      connect( mCalendarModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
 
136
               SLOT(dataChanged(QModelIndex,QModelIndex)) );
 
137
 
 
138
      connect( mCalendarModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
 
139
               SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) );
 
140
    }
 
141
 
 
142
    void testCreating()
 
143
    {
 
144
      int changeId;
 
145
 
 
146
      { // Create 5 incidences, wait for the signal.
 
147
        for ( int i = 0; i < 5; ++i ) {
 
148
          const QString uid( "uid" + QString::number( i ) );
 
149
          const QString summary( "summary" + QString::number( i ) );
 
150
          Incidence::Ptr incidence( new Event() );
 
151
          incidence->setUid( uid );
 
152
          incidence->setSummary( summary );
 
153
          mPendingInsertsInETM.append( uid );
 
154
          changeId = mChanger->createIncidence( incidence,
 
155
                                                mCollection );
 
156
          QVERIFY( changeId != -1 );
 
157
          mKnownChangeIds.insert( changeId );
 
158
        }
 
159
        waitForSignals();
 
160
      }
 
161
 
 
162
      { // Invalid parameters
 
163
        changeId = mChanger->createIncidence( Incidence::Ptr(), // Invalid payload
 
164
                                              mCollection );
 
165
        QVERIFY( changeId == -1 );
 
166
        mKnownChangeIds.insert( changeId );
 
167
      }
 
168
 
 
169
      { // Invalid collections
 
170
 
 
171
 
 
172
      }
 
173
 
 
174
 
 
175
    }
 
176
 
 
177
    void testDeleting()
 
178
    {
 
179
      int changeId;
 
180
      const Item::List incidences = mCalendar->rawIncidences();
 
181
 
 
182
      { // Delete 5 incidences, previously created
 
183
        foreach( const Item &item, incidences ) {
 
184
          mPendingDeletesInETM.append( item.payload<Incidence::Ptr>()->uid() );
 
185
        }
 
186
        changeId = mChanger->deleteIncidences( incidences );
 
187
        mKnownChangeIds.insert( changeId );
 
188
        QVERIFY( changeId != -1 );
 
189
        waitForSignals();
 
190
      }
 
191
 
 
192
      { // Delete something already deleted
 
193
        mWaitingForIncidenceChangerSignals = true;
 
194
        changeId = mChanger->deleteIncidences( incidences );
 
195
        mKnownChangeIds.insert( changeId );
 
196
        QVERIFY( changeId != -1 );
 
197
        mExpectedResult = IncidenceChanger2::ResultCodeAlreadyDeleted;
 
198
        waitForSignals();
 
199
      }
 
200
 
 
201
      { // If we provide an empty list, a job won't be created
 
202
        changeId = mChanger->deleteIncidences( Item::List() );
 
203
        mKnownChangeIds.insert( changeId );
 
204
        QVERIFY( changeId == -1 );
 
205
      }
 
206
 
 
207
      { // If we provide a list with at least one invalid item, a job won't be created
 
208
        Item::List list;
 
209
        list << Item();
 
210
        changeId = mChanger->deleteIncidences( list );
 
211
        QVERIFY( changeId == -1 );
 
212
      }
 
213
 
 
214
    }
 
215
 
 
216
    void testModifying()
 
217
    {
 
218
      int changeId;
 
219
 
 
220
      // First create an incidence
 
221
      const QString uid( "uid");
 
222
      const QString summary( "summary");
 
223
      Incidence::Ptr incidence( new Event() );
 
224
      incidence->setUid( uid );
 
225
      incidence->setSummary( summary );
 
226
      mPendingInsertsInETM.append( uid );
 
227
      changeId = mChanger->createIncidence( incidence,
 
228
                                            mCollection );
 
229
      QVERIFY( changeId != -1 );
 
230
      mKnownChangeIds.insert( changeId );
 
231
      waitForSignals();
 
232
 
 
233
      { // Just a summary change
 
234
        Item item = mCalendar->itemForIncidenceUid( uid );
 
235
        QVERIFY( item.isValid() );
 
236
        item.payload<Incidence::Ptr>()->setSummary( "summary2" );
 
237
        mPendingUpdatesInETM.append( uid );
 
238
        changeId = mChanger->modifyIncidence( item );
 
239
        QVERIFY( changeId != -1 );
 
240
        mKnownChangeIds.insert( changeId );
 
241
        waitForSignals();
 
242
        item = mCalendar->itemForIncidenceUid( uid );
 
243
        QVERIFY( item.isValid() );
 
244
        QVERIFY( item.payload<Incidence::Ptr>()->summary() == "summary2" );
 
245
      }
 
246
 
 
247
      { // Invalid item
 
248
        changeId = mChanger->modifyIncidence( Item() );
 
249
        QVERIFY( changeId == -1 );
 
250
      }
 
251
 
 
252
      { // Delete it and try do modify it, should result in error
 
253
        Item item = mCalendar->itemForIncidenceUid( uid );
 
254
        QVERIFY( item.isValid() );
 
255
        mPendingDeletesInETM.append( uid );
 
256
        changeId = mChanger->deleteIncidence( item );
 
257
        QVERIFY( changeId != -1 );
 
258
        mKnownChangeIds.insert( changeId );
 
259
        waitForSignals();
 
260
 
 
261
        mWaitingForIncidenceChangerSignals = true;
 
262
        changeId = mChanger->modifyIncidence( item );
 
263
        mKnownChangeIds.insert( changeId );
 
264
        mExpectedResult = IncidenceChanger2::ResultCodeAlreadyDeleted;
 
265
        QVERIFY( changeId != -1 );
 
266
        waitForSignals();
 
267
      }
 
268
    }
 
269
 
 
270
    void testMassModifyForConflicts()
 
271
    {
 
272
      int changeId;
 
273
 
 
274
      // First create an incidence
 
275
      const QString uid( "uid");
 
276
      const QString summary( "summary");
 
277
      Incidence::Ptr incidence( new Event() );
 
278
      incidence->setUid( uid );
 
279
      incidence->setSummary( summary );
 
280
      mPendingInsertsInETM.append( uid );
 
281
      changeId = mChanger->createIncidence( incidence,
 
282
                                            mCollection );
 
283
      QVERIFY( changeId != -1 );
 
284
      mKnownChangeIds.insert( changeId );
 
285
      waitForSignals();
 
286
 
 
287
      kDebug() << "Doing 30 modifications, but waiting for jobs to end before starting a new one.";
 
288
      const int LIMIT = 30;
 
289
      for ( int i = 0; i < LIMIT; ++i ) {
 
290
        mWaitingForIncidenceChangerSignals = true;
 
291
        mPendingUpdatesInETM.append( uid );
 
292
        Item item = mCalendar->itemForIncidenceUid( uid );
 
293
        QVERIFY( item.isValid() );
 
294
        item.payload<Incidence::Ptr>()->setSummary( QString::number( i ) );
 
295
        int changeId = mChanger->modifyIncidence( item );
 
296
        QVERIFY( changeId > -1 );
 
297
        mKnownChangeIds.insert( changeId );
 
298
        waitForSignals();
 
299
      }
 
300
 
 
301
      Item item = mCalendar->itemForIncidenceUid( uid );
 
302
      QVERIFY( item.isValid() );
 
303
 
 
304
      kDebug() << "Doing 30 modifications, and not for jobs to end before starting a new one.";
 
305
 
 
306
      for ( int i = 0; i < LIMIT; ++i ) {
 
307
        item.payload<Incidence::Ptr>()->setSummary( QString::number( i ) );
 
308
        const int changeId = mChanger->modifyIncidence( item );
 
309
        QVERIFY( changeId > -1 );
 
310
        mKnownChangeIds.insert( changeId );
 
311
 
 
312
        if ( i == LIMIT-1 ) {
 
313
          // Let's catch the last signal, so we don't exit our test with jobs still running
 
314
          mWaitingForIncidenceChangerSignals = true;
 
315
        }
 
316
        QTest::qWait( 100 );
 
317
      }
 
318
      waitForSignals();
 
319
 
 
320
      // Cleanup, delete the incidence
 
321
      item = mCalendar->itemForIncidenceUid( uid );
 
322
      QVERIFY( item.isValid() );
 
323
      mPendingDeletesInETM.append( uid );
 
324
      changeId = mChanger->deleteIncidence( item );
 
325
      QVERIFY( changeId != -1 );
 
326
      mKnownChangeIds.insert( changeId );
 
327
      waitForSignals();
 
328
    }
 
329
 
 
330
  public Q_SLOTS:
 
331
 
 
332
    void waitForSignals()
 
333
    {
 
334
      while ( !mPendingInsertsInETM.isEmpty() ||
 
335
              !mPendingUpdatesInETM.isEmpty() ||
 
336
              !mPendingDeletesInETM.isEmpty() ||
 
337
              mWaitingForIncidenceChangerSignals ) {
 
338
        QTest::qWait( 1000 );
 
339
      }
 
340
    }
 
341
 
 
342
    void rowsInserted( const QModelIndex &index, int start, int end )
 
343
    {
 
344
      Item::List list = itemsFromModel( mCalendarModel, index, start, end );
 
345
 
 
346
      foreach( const Item &item, list ) {
 
347
        Incidence::Ptr incidence = CalendarSupport::incidence( item );
 
348
        if ( incidence && mPendingInsertsInETM.contains( incidence->uid() ) )
 
349
          mPendingInsertsInETM.removeAll( incidence->uid() );
 
350
      }
 
351
    }
 
352
 
 
353
    void dataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight )
 
354
    {
 
355
      Q_ASSERT( topLeft.row() <= bottomRight.row() );
 
356
      const int endRow = bottomRight.row();
 
357
      QModelIndex i( topLeft );
 
358
      int row = i.row();
 
359
      while ( row <= endRow ) {
 
360
        const Akonadi::Item item = itemFromIndex( i );
 
361
        if ( item.isValid() ) {
 
362
          Incidence::Ptr incidence = CalendarSupport::incidence( item );
 
363
          if ( incidence && mPendingUpdatesInETM.contains( incidence->uid() ) )
 
364
            mPendingUpdatesInETM.removeAll( incidence->uid() );
 
365
        }
 
366
        ++row;
 
367
        i = i.sibling( row, topLeft.column() );
 
368
      }
 
369
    }
 
370
 
 
371
    void rowsAboutToBeRemoved( const QModelIndex &index, int start, int end )
 
372
    {
 
373
      Item::List list = itemsFromModel( mCalendarModel, index, start, end );
 
374
      foreach( const Item &item, list ) {
 
375
        Incidence::Ptr incidence = CalendarSupport::incidence( item );
 
376
        if ( incidence && mPendingDeletesInETM.contains( incidence->uid() ) )
 
377
          mPendingDeletesInETM.removeAll( incidence->uid() );
 
378
      }
 
379
    }
 
380
 
 
381
  void deleteFinished( int changeId,
 
382
                       const QVector<Akonadi::Item::Id> &deletedIds,
 
383
                       CalendarSupport::IncidenceChanger2::ResultCode resultCode,
 
384
                       const QString &errorMessage )
 
385
  {
 
386
    Q_UNUSED( deletedIds );
 
387
    QVERIFY( mKnownChangeIds.contains( changeId ) );
 
388
    QVERIFY( changeId != -1 );
 
389
 
 
390
    if ( resultCode != IncidenceChanger2::ResultCodeSuccess ) {
 
391
      kDebug() << "Error string is " << errorMessage;
 
392
    } else {
 
393
      QVERIFY( !deletedIds.isEmpty() );
 
394
      foreach( Akonadi::Item::Id id , deletedIds ) {
 
395
        QVERIFY( id != -1 );
 
396
      }
 
397
    }
 
398
 
 
399
    QVERIFY( resultCode == mExpectedResult );
 
400
    mExpectedResult = IncidenceChanger2::ResultCodeSuccess;
 
401
    mWaitingForIncidenceChangerSignals = false;
 
402
  }
 
403
 
 
404
  void createFinished( int changeId,
 
405
                       const Akonadi::Item &item,
 
406
                       CalendarSupport::IncidenceChanger2::ResultCode resultCode,
 
407
                       const QString &errorString )
 
408
  {
 
409
    QVERIFY( mKnownChangeIds.contains( changeId ) );
 
410
    QVERIFY( changeId != -1 );
 
411
 
 
412
    if ( resultCode == IncidenceChanger2::ResultCodeSuccess ) {
 
413
      QVERIFY( item.isValid() );
 
414
      QVERIFY( item.parentCollection().isValid() );
 
415
    } else {
 
416
      kDebug() << "Error string is " << errorString;
 
417
    }
 
418
 
 
419
    QVERIFY( resultCode == mExpectedResult );
 
420
    mExpectedResult = IncidenceChanger2::ResultCodeSuccess;
 
421
    mWaitingForIncidenceChangerSignals = false;
 
422
  }
 
423
 
 
424
  void modifyFinished( int changeId,
 
425
                       const Akonadi::Item &item,
 
426
                       CalendarSupport::IncidenceChanger2::ResultCode resultCode,
 
427
                       const QString &errorString )
 
428
  {
 
429
    Q_UNUSED( item );
 
430
    QVERIFY( mKnownChangeIds.contains( changeId ) );
 
431
    QVERIFY( changeId != -1 );
 
432
 
 
433
    if ( resultCode == IncidenceChanger2::ResultCodeSuccess )
 
434
      QVERIFY( item.isValid() );
 
435
    else
 
436
      kDebug() << "Error string is " << errorString;
 
437
 
 
438
    QVERIFY( resultCode == mExpectedResult );
 
439
 
 
440
    mExpectedResult = IncidenceChanger2::ResultCodeSuccess;
 
441
    mWaitingForIncidenceChangerSignals = false;
 
442
  }
 
443
};
 
444
 
 
445
QTEST_AKONADIMAIN( IncidenceChangerTest, NoGUI )
 
446
 
 
447
#include "incidencechangertest.moc"