phonebookengines_old/contactsmodel/tsrc/T_LocalViewDuplicates.cpp
changeset 40 b46a585f6909
equal deleted inserted replaced
37:fd64c38c277d 40:b46a585f6909
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32test.h>
       
    17 #include <cntdef.h>
       
    18 #include <cntdb.h>
       
    19 #include <cntitem.h>
       
    20 #include <cntfield.h>
       
    21 #include <cntfldst.h>
       
    22 #include <cntviewbase.h>
       
    23 
       
    24 #include "cfixedqueue.h"
       
    25 #include "CContactViewEventQueue.h"
       
    26 
       
    27 _LIT(KTestName, "T_LocalViewDuplicates");
       
    28 
       
    29 _LIT(KTestDbName, "c:T_LocalViewDuplicates.cdb");
       
    30 
       
    31 LOCAL_D RTest test(KTestName);
       
    32 
       
    33 
       
    34 class CDbEventListener : public CTimer, public MContactDbObserver
       
    35     {
       
    36     public:
       
    37         static CDbEventListener* NewL
       
    38             (CContactDatabase& aDb, TInt aMaxQueueSize=128);
       
    39         ~CDbEventListener();
       
    40 
       
    41         /**
       
    42          * Waits for an event from the database.
       
    43          * @param aTimeOut  max time to wait for an event.
       
    44          * @param aEvent    the received event, undefined if this function returns false.
       
    45          * @return true if an event was received, false if timeout expired first.
       
    46          */
       
    47         TBool ListenForEvent(TTimeIntervalSeconds aTimeOut, TContactDbObserverEvent& aEvent);
       
    48 
       
    49         /**
       
    50          * Removes all previously arrvied events from the queue.
       
    51          */
       
    52         void Flush()
       
    53             {
       
    54             iEventQueue.Reset();
       
    55             }
       
    56 
       
    57     private:  // from CTimer
       
    58         void RunL();
       
    59 
       
    60     private:  // from MContactDbObserver
       
    61         void HandleDatabaseEventL(TContactDbObserverEvent aEvent);
       
    62 
       
    63     private:  // Implementation
       
    64         CDbEventListener();
       
    65         void ConstructL(CContactDatabase& aDb, TInt aMaxQueueSize);
       
    66 
       
    67     private:  // Data
       
    68         CContactChangeNotifier* iContactChangeNotifier;
       
    69         CFixedQueue<TContactDbObserverEvent> iEventQueue;
       
    70     };
       
    71 
       
    72 CDbEventListener* CDbEventListener::NewL
       
    73         (CContactDatabase& aDb, TInt aMaxQueueSize/*=128*/)
       
    74     {
       
    75     CDbEventListener* self = new(ELeave) CDbEventListener;
       
    76     CleanupStack::PushL(self);
       
    77     self->ConstructL(aDb,aMaxQueueSize);
       
    78     CleanupStack::Pop(self);
       
    79     return self;
       
    80     }
       
    81 
       
    82 CDbEventListener::~CDbEventListener()
       
    83     {
       
    84     delete iContactChangeNotifier;
       
    85     CTimer::Cancel();
       
    86     }
       
    87 
       
    88 TBool CDbEventListener::ListenForEvent(TTimeIntervalSeconds aTimeOut, TContactDbObserverEvent& aEvent)
       
    89     {
       
    90     CTimer::Cancel();
       
    91 
       
    92     if (iEventQueue.IsEmpty())
       
    93         {
       
    94         CTimer::After(aTimeOut.Int() * 1000000);
       
    95         // Keep execution here until the timer expires
       
    96         do  {
       
    97             CActiveScheduler::Start();
       
    98             }
       
    99         while (CTimer::IsActive());
       
   100         }
       
   101 
       
   102     if (!iEventQueue.IsEmpty())
       
   103         {
       
   104         aEvent = iEventQueue.Head();
       
   105         iEventQueue.PopHead();
       
   106         return ETrue;
       
   107         }
       
   108     else
       
   109         {
       
   110         return EFalse;
       
   111         }
       
   112     }
       
   113 
       
   114 void CDbEventListener::RunL()
       
   115     {
       
   116     // Timer expired
       
   117     CActiveScheduler::Stop();
       
   118     }
       
   119 
       
   120 void CDbEventListener::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
       
   121     {
       
   122     const TBool timerWasActive = CTimer::IsActive();
       
   123     CTimer::Cancel();
       
   124 	TBool eventPushed = iEventQueue.Push(aEvent);
       
   125     __ASSERT_ALWAYS(eventPushed,User::Invariant());
       
   126     if (timerWasActive)
       
   127         {
       
   128         CActiveScheduler::Stop();
       
   129         }
       
   130     }
       
   131 
       
   132 CDbEventListener::CDbEventListener()
       
   133     : CTimer(CActive::EPriorityStandard)
       
   134     {
       
   135     }
       
   136 
       
   137 void CDbEventListener::ConstructL
       
   138         (CContactDatabase& aDb, TInt aMaxQueueSize)
       
   139     {
       
   140     CTimer::ConstructL();
       
   141     CActiveScheduler::Add(this);
       
   142     iEventQueue.ConstructL(aMaxQueueSize);
       
   143     iContactChangeNotifier = CContactChangeNotifier::NewL(aDb, this);
       
   144     }
       
   145 
       
   146 class CTestResources : public CBase
       
   147     {
       
   148     public:
       
   149         static CTestResources* NewLC();
       
   150         void ConstructL();
       
   151         void CreateTestContactsL();
       
   152         ~CTestResources();
       
   153 
       
   154         CContactDatabase* iDb;
       
   155         CDbEventListener* iDbEventQueue;
       
   156         RContactViewSortOrder iViewSortOrder;
       
   157     };
       
   158 
       
   159 CTestResources* CTestResources::NewLC()
       
   160     {
       
   161     CTestResources* self = new(ELeave) CTestResources;
       
   162     CleanupStack::PushL(self);
       
   163     self->ConstructL();
       
   164     return self;
       
   165     }
       
   166 
       
   167 void CTestResources::ConstructL()
       
   168     {
       
   169     iDb = CContactDatabase::ReplaceL(KTestDbName);
       
   170     iDbEventQueue = CDbEventListener::NewL(*iDb);
       
   171     iViewSortOrder.AppendL(KUidContactFieldFamilyName);
       
   172     iViewSortOrder.AppendL(KUidContactFieldGivenName);
       
   173     iViewSortOrder.AppendL(KUidContactFieldCompanyName);
       
   174     }
       
   175 
       
   176 CTestResources::~CTestResources()
       
   177     {
       
   178     iViewSortOrder.Close();
       
   179     delete iDbEventQueue;
       
   180     delete iDb;
       
   181     TRAP_IGNORE(CContactDatabase::DeleteDatabaseL(KTestDbName));
       
   182     }
       
   183 
       
   184 LOCAL_C void CreateTestContactsL(CTestResources& aRes, TInt aCount)
       
   185     {
       
   186     for (TInt i=1; i <= aCount; ++i)
       
   187         {
       
   188         CContactCard* card = CContactCard::NewLC();
       
   189         CContactItemField* field = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName);
       
   190         TBuf<30> name;
       
   191         name.Format(_L("Contact%02d"), i);
       
   192         field->TextStorage()->SetTextL(name);
       
   193         card->AddFieldL(*field);
       
   194         CleanupStack::Pop(field);
       
   195         aRes.iDb->AddNewContactL(*card);
       
   196         CleanupStack::PopAndDestroy(card);
       
   197         }
       
   198     }
       
   199 
       
   200 LOCAL_C void EatDbEvents(CTestResources& aRes)
       
   201     {
       
   202     TContactDbObserverEvent event;
       
   203     while (aRes.iDbEventQueue->ListenForEvent(2,event))
       
   204         {
       
   205         }
       
   206     }
       
   207 
       
   208 LOCAL_C void TestNoDuplicatesL(const CContactViewBase& aView)
       
   209     {
       
   210     const TInt count = aView.CountL();
       
   211     for (TInt i=0; i < count; ++i)
       
   212         {
       
   213         const TContactItemId id = aView.AtL(i);
       
   214         for (TInt i2=i+1; i2 < count; ++i2)
       
   215             {
       
   216             test(aView.AtL(i2) != id);
       
   217             }
       
   218         }
       
   219     }
       
   220 
       
   221 LOCAL_C void TestOpenLocalViewL
       
   222         (CTestResources& aRes, TInt aCount)
       
   223     {
       
   224     // Create a local view on the DB
       
   225     CContactViewEventQueue* viewEvents = CContactViewEventQueue::NewL();
       
   226     CleanupStack::PushL(viewEvents);
       
   227     CContactLocalView* testView = CContactLocalView::NewL
       
   228         (*viewEvents, *aRes.iDb, aRes.iViewSortOrder, EContactsOnly);
       
   229     CleanupStack::PushL(testView);
       
   230 
       
   231     // Wait for the view to initialize
       
   232     TContactViewEvent event;
       
   233     test(viewEvents->ListenForEvent(10,event));
       
   234     test(event.iEventType == TContactViewEvent::EReady);
       
   235 
       
   236     // Check view count is correct
       
   237     test(testView->CountL() == aCount);
       
   238 
       
   239     // Check view doesn't contain any duplicates
       
   240     TestNoDuplicatesL(*testView);
       
   241 
       
   242     CleanupStack::PopAndDestroy(2,viewEvents);
       
   243     }
       
   244 
       
   245 // This test runs fine
       
   246 
       
   247 LOCAL_C void TestOpenLocalViewWithoutPendingEventsL()
       
   248     {
       
   249     test.Next(_L("Open local view with pending events from the DB FLUSHED"));
       
   250 
       
   251 
       
   252     CTestResources* res = CTestResources::NewLC();
       
   253     const TInt KContactCount = 10;
       
   254 
       
   255     // Create the test contacts
       
   256     CreateTestContactsL(*res, KContactCount);
       
   257 
       
   258     // Eat all outstanding DB events
       
   259     EatDbEvents(*res);
       
   260 
       
   261     // Open local view on the DB
       
   262     TestOpenLocalViewL(*res, KContactCount);
       
   263 
       
   264     CleanupStack::PopAndDestroy(res);
       
   265     }
       
   266 
       
   267 // This test fails: view contact count is 2*DB contact count, each contact is 
       
   268 // twice in the view!!!
       
   269 
       
   270 LOCAL_C void TestOpenLocalViewWithPendingEventsL()
       
   271     {
       
   272     test.Next(_L("Open local view with pending events from the DB NOT FLUSHED"));
       
   273 
       
   274 
       
   275     CTestResources* res = CTestResources::NewLC();
       
   276     const TInt KContactCount = 10;
       
   277 
       
   278     // Create the test contacts
       
   279     CreateTestContactsL(*res, KContactCount);
       
   280 
       
   281     // Don't Eat all outstanding DB events
       
   282     //EatDbEvents(*res);
       
   283 
       
   284     // Open local view on the DB
       
   285     TestOpenLocalViewL(*res, KContactCount);
       
   286 
       
   287     CleanupStack::PopAndDestroy(res);
       
   288     }
       
   289 
       
   290 /**
       
   291 
       
   292 @SYMTestCaseID     PIM-T-LOCALVIEWDUPLICATES-0001
       
   293 
       
   294 */
       
   295 
       
   296 void DoTestsL()
       
   297     {
       
   298 	test.Start(_L("@SYMTESTCaseID:PIM-T-LOCALVIEWDUPLICATES-0001 T_LocalViewDuplicates"));
       
   299 
       
   300 
       
   301     TestOpenLocalViewWithoutPendingEventsL();
       
   302     TestOpenLocalViewWithPendingEventsL();
       
   303 
       
   304     test.End();
       
   305     test.Close(); 
       
   306     }
       
   307 
       
   308 GLDEF_C TInt E32Main()
       
   309 	{
       
   310     // Init
       
   311     __UHEAP_MARK; 
       
   312 
       
   313     CTrapCleanup* cleanupStack = CTrapCleanup::New();
       
   314     if (!cleanupStack)
       
   315         {
       
   316         return KErrNoMemory;
       
   317         }
       
   318 
       
   319     CActiveScheduler* activeScheduler = new CActiveScheduler;
       
   320     if (!activeScheduler)
       
   321         {
       
   322         return KErrNoMemory;
       
   323         }
       
   324     CActiveScheduler::Install(activeScheduler);
       
   325 
       
   326     // Run the tests
       
   327     TRAPD(err, DoTestsL());
       
   328 
       
   329     // Cleanup
       
   330     delete activeScheduler;
       
   331     delete cleanupStack;
       
   332     __UHEAP_MARKEND;
       
   333 	return err;
       
   334     }