--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pimprotocols/phonebooksync/Test/TE_cntsync/te_cntsyncview.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,551 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests that PhBkSync adds contacts from USIM address books to the contacts database,
+// and that they appear correctly in the Contacts Model local view.
+//
+//
+
+#include <e32test.h>
+#include "te_cntsyncbase.h"
+#include "te_cntsyncview.h"
+#include <cntview.h>
+
+// Values for User::After()
+const TInt K1SecondWait(1000000);
+const TInt K5SecondWait(5*K1SecondWait);
+const TInt K20SecondWait(20*K1SecondWait);
+
+// Test config numbers...
+const TInt KNormalSIMTestConfig(0);
+const TInt KLockedSIMTestConfig(8);
+
+// Number of contacts on SIM cards
+const TInt KNumContactsNormalSIM(5);
+const TInt KNumContactsLockedSIM(25);
+
+class TViewCleanup
+ {
+ public:
+ TViewCleanup(CContactLocalView* aLocalView, CContactViewEventWait* aViewWaitEvent)
+ {
+ iLocalView = aLocalView;
+ iViewWaitEvent = aViewWaitEvent;
+ }
+ CContactViewEventWait* iViewWaitEvent;
+ CContactLocalView* iLocalView;
+ };
+
+static void ViewCleanup(TAny* aPointer)
+ {
+ TViewCleanup* cleanup = static_cast<TViewCleanup*> (aPointer);
+ CContactLocalView* iLocalView = cleanup->iLocalView;
+ CContactViewEventWait* iViewWaitEvent = cleanup->iViewWaitEvent;
+ iLocalView->Close(*iViewWaitEvent);
+ delete iViewWaitEvent;
+ }
+
+/**
+ * Factory construction method.
+ * @return Pointer to CPhbkViewICCSyncTest object
+ */
+CPhbkViewICCSyncTest* CPhbkViewICCSyncTest::NewL()
+ {
+ CPhbkViewICCSyncTest* self = new(ELeave) CPhbkViewICCSyncTest();
+ return self;
+ }
+
+/**
+ * Default constructor. Each test step initialises it's own name.
+ */
+CPhbkViewICCSyncTest::CPhbkViewICCSyncTest()
+ {
+ SetTestStepName(_L("ViewICCSyncTest"));
+ }
+
+/**
+ * Synchronisation of normal, unlocked, ICC. Creates a Contacts View
+ * with ICC entries only.
+ */
+enum TVerdict CPhbkViewICCSyncTest::doTestStepL()
+ {
+ SetSimTsyTestNumberL(0);
+ DoSyncL();
+
+ // all View tests use Manual Sync mode
+ User::LeaveIfError(iSession.SetSyncMode(RPhoneBookSession::EManual)); // Set mode to manual to avoid getting KErrInUse
+ CheckSyncModeL(RPhoneBookSession::EManual);
+
+ // ICC unlocked
+ SetSimTsyTestNumberL(KNormalSIMTestConfig);
+ CleanupClosePushL(iViewSortOrder);
+
+ // A sort order (only Family Name is present in ADN phonebooks)
+ iViewSortOrder.AppendL(KUidContactFieldFamilyName);
+ iViewSortOrder.AppendL(KUidContactFieldGivenName);
+ iViewSortOrder.AppendL(KUidContactFieldCompanyName);
+
+ // Helper class that gives timed wait for View events
+ CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL();
+ CleanupStack::PushL(viewEventWait);
+
+ // View with just ICC entries
+ iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesOnly);
+
+ CleanupStack::Pop();//viewEventWait will be deleted with cleanup below
+ TViewCleanup cleanup(iIccView, viewEventWait);
+ CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup));
+
+ INFO_PRINTF1(_L(" Manual Sync"));
+ // do manual synchronisation
+ DoSyncL();
+ WaitForSyncToCompleteL();
+
+ // let view catch up, waits 2s
+ INFO_PRINTF1(_L(" Wait for ICC view to become ready"));
+ // Wait 30s for View Event: EReady or ESortOrderChanged only
+ TBool eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse);
+ // check that event was received
+ TESTCHECKCONDITIONL(eventReceived);
+ TESTCHECKL(iEvent.iEventType, TContactViewEvent::EReady);
+
+ INFO_PRINTF1(_L(" Check all PhoneBook entries are in view"));
+ TInt count = iIccView->CountL();
+ if (count != KNumContactsNormalSIM)
+ {
+ INFO_PRINTF3(_L(" Expecting %d entries in View but found %d:"),
+ KNumContactsNormalSIM, count);
+ DumpICCViewL();
+ }
+ TESTCHECK(count, KNumContactsNormalSIM);
+
+ User::After(K5SecondWait);
+ CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder
+
+ return TestStepResult();
+ }
+
+
+/**
+ * Factory construction method.
+ * @return Pointer to CPhbkViewICCLockedICCTest object
+ */
+CPhbkViewICCLockedICCTest* CPhbkViewICCLockedICCTest::NewL()
+ {
+ CPhbkViewICCLockedICCTest* self = new(ELeave) CPhbkViewICCLockedICCTest();
+ return self;
+ }
+
+/**
+ * Default constructor. Each test step initialises it's own name.
+ */
+CPhbkViewICCLockedICCTest::CPhbkViewICCLockedICCTest()
+ {
+ SetTestStepName(_L("ViewICCLockedICCTest"));
+ }
+
+/**
+ * Synchronisation when ICC is locked. Creates a Contacts View of ICC entries
+ * only.
+ *
+ * Synchroniser is initially unable to perform synchronisation because ICC is locked. The
+ * Local View class recognises that the ICC is locked, and creates an empty View.
+ *
+ * When ICC becomes unlocked the synchronisation completes successfully. The Contacts Local
+ * View sees this, and re-sorts itself making the ICC entries appear in the View.
+ */
+enum TVerdict CPhbkViewICCLockedICCTest::doTestStepL()
+ {
+ // ICC locked, so initial Synchronisation is not carried out
+ SetSimTsyTestNumberL(KLockedSIMTestConfig);
+ CleanupClosePushL(iViewSortOrder);
+ // A sort order (only Family Name is present in ADN phonebooks)
+ iViewSortOrder.AppendL(KUidContactFieldFamilyName);
+ iViewSortOrder.AppendL(KUidContactFieldGivenName);
+ iViewSortOrder.AppendL(KUidContactFieldCompanyName);
+
+ // Helper class that gives timed wait for View events
+ CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL();
+ CleanupStack::PushL(viewEventWait);
+
+ // View with just ICC entries
+ iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesOnly);
+ CleanupStack::Pop();//viewEventWait will be deleted with cleanup below
+ TViewCleanup cleanup(iIccView, viewEventWait);
+ CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup));
+
+ INFO_PRINTF1(_L(" Initial Sync Failure"));
+ // check that ICC is locked
+ TRAPD(err, DoSyncFailL());
+ if(err == KErrGeneral)
+ {
+ INFO_PRINTF1(_L("The view has already been created before we attempt to sync, so sync won't fail. We should finsh test here"));
+ SetTestStepResult(EPass);
+ CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder
+ return TestStepResult();
+ }
+ TESTCHECKL(err, KErrNone);
+ User::After(K1SecondWait);
+
+ RPhoneBookSession::TSyncState state;
+ iSession.GetPhoneBookCacheState(state);
+
+ TESTCHECKL(state, RPhoneBookSession::EErrorDuringSync); // Cache not in valid state
+
+ iSession.GetLastSyncError(err);
+ TESTCHECKL(err, KErrAccessDenied); // ICC locked
+
+ // initially ready with no entries as ICC (SIM) card is not ready, waits 2s
+ INFO_PRINTF1(_L(" Check View becomes ready with no entries"));
+ // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only
+ TBool eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse);
+ // check that event was received
+ TESTCHECKCONDITIONL(eventReceived);
+
+ TESTCHECKL(iEvent.iEventType, TContactViewEvent::EReady);
+ TESTCHECKL(iIccView->CountL(), 0); // view should be empty
+
+ // wait for ICC to become unlocked
+ INFO_PRINTF1(_L(" Start Sync when ICC becomes unlocked"));
+ User::After(K20SecondWait); // ICC should become unlocked now
+ DoSyncL();
+ WaitForSyncToCompleteL();
+
+ // let the view catch up, waits 2s
+ INFO_PRINTF1(_L(" Wait for View to Re-Sort with ICC entries"));
+ // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only
+ eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse);
+ // check that event was received
+ TESTCHECKCONDITIONL(eventReceived);
+
+ INFO_PRINTF1(_L(" Contacts View should be resorted"));
+ TESTCHECKL(iEvent.iEventType, TContactViewEvent::ESortOrderChanged);
+
+ INFO_PRINTF1(_L(" Check all PhoneBook entries are in view"));
+ TInt count = iIccView->CountL();
+ if (count != KNumContactsLockedSIM)
+ {
+ INFO_PRINTF3(_L(" Expecting %d entries in View but found %d:"),
+ KNumContactsLockedSIM, count);
+ DumpICCViewL();
+ }
+ TESTCHECK(count, KNumContactsLockedSIM);
+
+ User::After(K5SecondWait);
+ CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder
+
+ return TestStepResult();
+ }
+
+
+/**
+ * Factory construction method.
+ * @return Pointer to CPhbkViewICCLockedMixedTest object
+ */
+CPhbkViewICCLockedMixedTest* CPhbkViewICCLockedMixedTest::NewL()
+ {
+ CPhbkViewICCLockedMixedTest* self = new(ELeave) CPhbkViewICCLockedMixedTest();
+ return self;
+ }
+
+/**
+ * Default constructor. Each test step initialises it's own name.
+ */
+CPhbkViewICCLockedMixedTest::CPhbkViewICCLockedMixedTest()
+ {
+ SetTestStepName(_L("ViewICCLockedMixedTest"));
+ }
+
+/**
+ * Synchronisation when ICC is locked. Creates a Contacts View of Contacts
+ * and ICC entries. This is similar to the ICC entries only test, but timing
+ * and behaviour of Contacts model is different.
+ *
+ * Synchroniser is initially unable to perform synchronisation because ICC is locked. The
+ * Local View class recognises that the ICC is locked, and creates a View without ICC entries.
+ *
+ * When ICC becomes unlocked the synchronisation completes successfully. The Contacts Local
+ * View sees this, and re-sorts itself making the ICC entries appear in the View.
+ */
+enum TVerdict CPhbkViewICCLockedMixedTest::doTestStepL()
+ {
+ // ICC locked, so initial Synchronisation is not carried out
+ SetSimTsyTestNumberL(KLockedSIMTestConfig);
+ CleanupClosePushL(iViewSortOrder);
+
+ // A sort order (only Family Name is present in ADN phonebooks)
+ iViewSortOrder.AppendL(KUidContactFieldFamilyName);
+ iViewSortOrder.AppendL(KUidContactFieldGivenName);
+ iViewSortOrder.AppendL(KUidContactFieldCompanyName);
+
+ // Helper class that gives timed wait for View events
+ CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL();
+ CleanupStack::PushL(viewEventWait);
+
+ // View with ICC entries and contacts
+ iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesAndContacts);
+
+ CleanupStack::Pop();//viewEventWait will be deleted with cleanup below
+ TViewCleanup cleanup(iIccView, viewEventWait);
+ CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup));
+
+ INFO_PRINTF1(_L(" Initial Sync Failure"));
+ // check that ICC is locked
+ TRAPD(err, DoSyncFailL());
+ if(err == KErrGeneral)
+ {
+ INFO_PRINTF1(_L("The view has already been created before we attempt to sync, so sync won't fail. We should finsh test here"));
+ SetTestStepResult(EPass);
+ CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder
+ return TestStepResult();
+ }
+ TESTCHECKL(err, KErrNone);
+ User::After(K1SecondWait);
+
+ RPhoneBookSession::TSyncState state;
+ iSession.GetPhoneBookCacheState(state);
+
+ TESTCHECKL(state, RPhoneBookSession::EErrorDuringSync); // Cache not in valid state
+
+ iSession.GetLastSyncError(err);
+ TESTCHECKL(err, KErrAccessDenied); // ICC locked
+
+ // initially ready with no entries as ICC (SIM) card is not ready, waits 2s
+ INFO_PRINTF1(_L(" Check View becomes ready without ICC entries"));
+ // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only
+ TBool eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse);
+ // check that event was received
+ TESTCHECKCONDITIONL(eventReceived);
+
+ TESTCHECKL(iEvent.iEventType, TContactViewEvent::EReady);
+ TESTCHECKL(iIccView->CountL(), 0); // view should be empty
+
+ // wait for ICC to become unlocked
+ INFO_PRINTF1(_L(" Start Sync when ICC becomes unlocked"));
+ User::After(K20SecondWait); // ICC should become unlocked now
+ DoSyncL();
+ WaitForSyncToCompleteL();
+
+ // let the view catch up, waits 2s
+ INFO_PRINTF1(_L(" Wait for View to Re-Sort with ICC entries"));
+ // Wait 30seconds at max for View Event: EReady or ESortOrderChanged only
+ eventReceived = viewEventWait->WaitForViewEvent(iIccView, 30, iEvent, EFalse);
+ // check that event was received
+ TESTCHECKCONDITIONL(eventReceived);
+
+ INFO_PRINTF1(_L(" Contacts View should be resorted"));
+ TESTCHECKL(iEvent.iEventType, TContactViewEvent::ESortOrderChanged);
+
+ INFO_PRINTF1(_L(" Check all PhoneBook entries are in view"));
+ TInt count = iIccView->CountL();
+ if (count != KNumContactsLockedSIM)
+ {
+ INFO_PRINTF3(_L(" Expecting %d entries in View but found %d:"),
+ KNumContactsLockedSIM, count);
+ DumpICCViewL();
+ }
+ TESTCHECK(count, KNumContactsLockedSIM);
+
+ User::After(K5SecondWait);
+ CleanupStack::PopAndDestroy(2);//iIccView, viewEventWait and iViewSortOrder
+ return TestStepResult();
+ }
+
+
+/**
+ * Synchronisation and create a view when just one phonebook exists. Previously
+ * a defect existed which would fail if no FDN phonebook was defined.
+ */
+enum TVerdict CPhbkViewICCSinglePhonebookTest::doTestStepL()
+ {
+ SetSimTsyTestNumberL(30);
+
+ //
+ // Setup a sort order (only Family Name is present in ADN phonebooks)
+ //
+ INFO_PRINTF1(_L("Setup a sort order (only Family Name is present in ADN phonebooks)"));
+ CleanupClosePushL(iViewSortOrder);
+ iViewSortOrder.AppendL(KUidContactFieldFamilyName);
+ iViewSortOrder.AppendL(KUidContactFieldGivenName);
+ iViewSortOrder.AppendL(KUidContactFieldCompanyName);
+
+ //
+ // Helper class that gives timed wait for View events
+ //
+ CContactViewEventWait *viewEventWait = CContactViewEventWait::NewL();
+ CleanupStack::PushL(viewEventWait);
+
+ //
+ // Create a view with ICC entries and contacts
+ //
+ INFO_PRINTF1(_L("Create a view with ICC entries and contacts"));
+ iIccView = CContactLocalView::NewL(*viewEventWait, *iDb, iViewSortOrder, EICCEntriesAndContacts);
+
+ CleanupStack::Pop();//viewEventWait will be deleted with cleanup below
+ TViewCleanup cleanup(iIccView, viewEventWait);
+ CleanupStack::PushL(TCleanupItem(ViewCleanup, &cleanup));
+
+ //
+ // Sync ADN phonebook...
+ //
+ INFO_PRINTF1(_L(" Sync ADN phonebook..."));
+ TRequestStatus status;
+
+ iSession.DoSynchronisation(status, KUidIccGlobalAdnPhonebook);
+ User::WaitForRequest(status);
+ TESTCHECKL(status.Int(), KErrNone);
+
+ //
+ // Close view and clean up...
+ //
+ INFO_PRINTF1(_L(" Close view and clean up..."));
+ CleanupStack::PopAndDestroy(2);
+
+ return TestStepResult();
+ } // CPhbkViewICCSinglePhonebookTest::doTestStepL
+
+
+void CPhbkSyncViewIntegrationTestBase::DumpICCViewL()
+ {
+ const TInt count = iIccView->CountL();
+
+ if (count == 0)
+ {
+ INFO_PRINTF1(_L(" No contacts to list."));
+ return;
+ }
+
+ CContactItem* contact = NULL;
+ TInt index;
+
+ for (index = 0; index < count; index++)
+ {
+ const CViewContact& viewContact = iIccView->ContactAtL(index);
+ const TInt id = viewContact.Id();
+
+ // get actual Contact from DB
+ contact = iDb->ReadMinimalContactLC(id);
+
+ // Get & print Contact's phone number
+ CContactItemFieldSet& fieldset = contact->CardFields();
+ // look for Phone Number field in record
+ const TInt pos = fieldset.Find(KUidContactFieldPhoneNumber);
+ User::LeaveIfError(pos); // field must be present
+ CContactItemField& field = fieldset[pos];
+ CContactTextField* textfield = field.TextStorage();
+
+ TBuf<128> outputString;
+ outputString.AppendFormat(_L(" [%04i] Id=%04i Name=\""), index+1, id);
+ outputString.Append(viewContact.Field(0));
+ outputString.AppendFormat(_L("\" Number=\""));
+ outputString.Append(textfield->Text());
+ outputString.AppendFormat(_L("\""));
+ INFO_PRINTF1(outputString);
+
+ CleanupStack::PopAndDestroy(contact);
+ contact = NULL;
+ }
+ }
+
+// support class implementation, timed wait for View Event; (based on CContactViewEventQueue)
+
+CContactViewEventWait* CContactViewEventWait::NewL()
+ {
+ CContactViewEventWait* self = new(ELeave) CContactViewEventWait;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+CContactViewEventWait::~CContactViewEventWait()
+ {
+ CTimer::Cancel();
+ if (iView) iView->Close(*this);
+ }
+
+
+/**
+ * Waits for an event from the database.
+ *
+ * @param aView Contact view to listen for events.
+ * @param aTimeOut Max time to wait for an event.
+ * @param aEvent The received event, undefined if this function returns false.
+ * @param aWaitForAny ETrue if wait is for any event, EFalse for view ready events only
+ *
+ * @return true if an event was received, false if timeout expired first.
+ */
+TBool CContactViewEventWait::WaitForViewEvent(CContactViewBase* aView,
+ TTimeIntervalSeconds aTimeOut,
+ TContactViewEvent& aEvent,
+ TBool aWaitForAny)
+ {
+ iView = aView;
+ iWaitForAny = aWaitForAny;
+ iTimedOut = EFalse;
+ CTimer::After(aTimeOut.Int() * 1000000);
+
+ // wait for timer to finish or desired View event
+ CActiveScheduler::Start();
+
+ if (!iTimedOut)
+ {
+ aEvent = iEvent;
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+
+void CContactViewEventWait::RunL()
+ {
+ // Timer expired
+ iTimedOut = ETrue;
+ CActiveScheduler::Stop();
+ }
+
+
+void CContactViewEventWait::HandleContactViewEvent(const CContactViewBase& aView,
+ const TContactViewEvent& aEvent)
+ {
+ __ASSERT_ALWAYS(iView == &aView, User::Invariant());
+
+ // either waiting for Any event, or Ready or Ready after Re-sort
+ if(iWaitForAny || aEvent.iEventType == TContactViewEvent::EReady ||
+ aEvent.iEventType == TContactViewEvent::ESortOrderChanged)
+ {
+ iEvent = aEvent;
+
+ CTimer::Cancel();
+ CActiveScheduler::Stop();
+ }
+ }
+
+
+CContactViewEventWait::CContactViewEventWait()
+ : CTimer(CActive::EPriorityStandard)
+ {
+ }
+
+
+void CContactViewEventWait::ConstructL()
+ {
+ CTimer::ConstructL();
+ CActiveScheduler::Add(this);
+ iView = NULL;
+ }
+