phonebookengines/contactsmodel/tsrc/t_CaseSensitiveDB.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/tsrc/t_CaseSensitiveDB.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,454 @@
+// Copyright (c) 1997-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 "t_CaseSensitiveDB.h"
+
+// System includes
+#include <e32std.h>
+#include <e32test.h>
+#include <cntdbobs.h>
+
+#include <cntitem.h>
+#include <cntfldst.h>
+
+#include "coreappstest/testserver.h" 
+
+
+// Globals
+static RTest					TheTest(_L("T_CASESENSITIVEDB - Test CntModel support"));
+static CTrapCleanup*			TheCleanup;
+
+// Constants (literal)
+
+// Configure database location
+_LIT(KTestDatabaseFileU,		"C:Contacts.cdb");
+_LIT(KTestDatabaseFileL,		"C:contacts.cdb");
+
+// Configure .ini file location
+_LIT(KContactsModelIniFile,		"C:\\private\\10003A73\\CntModel.ini");
+
+
+_LIT(KTestSemaphoreName,		"T_CASESENSITIVEDB_SEMAPHORE");
+
+_LIT(KNewContactName,"Test Name");
+
+class CTestActiveScheduler : public CActiveScheduler
+	{
+public:
+	void Error (TInt aError) const;
+	};
+
+void CTestActiveScheduler::Error(TInt aError) const
+	{
+	User::Panic(_L("AScheduler"),aError);
+	}
+
+CTestBase::CTestBase(TInt aClientNumber, TThreadPriority aThreadPriority, TInt aPriority)
+:	CActive(aPriority), 
+	iClientNumber(aClientNumber), 
+	iThreadPriority(aThreadPriority)
+	{
+	}
+
+CTestBase::~CTestBase()
+	{
+	Cancel();
+	iThread.Close();
+	}
+
+void CTestBase::ConstructL(const TDesC& aName)
+	{
+	User::LeaveIfError(iThread.Create(aName, ThreadFunction, KDefaultStackSize, 0x2000, 0x20000, this, EOwnerThread));
+	iThread.Resume();
+	iThread.SetPriority(iThreadPriority);
+	}
+
+void CTestBase::Complete(TInt aReason)
+	{
+	// Complete the request with the specified reason.
+	__ASSERT_ALWAYS(IsActive() && iStatus.Int() == KRequestPending, User::Invariant());
+	TRequestStatus* status = &iStatus;
+	iThread.RequestComplete(status, aReason);
+	}
+
+void CTestBase::RunL()
+	{
+	if(!iTestFinished)
+		{
+		if(!iWaiting)
+			{
+			DoTestL();
+			CActiveScheduler::Stop();	
+			}
+		else
+			{
+			//if test hasnt finished and is waiting for notification then it must have 
+			//failed as timer on waiting for notification has expired.
+			iTest->Printf(_L("ERROR:No notification received"));
+			(*iTest)(EFalse);
+			}
+		}
+	}
+
+void CTestBase::DoCancel()
+	{
+	iWaitTimer.Cancel();
+
+	// Cancel any outstanding request
+	if	(!(iWaiting))
+		Complete(KErrCancel);
+	}
+
+TInt CTestBase::ThreadFunction(TAny* aParam)
+	{
+	CTestBase* self = STATIC_CAST(CTestBase*, aParam);
+
+	// Prepare the stuff required before we start the
+	// active scheduler.
+    CTrapCleanup* cleanup = CTrapCleanup::New();
+	if	(!cleanup)
+		return KErrNoMemory;
+
+	// Call virtual handler which does anything that needs doing as
+	// a result of the thread function from being created.
+	TRAPD(err, self->RunTestsL());
+
+    delete cleanup;
+	return err;
+	}
+
+void CTestBase::RunTestsL()
+	{
+	User::LeaveIfError(iWaitTimer.CreateLocal());
+
+	TBuf<100> threadName;
+	threadName.Format(_L("Test thread %d"), iClientNumber);
+	iTest = new(ELeave) RTest(threadName);
+	iTest->Start(threadName);
+	iTest->Printf(_L("Starting Test thread %d \n"), iClientNumber);
+	//create Active Schedular for this thread
+	CActiveScheduler::Install(new(ELeave) CActiveScheduler);
+	
+	// Create contacts db session
+	OpenDatabaseL();
+
+	// Add the CTestBase object
+	// to it. Has to be done in this function, otherwise the AO can
+	// end up being added to the wrong active scheduler
+	CActiveScheduler::Add(this);
+
+	//Set request status 
+	SetRequestStatus();
+
+	CActiveScheduler::Start();
+
+	//close thread
+	iTest->Printf(_L("\tClosing thread %d \n"), iClientNumber);
+	iTest->End();
+	iTest->Close();
+
+	delete iDb;
+	delete CActiveScheduler::Current();
+
+	iWaitTimer.Cancel();
+	iWaitTimer.Close();
+	
+	//Setting this flag should be the last thing that happens
+	iTestFinished = ETrue;
+	}
+
+//	Requests another test be executed
+void CTestBase::SetRequestStatus()
+	{
+	__ASSERT_ALWAYS(!iWaiting, User::Invariant());
+	SetActive();
+	iStatus = KRequestPending;
+	}
+
+void CTestBase::WaitForContactsEvent(TContactDbObserverEventType aEvent, TInt aTimeInSecondsToWaitFor)
+	{
+	iWaiting = ETrue;
+	iEvent = aEvent;
+	TTimeIntervalMicroSeconds32 time(aTimeInSecondsToWaitFor * 1000000);
+
+	iWaitTimer.After(iStatus, time);
+	SetActive();
+	CActiveScheduler::Start();
+	}
+
+void CTestBase::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
+	{
+	__ASSERT_ALWAYS(iWaiting, User::Invariant());
+
+	switch(aEvent.iType)
+		{
+	case EContactDbObserverEventContactAdded:
+		iTest->Printf(_L("Event: EContactDbObserverEventContactAdded\n"));
+		break;
+	default:
+		iTest->Printf(_L("Unhandled Event\n"));
+		}
+
+	if	(aEvent.iType == iEvent)
+		{
+		Cancel();
+		iWaiting = EFalse;
+		CActiveScheduler::Stop();
+		return;
+		}
+	}
+
+CTestThreadOne::CTestThreadOne(TInt aClientNumber, TThreadPriority aThreadPriority, TInt aPriority)
+:	CTestBase(aClientNumber, aThreadPriority, aPriority)
+	{
+	}
+
+CTestThreadOne*	CTestThreadOne::NewL(TInt aClientNumber, const TDesC& aName, TThreadPriority aThreadPriority, TInt aPriority)
+	{
+	CTestThreadOne* self = new(ELeave) CTestThreadOne(aClientNumber, aThreadPriority, aPriority);
+	CleanupStack::PushL(self);
+	self->ConstructL(aName);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CTestThreadOne::OpenDatabaseL()
+	{
+	TBuf<200> buf;
+	buf.Format(_L("Opening database %S for thread 1 \n"), &KTestDatabaseFileU);
+	iTest->Printf(buf);
+	iDb = CContactDatabase::OpenL(KTestDatabaseFileU);
+	}
+
+LOCAL_C void SetNameL(CContactItem& aItem,TUid aType,const TDesC& aName)
+//
+// Set the contents of a text field, creating the field if required
+//
+	{
+	CContactItemFieldSet& fieldSet=aItem.CardFields();
+	const TInt pos=fieldSet.Find(aType);
+	if (pos!=KErrNotFound)
+		fieldSet[pos].TextStorage()->SetTextL(aName);
+	}
+
+void CTestThreadOne::DoTestL()
+	{
+	RSemaphore semaphore;
+	TInt semCreateErr = semaphore.CreateGlobal(KTestSemaphoreName, 0);
+	if (semCreateErr == KErrAlreadyExists)
+		{
+		User::LeaveIfError(semaphore.OpenGlobal(KTestSemaphoreName));
+		}
+	else
+		{
+		User::LeaveIfError(semCreateErr);		
+		}
+	CleanupClosePushL(semaphore);
+	
+	// Pause this thread while thread 2 sets up change notifier
+	semaphore.Wait();
+	
+	iTest->Printf(_L("Add new contact data\n"));
+
+	CContactItem* item=CContactCard::NewLC();
+	SetNameL(*item,KUidContactFieldGivenName,KNewContactName);
+	iDb->AddNewContactL(*item);	
+	
+	// Pause this thread while thread 2 checks for update
+	semaphore.Wait();
+	
+	CleanupStack::PopAndDestroy(2,&semaphore); // item, semaphore
+	}
+
+CTestThreadTwo::CTestThreadTwo(TInt aClientNumber, TThreadPriority aThreadPriority, TInt aPriority)
+:	CTestBase(aClientNumber, aThreadPriority, aPriority)
+	{
+	}
+
+CTestThreadTwo*	CTestThreadTwo::NewL(TInt aClientNumber, const TDesC& aName, TThreadPriority aThreadPriority, TInt aPriority)
+	{
+	CTestThreadTwo* self = new(ELeave) CTestThreadTwo(aClientNumber, aThreadPriority, aPriority);
+	CleanupStack::PushL(self);
+	self->ConstructL(aName);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CTestThreadTwo::OpenDatabaseL()
+	{
+	TBuf<200> buf;
+	buf.Format(_L("Opening database %S for thread 2 \n"), &KTestDatabaseFileL);
+	iTest->Printf(buf);
+	iDb = CContactDatabase::OpenL(KTestDatabaseFileL);
+	}
+
+void CTestThreadTwo::DoTestL()
+	{
+	RSemaphore semaphore;
+	TInt semCreateErr = semaphore.CreateGlobal(KTestSemaphoreName, 0);
+	if (semCreateErr == KErrAlreadyExists)
+		{
+		User::LeaveIfError(semaphore.OpenGlobal(KTestSemaphoreName));
+		}
+	else
+		{
+		User::LeaveIfError(semCreateErr);		
+		}
+	CleanupClosePushL(semaphore);
+	
+	iTest->Printf(_L("Setting up thread 2 change notifier\n"));
+
+	CContactChangeNotifier* changeNotifier = CContactChangeNotifier::NewL(*iDb, this);
+	CleanupStack::PushL(changeNotifier);
+
+	// Wait for change notifier to start
+	User::After(2000000);
+	
+	// Signal thread 1
+	semaphore.Signal();
+
+		// This will wait for it
+	iTest->Printf(_L("\tWaiting for change notification...\n"));
+	WaitForContactsEvent(EContactDbObserverEventContactAdded);
+	iTest->Printf(_L("\tNotification complete...\n"));
+	CleanupStack::PopAndDestroy(changeNotifier); // changeNotifier
+	
+	// Signal thread 1
+	semaphore.Signal();
+	
+	CleanupStack::PopAndDestroy(&semaphore); // semaphore
+	}
+
+CTestManager::CTestManager(TInt aPriority)
+:	CTimer(aPriority)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CTestManager::~CTestManager()
+	{
+	Cancel();
+	delete iClient1;
+	delete iClient2;
+	}
+
+void CTestManager::ConstructL()
+	{
+	CTimer::ConstructL();
+
+	iClient2 = CTestThreadTwo::NewL(2, _L("Client-2"), EPriorityLess); // lower
+	iClient1 = CTestThreadOne::NewL(1, _L("Client-1"), EPriorityMore);
+	IssueTimerRequest();
+	}
+
+CTestManager* CTestManager::NewL()
+	{
+	CTestManager* self = NewLC();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CTestManager* CTestManager::NewLC()
+	{
+	CTestManager* self = new (ELeave) CTestManager();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+void CTestManager::RunL()
+	{
+
+	if	( iClient1->IsActive() && iClient2->IsActive() 
+		&& !(iClient1->Waiting() || iClient2->Waiting()))
+		{
+		iClient1->Complete(1);
+		iClient2->Complete(1);
+		}	
+	if ( iClient1->TestFinished() && iClient2->TestFinished()) 
+		{				
+		//tests are finished so stop active schedular
+		CActiveScheduler::Stop();
+		return; // prevent from starting timer again
+		}
+		
+	// Re-issue the asynchronous request to the CTimer
+	IssueTimerRequest();
+	}
+
+void CTestManager::IssueTimerRequest()
+	{
+	const TInt KOneSecond = 1000000;
+	After(KOneSecond);
+	}
+
+static void doMainL()
+	{
+	CTestActiveScheduler*  scheduler = new (ELeave) CTestActiveScheduler;
+	CleanupStack::PushL(scheduler);                                 
+	CActiveScheduler::Install(scheduler);
+
+	// Replace contacts, using two styles of capitalisation
+	CContactDatabase* db;
+
+	db = CContactDatabase::ReplaceL(KTestDatabaseFileU);
+	delete db;
+	db = NULL;
+
+	db = CContactDatabase::ReplaceL(KTestDatabaseFileL);
+	delete db;
+	db = NULL;
+	
+	// Secure Server waits 5s from last connection
+	// to write the .ini file and close
+	User::After(6000000);
+	// Delete any existing ini file so that we can be sure this test is ok
+    RPIMTestServer serv;
+    User::LeaveIfError(serv.Connect());
+	serv.DeleteFileL(KContactsModelIniFile);
+    serv.Close();
+
+	// create test manager
+	CTestManager::NewLC();
+	// run tests
+	CActiveScheduler::Start();
+	// clean up
+	CleanupStack::PopAndDestroy(2,scheduler); // scheduler, tester
+	}
+
+
+/**
+
+@SYMTestCaseID     PIM-T-CASESENSITIVEDB-0001
+
+*/
+
+GLDEF_C TInt E32Main()
+	{	
+	__UHEAP_MARK;
+	TheTest.Start(_L("@SYMTESTCaseID:PIM-T-CASESENSITIVEDB-0001 Multi session case sensitive testcode"));
+
+	TheTest.Title();
+	TheCleanup = CTrapCleanup::New();
+	TRAPD(ret, doMainL());	
+	TheTest(ret == KErrNone);
+	delete TheCleanup;	
+
+	TheTest.End();
+	TheTest.Close();
+	__UHEAP_MARKEND;
+	return(KErrNone);
+	}
+