diff -r 000000000000 -r e686773b3f54 phonebookengines/contactsmodel/tsrc/T_OwnCardDelete.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines/contactsmodel/tsrc/T_OwnCardDelete.CPP Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,516 @@ +// Copyright (c) 2007-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: +// + +#include +#include +#include +#include +#include +#include +#include +#include "t_utils2.h" +#include "T_UTILS.H" +#include + +LOCAL_D TInt ThreadFunction(TAny*); + +_LIT(KDatabaseFileName, "C:T_OwnCardDelete"); +_LIT(KOwnCardMutex, "OwnCardMutex"); +_LIT(KOwnCard, "OwnCard"); +_LIT(KThreadFunc, "ThreadFunc"); + +const TInt KTotalContacts = 4; +const TInt KTimeout = 2000000; + +LOCAL_D TInt gEventCounter = 0; +LOCAL_D TInt gUnknownEventCounter = 0; +// Add*KTotalContacts + 1*OwnCardChanged + 1*UnknownChanges + OwnCardDeleted +const TInt KMaxNumOfEvents = KTotalContacts + 3; +const TInt KMaxUnknownEvents = 1; + + +class RTestPtr + { +public: + RTestPtr(RTest* aPtr) : iPtr(aPtr) + { + } + ~RTestPtr() + { + iPtr->Close(); + delete iPtr; + } + RTest* operator->() + { + return iPtr; + } + RTest& Ref() + { + return *iPtr; + } +private: + RTest* iPtr; + }; + + +class CMyObserver : public CActive, public MContactDbObserver + { +public: + CMyObserver() : CActive(EPriorityIdle) + { + iStart.UniversalTime(); + } + void Activate(); + +private: // From CActive. + void RunL(); + void DoCancel(); + TInt RunError(TInt aError); + +private: // From MContactDbObserver + void HandleDatabaseEventL(TContactDbObserverEvent aEvent); + +private: + TTime iStart; + TTime iEnd; + }; + +void CMyObserver::RunL() + { + iEnd.UniversalTime(); + // Timeout has been excedeed, stop waiting + if( iEnd.MicroSecondsFrom(iStart.Int64()) > KTimeout ) + { + CActiveScheduler::Stop(); + } + else // Waiting for next event + { + Activate(); + } + } + +void CMyObserver::DoCancel() + { + } + +TInt CMyObserver::RunError(TInt aError) + { + return aError; + } + +void CMyObserver::Activate() + { + if(!IsActive()) + { + TRequestStatus* pS = &iStatus; + User::RequestComplete(pS, KErrNone); + SetActive(); + } + } + + +void CMyObserver::HandleDatabaseEventL(TContactDbObserverEvent aEvent) + { + switch( aEvent.iType ) + { + case EContactDbObserverEventUnknownChanges: + { + gUnknownEventCounter++; + }break; + default: + { + Activate(); + break; + } + } + gEventCounter++; + } + + +LOCAL_C void WaitForNotificationsL(CContactDatabase* aDb) + { + CMyObserver* observer = new (ELeave) CMyObserver(); + CleanupStack::PushL(observer); + CContactChangeNotifier* notifier = CContactChangeNotifier::NewL(*aDb, observer); + CleanupStack::PushL(notifier); + CActiveScheduler::Add(observer); + observer->Activate(); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(notifier); + CleanupStack::PopAndDestroy(observer); + } + + +LOCAL_C void DeleteMultipleContactsL(CContactDatabase* aDb) + { + CContactIdArray* idArray = aDb->ContactsChangedSinceL(TTime(0)); + CleanupStack::PushL(idArray); + aDb->DeleteContactsL(*idArray); + CleanupStack::PopAndDestroy(idArray); + } + +LOCAL_C void DeleteOwnContactL(CContactDatabase* aDb) + { + TContactItemId contactId = aDb->OwnCardId(); + aDb->DeleteContactL(contactId); + } + + +LOCAL_C void TestSetOwnCardL(CContactDatabase* aDb) + { + CContactIdArray* idArray = aDb->ContactsChangedSinceL(TTime(0)); + CleanupStack::PushL(idArray); + TInt count = idArray->Count(); + if (count > 0) + { + TInt someIndex(0); //Make the first contact own contact + TContactItemId id = (*idArray)[someIndex]; + CContactItem* item = aDb->ReadContactLC(id); // take ownership of item + aDb->SetOwnCardL(*item); + CleanupStack::PopAndDestroy(item); + } + CleanupStack::PopAndDestroy(idArray); + } + + +LOCAL_C void PopulateDatabaseL(CContactDatabase* aDb, TInt aCntCount) + { + CRandomContactGenerator* randomCnt = CRandomContactGenerator::NewL(); + CleanupStack::PushL(randomCnt); + randomCnt->SetDbL(*aDb); + for (TInt i = 0; i < aCntCount; ++i) + { + randomCnt->AddTypicalRandomContactL(); + } + CleanupStack::PopAndDestroy(randomCnt); + } + + +LOCAL_D void SwitchToMainThread(RMutex& aMutex) + { + RThread::Rendezvous(KErrNone); + aMutex.Wait(); + aMutex.Signal(); + User::After(10); + } + + +LOCAL_D void SwitchToWorkerThread(RMutex& aMutex, RThread& aThread, TBool aSignal, TBool aWait) + { + if (aSignal) + { + aMutex.Signal(); + User::After(10); + } + + if (aWait) + { + aMutex.Wait(); + } + + TRequestStatus status; + aThread.Rendezvous(status); + + + User::WaitForRequest(status); + } + +LOCAL_D void ThreadFirstTestL(RTest& aTest) + { + aTest.Next(_L("-- Running worker thread --")); + + + RMutex mutex; + TInt errMutex = mutex.OpenGlobal(KOwnCardMutex); + User::LeaveIfError(errMutex); + CleanupClosePushL(mutex); + + aTest.Printf(_L("Replacing the database \n")); + CContactDatabase* db = CContactDatabase::ReplaceL(KDatabaseFileName); + CleanupStack::PushL(db); + + // get a second database object + CContactDatabase* dbAnother = CContactDatabase::OpenL(KDatabaseFileName); + CleanupStack::PushL(dbAnother); + + SwitchToMainThread(mutex); // 1) Back to MT-a + + // + // Main thread has now opened the database + // + + aTest.Printf(_L("Populating the database \n")); + PopulateDatabaseL(db, KTotalContacts); + WaitForNotificationsL(db); + + aTest.Printf(_L("Set the Own card id \n")); + TestSetOwnCardL(db); + WaitForNotificationsL(db); + + aTest.Printf(_L("Checking count value \n")); + TInt count = db->CountL(); + TInt countAnother = dbAnother->CountL(); + aTest.Printf(_L("Count: %d \n"), count ); + aTest(count == KTotalContacts && countAnother == KTotalContacts, __LINE__); + + aTest.Printf(_L("Checking the id \n")); + TContactItemId id = db->OwnCardId(); + TContactItemId idCopy = dbAnother->OwnCardId(); + aTest.Printf(_L("Id: %d \n"), id); + aTest(id != KNullContactId && idCopy != KNullContactId, __LINE__); + + SwitchToMainThread(mutex); // 2) Back to MT-b + + // + // Main thread has now checked the added values + // + + DeleteMultipleContactsL(db); + WaitForNotificationsL(db); + + aTest.Printf(_L("Checking deleted count value \n")); + count = db->CountL(); + countAnother = dbAnother->CountL(); + aTest.Printf(_L("Count: %d \n"), count ); + aTest(count == 0 && countAnother == 0, __LINE__); + + aTest.Printf(_L("Checking the deleted id \n")); + id = db->OwnCardId(); + idCopy = dbAnother->OwnCardId(); + aTest.Printf(_L("Id: %d \n"), id); + aTest(id == KNullContactId && idCopy == KNullContactId, __LINE__); + + SwitchToMainThread(mutex); // 3) Back to MT-c + + // + // Main thread has now checked the deleted values + // + + CleanupStack::PopAndDestroy(dbAnother); + CleanupStack::PopAndDestroy(db); + CleanupStack::PopAndDestroy(); // close mutex handle + + RThread::Rendezvous(KErrNone); // Finish) back to MT-d + } + +LOCAL_D void TestSecondL(RTest& aTest) + { + aTest.Next(_L("-- Second Owncard Test --")); + + + RMutex mtx; + TInt errMutex = mtx.CreateGlobal(KOwnCardMutex); + User::LeaveIfError(errMutex); + CleanupClosePushL(mtx); + + RThread thd; + aTest.Printf(_L("Creating worker thread \n")); + TInt errThread = thd.Create(KThreadFunc, ThreadFunction, KDefaultStackSize, KDefaultStackSize*20, KDefaultStackSize*40, NULL); + User::LeaveIfError(errThread); + CleanupClosePushL(thd); + thd.Resume(); + + SwitchToWorkerThread(mtx, thd, EFalse, ETrue); // a) Run: WT-start to WT-1 + + // + // Worker thread has now replaced the database + // + + aTest.Printf(_L("Open existing database \n")); + CContactDatabase* db = CContactDatabase::OpenL(KDatabaseFileName); + CleanupStack::PushL(db); + + SwitchToWorkerThread(mtx, thd, ETrue, ETrue); // b) Run: WT-1 to WT-2 + + // + // Worker thread has now added the contacts + // + + WaitForNotificationsL(db); + + aTest.Printf(_L("Checking db count \n")); + TInt count = db->CountL(); + aTest.Printf(_L("Count: %d \n"), count); + aTest(count == KTotalContacts, __LINE__); + + aTest.Printf(_L("Checking owncard id \n")); + TContactItemId id = db->OwnCardId(); + aTest.Printf(_L("id: %d \n"), id); + aTest(id != KNullContactId, __LINE__); + + SwitchToWorkerThread(mtx, thd, ETrue, ETrue); // c) Run: WT-2 to WT-3 + + // + // Worker thread has now deleted the contacts + // + + aTest.Printf(_L("Checking deleted db count \n")); + + WaitForNotificationsL(db); + + count = db->CountL(); + aTest.Printf(_L("Count: %d \n"), count); + aTest(count == 0, __LINE__); + + aTest.Printf(_L("Checking deleted owncard id \n")); + id = db->OwnCardId(); + aTest.Printf(_L("id: %d \n"), id); + aTest(id == KNullContactId, __LINE__); + + CleanupStack::PopAndDestroy(db); + + SwitchToWorkerThread(mtx, thd, ETrue, EFalse); // d) Run: WT-3 to end + + CleanupStack::PopAndDestroy(); // close thd handle + CleanupStack::PopAndDestroy(); // close mtx handle + } + + +LOCAL_D void TestFirstL(RTest& aTest) + { + aTest.Next(_L("@SYMTestCaseID:PIM-T-OWNCARDDELETE-0001 -- First Owncard Test --")); + + aTest.Printf(_L("Replacing database \n")); + CContactDatabase* db = CContactDatabase::ReplaceL(KDatabaseFileName); + CleanupStack::PushL(db); + + CContactDatabase* dbAnother = CContactDatabase::OpenL(KDatabaseFileName); + CleanupStack::PushL(dbAnother); + + PopulateDatabaseL(db, KTotalContacts); + WaitForNotificationsL(db); + + TestSetOwnCardL(db); + WaitForNotificationsL(db); + + aTest.Printf(_L("Checking the count value \n")); + TInt count = dbAnother->CountL(); + aTest.Printf(_L("Count: %d \n"), count); + aTest(count == KTotalContacts, __LINE__); + + aTest.Printf(_L("Checking the id \n")); + TContactItemId id = dbAnother->OwnCardId(); + aTest.Printf(_L("id: %d \n"), id); + aTest(id != KNullContactId, __LINE__); + + TContactIter iter(*db); //Test that the iterator is updated + TContactItemId firstContactId; + firstContactId = iter.FirstL(); //should be own contactId + + DeleteOwnContactL(dbAnother); + WaitForNotificationsL(dbAnother); + + TContactItemId secondContactId; + TRAPD (err, secondContactId = iter.FirstL()); + aTest(err == KErrNone && firstContactId != secondContactId, __LINE__); + + + DeleteMultipleContactsL(db); + WaitForNotificationsL(db); + + aTest.Printf(_L("Checking the deleted count value \n")); + count = dbAnother->CountL(); + aTest.Printf(_L("Count: %d \n"), count); + aTest(count == 0, __LINE__); + + aTest.Printf(_L("Checking the deleted id \n")); + id = dbAnother->OwnCardId(); + aTest.Printf(_L("id: %d \n"), id); + aTest(id == KNullContactId, __LINE__); + + aTest(gEventCounter == KMaxNumOfEvents, __LINE__); + aTest(gUnknownEventCounter == KMaxUnknownEvents, __LINE__); + + CleanupStack::PopAndDestroy(2,db); + } + + +LOCAL_D void ThreadDoTestsL() + { + RTestPtr myTest(new(ELeave) RTest(KThreadFunc)); + + myTest->Start(KThreadFunc); + ThreadFirstTestL(myTest.Ref()); + myTest->End(); + } + + +/** +@SYMTestCaseID PIM-T-OWNCARDDELETE-0001 +@SYMTestType UT +@SYMTestPriority Medium +@SYMDEF PDEF107246 +@SYMTestCaseDependencies CntModel CoreAppsTest +@SYMTestCaseDesc Check that updates to one CContactDatabase-instance will propagate to a second instance +@SYMTestActions Add some contacts. Set one as own card. Check that the count is the same for all instances. + Check that the own card id is the same for all instances. Delete all contacts and check that + the count is zero and own card id is KNullContactId (-1) for all instances. +@SYMTestExpectedResults see above. +*/ +LOCAL_D void DoTestsL() + { + RTestPtr myTest(new(ELeave) RTest(KOwnCard)); + + myTest->Start(KOwnCard); + TestFirstL(myTest.Ref()); + TestSecondL(myTest.Ref()); + + CContactDatabase::DeleteDatabaseL(KDatabaseFileName); + myTest->Printf(_L("Completed OK \n")); + myTest->End(); + } + + +LOCAL_D TInt ThreadFunction(TAny*) + { + __UHEAP_MARK; + CActiveScheduler* scheduler = new CActiveScheduler; + if (scheduler) + { + CActiveScheduler::Install(scheduler); + CTrapCleanup* cleanup = CTrapCleanup::New(); + if (cleanup) + { + TRAPD(err, ThreadDoTestsL()); + __ASSERT_ALWAYS(err == KErrNone, User::Panic(_L("Failure in Worker Thread"),err)); + delete cleanup; + } + delete scheduler; + } + __UHEAP_MARKEND; + return KErrNone; + } + + +GLDEF_C TInt E32Main() + { + __UHEAP_MARK; + CActiveScheduler* scheduler = new CActiveScheduler; + if (scheduler) + { + CActiveScheduler::Install(scheduler); + CTrapCleanup* cleanup = CTrapCleanup::New(); + if (cleanup) + { + TRAPD(err, DoTestsL()); + __ASSERT_ALWAYS(err == KErrNone, User::Panic(_L("Failure in Main Thread"),err)); + delete cleanup; + } + delete scheduler; + } + __UHEAP_MARKEND; + return KErrNone; + }