messagingfw/biomsgfw/BITSSRC/BioTestUtils.cpp
changeset 0 8e480a14352b
child 58 6c34d0baa0b1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/biomsgfw/BITSSRC/BioTestUtils.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,1305 @@
+// 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:
+// BioTestUtils.h
+//
+
+#include "biotestutils.h"
+
+#include <e32test.h>
+#include <f32fsys.h>
+#include <s32file.h>
+#include <e32uid.h>
+#include <txtrich.h>
+#include <txtfmlyr.h>
+#include <msvids.h>
+#include <msvuids.h>
+#include <msvruids.h>
+#include <e32std.h>
+#include <e32math.h>
+#include <mtclbase.h>
+#include <mtclreg.h>
+#include <msvapi.h>
+#include <mtmuids.h>
+
+#include <smuthdr.h>
+#include <biouids.h>
+#include <biodb.h>
+#include <biouids.h>
+#include <regpsdll.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS 
+#include <tmsvsmsentry.h>
+#include <bifchangeobserver.h>
+#include <biomessageuids.h>
+#include "tmsvbioinfo.h"
+#endif
+
+#define KCharSpace          ' '
+
+EXPORT_C CBioTestUtils::~CBioTestUtils()
+	{
+	Reset();
+	delete iBioDb;
+	}
+
+EXPORT_C CBioTestUtils* CBioTestUtils::NewL(RTest& aRTest)
+	{
+	CBioTestUtils* self = new (ELeave) CBioTestUtils(aRTest);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CBioTestUtils* CBioTestUtils::NewLC(RTest& aRTest)
+	{
+	CBioTestUtils* self = new(ELeave) CBioTestUtils(aRTest);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+EXPORT_C CBioTestUtils* CBioTestUtils::NewL(RTest& aRTest, TInt aCreationFlags)
+	{
+	CBioTestUtils* self = NewLC(aRTest, aCreationFlags);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CBioTestUtils* CBioTestUtils::NewLC(RTest& aRTest, TInt aCreationFlags)
+	{
+	CBioTestUtils* self = new(ELeave) CBioTestUtils(aRTest);
+	CleanupStack::PushL(self);
+	self->ConstructL(aCreationFlags);
+	return self;
+	}
+
+void CBioTestUtils::Reset()
+	{
+	if(iTestParsedFieldArray)
+		{
+		iTestParsedFieldArray->ResetAndDestroy();
+		delete iTestParsedFieldArray;
+		iTestParsedFieldArray=NULL;
+		}
+	if(iMessageBody)
+		{
+		delete iMessageBody;
+		iMessageBody = NULL;
+		}
+	if(iDir)
+		{
+		delete iDir;
+		iDir = NULL;
+		}
+	if(iRegisteredParserDll)
+		{
+		delete iRegisteredParserDll;
+		iRegisteredParserDll = NULL;
+		}
+	if (iBioClientMtm)
+		{
+		delete iBioClientMtm;
+		iBioClientMtm=NULL;
+		}
+	if (iBioServerMtm)
+		{
+		delete iBioServerMtm;
+		iBioServerMtm = NULL;
+		iServerEntry = NULL;
+		}
+
+	iNumFiles = 0;
+	iFilesProcessed = 0;
+	iMessagesCreated = 0;
+
+	CMsvTestUtils::Reset();
+	}
+
+//
+// Register a Sms Mtm server DLL
+//
+EXPORT_C void CBioTestUtils::CreateBioServerMtmRegL()
+	{
+	CreateServerMtmRegL(KUidMsgTypeSmartMessage, _L("BIO MTM"),KBioServerMtmFileName(), KBioClientMtmFileName(), TMsvTestDllInfo(KBioUiMtmFileName,2), TMsvTestDllInfo(KBioUiMtmFileName,1), KUidMsgTypeSmartMessage, KDataComponentFileName);
+	}
+
+CBioTestUtils::CBioTestUtils(RTest& aRTest)
+: CMsvTestUtils(aRTest)
+	{
+	iBioServiceId = KMsvNullIndexEntryId;
+	}
+
+void CBioTestUtils::ConstructL()
+	{
+	TInt flags=NULL; // Settings flags for the base ConstructL() function
+
+	//	Loading the DLLs
+	iRTest.Next(_L("Create Data Component FileStores"));
+
+	CMsvTestUtils::ConstructL(flags);
+
+	iBioDb = CBIODatabase::NewL(iFs);
+
+	FileSession().SetSessionPath(_L("c:\\"));
+	}
+
+// Overloaded constructor - allows developer to decide what components to create
+void CBioTestUtils::ConstructL(TInt aCreationFlags)
+	{
+	iRTest.Next(_L("Initialising Data Components"));
+	// 
+	CMsvTestUtils::ConstructL(aCreationFlags);
+
+	iBioDb = CBIODatabase::NewL(iFs);
+	FileSession().SetSessionPath(_L("c:\\"));
+	}
+
+
+void CBioTestUtils::Panic(TBioTestUtilsPanic aPanic)
+	{
+	Panic((TInt) aPanic);
+	}
+
+void CBioTestUtils::Panic(TInt aPanic)
+	{
+	User::Panic(BIOTEST_PANIC, aPanic);
+	}
+
+EXPORT_C TMsvId CBioTestUtils::CreateBIOEntryL(TDesC& aText, TBIOMessageType aMessageType )
+	{
+	// Ensure that we have a valid service ID to work with:
+	if (iBioServiceId==0)
+		iBioServiceId = SetBIOServiceIdL();
+
+	// First take the descriptor reference and create a new descriptor to manipulate.
+	// Then convert '\n' to the paragraph delimiters used in proper SMS.
+	HBufC* localBuffer = aText.AllocL();
+	CleanupStack::PushL(localBuffer);
+
+	TPtr messDes = localBuffer->Des();
+
+	if (aMessageType != EBiovCardMessage && aMessageType != EBiovCalenderMessage)
+		{
+		// convert \r\n to \n since this is what is expected from SMS when not vCard data
+		for (TInt i=0; i<messDes.Length(); i++)
+			{
+			if (messDes[i]==(TText)'\r' && i<messDes.Length()-1 && messDes[i+1]==(TText)'\n')
+				messDes.Delete(i,1); 
+			} 
+		}
+
+	//	Create and fill a CRichText object for the jobbie:
+	CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
+	CleanupStack::PushL(paraFormatLayer);
+	CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
+	CleanupStack::PushL(charFormatLayer);
+	CRichText* richText = CRichText::NewL(paraFormatLayer,charFormatLayer);
+	CleanupStack::PushL(richText);
+
+	TInt pos = richText->DocumentLength();	// Ought to be 0.
+	richText->InsertL(pos, messDes);
+	
+	TMsvEntry newBioEntry;
+	newBioEntry.SetNew(ETrue);
+	newBioEntry.SetComplete(EFalse);
+	newBioEntry.SetUnread(ETrue);
+	newBioEntry.SetVisible(ETrue);
+	newBioEntry.SetReadOnly(EFalse);
+	newBioEntry.SetFailed(EFalse);
+	newBioEntry.SetOperation(EFalse);
+	newBioEntry.SetMultipleRecipients(EFalse);
+	newBioEntry.SetAttachment(EFalse);
+	newBioEntry.iMtm= KUidBIOMessageTypeMtm;
+	newBioEntry.iType=KUidMsvMessageEntry;
+	newBioEntry.iServiceId=iBioServiceId;
+	TTime now;
+	now.UniversalTime();
+	newBioEntry.iDate = now;
+
+	newBioEntry.iDescription.Set(richText->Read(0, richText->DocumentLength()));
+	TBufC<KTelephoneNumberMaxLength> telNumber;
+	HBufC* tempNumber = CreateDummyPhoneNumberL();
+	telNumber = tempNumber->Des();
+	newBioEntry.iDetails.Set(telNumber);
+	// Finished with telNumber, so free up the memory:
+	delete tempNumber; 
+
+	// Change the iServiceId, iMtm, iBioType  for message:
+	SetForMtmTypeL(newBioEntry, aMessageType);
+	// Update the size to that of the attachment length  - correct? 
+	// Otherwise just get 68
+	newBioEntry.iSize = richText->DocumentLength();// msgSize;
+	iClientServer == EServerSide ? CreateBioEntryServerSideL(newBioEntry,*richText) : CreateBioEntryClientSideL(newBioEntry,*richText);
+
+	CleanupStack::PopAndDestroy(4); // richText, charFormatLayer, paraFormatLayer, localBuffer
+	return newBioEntry.Id(); 
+	}
+
+void CBioTestUtils::SetForMtmTypeL(TMsvEntry& aEntry, TBIOMessageType aType)
+	{
+	TInt index;
+	// Should have a match for the Message Type as the message is created with the SMS id's.
+	switch(aType)
+		{
+		case ENoMessage:
+			// Just to keep compiler happy!
+			break;
+		case EBioIapSettingsMessage:
+			aEntry.iBioType  = KUidBIOInternetAccessPointMsg;
+			break;
+		case EBioEnpMessage:
+			aEntry.iBioType =KUidBIOEmailNotificationMsg;
+			break;
+		case EBioRingTonesMessage:
+			aEntry.iBioType =KUidBIORingingTonesMsg;
+			break;
+		case EBioOpLogoMessage:
+			aEntry.iBioType =KUidBIOOperatorLogoMsg;
+			break;
+		case EBioCompBusCardMessage:
+			aEntry.iBioType =KUidBIOBusinessCardMsg;
+			break;
+		case EBiovCardMessage:
+			aEntry.iBioType =KUidBIOVCardMsg;
+			break;
+		case EBiovCalenderMessage:
+			aEntry.iBioType =KUidBIOVCalenderMsg;
+			break;
+		case EBioWAPSettingsMessage:
+			aEntry.iBioType =KUidBIOWAPAccessPointMsg;
+			break;
+		case EBioWPRVSettingsMessage:
+			aEntry.iBioType =KUidBIOWPRVMsg;
+			break;
+		}
+	// Set other TMsvEntry fields if we have a BIO message type
+	if (aType != ENoMessage)
+		{
+		aEntry.SetMtmData2(0);
+		aEntry.SetMtmData3(0);
+		}
+
+	// set description from BIF file
+	iBioDb->GetBioIndexWithMsgIDL(TUid::Uid(aEntry.iBioType),index);
+	if(index==KErrNotFound)
+		User::Leave(KErrNotFound);
+	aEntry.iDescription.Set(iBioDb->BifReader(index).Description());
+	}
+
+EXPORT_C void CBioTestUtils::LogCurrentMessageTypeL(TMsvId aMsvId)
+	{
+	// assume we're already pointing at a BIO message
+	TMsvEntry entry;
+	TMsvId oldId;
+	if(iClientServer == EServerSide)
+		{
+		oldId = iServerEntry->Entry().Id();
+		User::LeaveIfError(iServerEntry->SetEntry(aMsvId));
+		entry = iServerEntry->Entry();
+		}
+	else
+		{
+		oldId = iMsvEntry->Entry().Id();
+		iMsvEntry->SetEntryL(aMsvId);
+		entry = iMsvEntry->Entry();
+		}
+
+	TInt biotype = entry.iBioType;
+	if(biotype == KUidBIOInternetAccessPointMsg)
+		{
+		switch(entry.MtmData1())
+			{
+		case 1:
+			WriteComment(_L("IACP basic IAP message"));
+			break;
+		case 2:
+			WriteComment(_L("IACP basic mail message"));
+			break;
+		case 3:
+			WriteComment(_L("IACP basic IAP & mail message"));
+			break;
+		case 7:
+			WriteComment(_L("IACP Internet script message"));
+			break;
+		case 8:
+			WriteComment(_L("IACP SMS settings message"));
+			break;
+		case 15:
+			WriteComment(_L("Telephone settings message"));
+			break;
+		default:
+			WriteComment(_L("Unsupported IACP type"));
+			break;
+			}
+		}
+	else if(biotype == KUidBIOEmailNotificationMsg)
+			WriteComment(_L("Email notification message"));
+	else if(biotype == KUidBIORingingTonesMsg)
+			WriteComment(_L("Ringing tones message"));
+	else if(biotype == KUidBIOOperatorLogoMsg)
+			WriteComment(_L("Operator logo message"));
+	else if(biotype == KUidBIOBusinessCardMsg)
+			WriteComment(_L("Compact Business Card message"));
+	else if(biotype == KUidBIOVCardMsg)
+			WriteComment(_L("vCard message"));
+	else if(biotype == KUidBIOVCalenderMsg)
+			WriteComment(_L("vCalendar"));
+	else if(biotype == KUidBIOWAPAccessPointMsg)
+			WriteComment(_L("WAP settings message"));
+	else
+		WriteComment(_L("Unknown type"));
+
+	if(iClientServer == EServerSide)
+		{
+		User::LeaveIfError(iServerEntry->SetEntry(oldId));
+		}
+	else
+		{
+		iMsvEntry->SetEntryL(oldId);
+		}
+	}
+
+EXPORT_C TMsvId CBioTestUtils::CreateBIOEntryFromFileL(const TDesC& aFilename, TBIOMessageType aMessageType)
+	{
+	//First use the filename to get the message body, 
+	// then convert '\n' to the paragraph delimiters used in proper SMS	
+	HBufC* tempBuffer;
+	TMsvId newEntryId;
+	tempBuffer = ReadFromFileL(aFilename);
+	CleanupStack::PushL(tempBuffer);
+
+	newEntryId = CreateBIOEntryL(*tempBuffer, aMessageType );
+
+	// Finished with our local descriptors - free up some memory
+	CleanupStack::PopAndDestroy();  
+	return newEntryId;
+	}
+
+
+EXPORT_C void CBioTestUtils::EmptyInboxMessagesL()
+	{
+	// Function gets the Inbox Entry, and then all the children of this entry.
+	// Then we iterate through the selection deleting each entry.
+	CMsvEntrySelection* inboxMessageSel;
+	if(iClientServer == EServerSide)
+		{
+		inboxMessageSel = new (ELeave) CMsvEntrySelection;
+		CleanupStack::PushL(inboxMessageSel);
+		// Create a local Server entry, and get the children of the Global Inbox:
+		User::LeaveIfError(iServerEntry->SetEntry(KMsvGlobalInBoxIndexEntryId));	
+		iServerEntry->GetChildren(*inboxMessageSel ); // children of parent, ie global inbox
+		if (inboxMessageSel->Count() != 0)
+			{
+			iServerEntry->DeleteEntries(*inboxMessageSel);
+    		}
+		//	Point back at something safe before we return:
+		User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryId));
+		}
+	else
+		{
+		iMsvEntry->SetEntryL(KMsvGlobalInBoxIndexEntryId);
+		inboxMessageSel = iMsvEntry->ChildrenL();
+		CleanupStack::PushL(inboxMessageSel);
+		if (inboxMessageSel->Count() != 0)
+			{
+			TInt count;
+			TMsvId currentMsgId;
+			for (count = 0; count < inboxMessageSel->Count(); count++)
+				{
+				currentMsgId= inboxMessageSel->At(count);
+				// Delete this entry
+				DeleteLocalEntrySynchronouslyL(*iMsvEntry, currentMsgId);
+				}
+    		}
+		iMsvEntry->SetEntryL(KMsvRootIndexEntryId);
+		}
+	CleanupStack::PopAndDestroy();	// inboxMessageSel
+	}
+
+void CBioTestUtils::DeleteLocalEntrySynchronouslyL(CMsvEntry& aParentEntry, TMsvId anId)
+	{ 
+	//  Creates an entry synchronously by handling the asynchrous parts locally
+ 
+	const TMsvSelectionOrdering& originalSort=aParentEntry.SortType();
+	TMsvSelectionOrdering sort(originalSort);
+	sort.SetShowInvisibleEntries(ETrue);
+	aParentEntry.SetSortTypeL(sort);
+	CMsvOperationWait* myDog=CMsvOperationWait::NewLC();
+	CMsvOperation* op=aParentEntry.DeleteL(anId, myDog->iStatus);
+	myDog->Start();
+	CActiveScheduler::Start();
+	const TInt err=op->iStatus.Int();
+	TMsvLocalOperationProgress progress=McliUtils::GetLocalProgressL(*op);
+	delete op;
+	User::LeaveIfError(err);
+	User::LeaveIfError(progress.iError);
+	CleanupStack::PopAndDestroy();
+	aParentEntry.SetSortTypeL(originalSort);
+	}
+//*************************************************************************
+//
+//		Getting BIO service ID
+//
+//*************************************************************************
+
+// Get,or create, the default BIO service:
+EXPORT_C TMsvId CBioTestUtils::SetBIOServiceIdL()
+	{
+	// If Bio service Id is none zero its already been set - just return the value:
+	if (iBioServiceId)
+		return iBioServiceId;
+
+	if(iClientServer == EServerSide)
+		SetBioServiceServerSideL();
+	else
+		SetBioServiceClientSideL();
+	return iBioServiceId;
+	}
+
+void CBioTestUtils::SetBioServiceServerSideL()
+	{
+	// Set up the RootEntry sort order first:
+	TMsvSelectionOrdering oldSortType = iServerEntry->Sort();
+	TMsvSelectionOrdering sortType(KMsvGroupByType, EMsvSortByNone, ETrue);	
+	iServerEntry->SetSort(sortType);
+
+	// Search the root folder for any entries which are BIO Message services.
+	// If none are found then create one.
+	TMsvId localServiceId=KMsvNullIndexEntryId;
+	localServiceId = DefaultServiceForMTML(KUidBIOMessageTypeMtm, ETrue);
+
+	// Check that the Service id is valid, i.e. set iCurrentEntry context to service entry:
+	TRAPD( error, iServerEntry->SetEntry(localServiceId) );
+	if ( (localServiceId == KMsvUnknownServiceIndexEntryId)  || (error == KErrNotFound) )
+		{
+		// Id isn't a valid BIO service, so try and get the first BIO service:
+		CMsvEntrySelection* sel = GetListOfAccountsWithMTMServerL(KUidBIOMessageTypeMtm);
+		CleanupStack::PushL(sel);
+		if (sel->Count())
+			iBioServiceId=(*sel)[0];	// Select the first available service.
+		CleanupStack::PopAndDestroy();	// sel
+		if (localServiceId == KMsvUnknownServiceIndexEntryId || localServiceId == KMsvNullIndexEntryId)
+			// Haven't found any valid BIO service, so try and create a BIO service:
+			localServiceId=CreateDefaultBIOServiceL();
+		}
+		else
+			User::LeaveIfError(error);  // An error other than no service occurred.
+
+	__ASSERT_DEBUG( localServiceId != KMsvNullIndexEntryId, User::Panic(_L("BioGen"), KErrNotFound));
+
+	//	Point back at something safe:
+	User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryId));
+	iServerEntry->SetSort(oldSortType);
+
+	iBioServiceId = localServiceId;
+	}
+
+void CBioTestUtils::SetBioServiceClientSideL()
+	{
+	iMsvEntry->SetSortTypeL(TMsvSelectionOrdering(KMsvGroupByType, EMsvSortByNone, ETrue));
+#if defined (_DEBUG)
+	if (iMsvEntry->EntryId() != KMsvRootIndexEntryId)  //iMsvEntry should be set to root
+		User::Leave(KErrNotFound);	//replaces a panic - ENotAServiceEntry
+#endif
+
+	TMsvId localServiceId=KMsvNullIndexEntryId;
+	localServiceId=DefaultServiceForMTML(KUidBIOMessageTypeMtm, ETrue);
+
+	//Check if there is a valid entry for this ID
+	TRAPD(ret, /*const TMsvEntry& ent=*/iMsvEntry->ChildDataL(localServiceId));
+
+	if (localServiceId == KMsvUnknownServiceIndexEntryId || ret==KErrNotFound)
+		{
+		// Our Id isn't a valid BIO service, possibly because there isn't a default 
+		// BIO service.  So try and get the first BIO service.
+		CMsvEntrySelection* sel=GetListOfAccountsWithMTMClientL(KUidBIOMessageTypeMtm);
+		if (sel->Count())
+			localServiceId=(*sel)[0]; // select the first available service
+		delete sel;
+		if (localServiceId == KMsvUnknownServiceIndexEntryId || localServiceId == KMsvNullIndexEntryId)
+			// No SMS service present, so let's create one 
+			CreateServicesL();
+		}
+	else
+		User::LeaveIfError(ret);  // an error other than no service occurred
+
+#if defined (_DEBUG)
+	if (localServiceId == KMsvNullIndexEntryId)
+		User::Leave(KErrNotFound);	//replaces a panic - ENotAServiceEntry
+#endif
+	iBioServiceId = localServiceId;
+	}
+
+TMsvId CBioTestUtils::CreateDefaultBIOServiceL() 
+	{
+	//	Haven't found an entry so create a BIO Message service:
+	TMsvEntry bioServiceEntry;
+	bioServiceEntry.iMtm = KUidBIOMessageTypeMtm;
+	bioServiceEntry.iType = KUidMsvServiceEntry;
+	bioServiceEntry.SetVisible(EFalse);
+	bioServiceEntry.iDate.UniversalTime();
+	bioServiceEntry.iDescription.Set(_L("BIO Message Service "));	// Is there such a thing?
+	bioServiceEntry.iDetails.Set(_L("BIO Message Service"));
+
+//	no need to set default service for v2, CBaseMtm 'knows' that for services 
+//	where there is a single service entry, it has to be the default
+	TMsvId newBIOServiceId;
+	if(iClientServer == EServerSide)
+		{
+		User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryId));
+		User::LeaveIfError(iServerEntry->CreateEntry(bioServiceEntry)); // Needs to be a child of the root!
+		newBIOServiceId =bioServiceEntry.Id();
+
+		}
+	else
+		{
+		iMsvEntry->SetEntryL(KMsvRootIndexEntryId);
+		iMsvEntry->CreateL(bioServiceEntry); // Needs to be a child of the root!
+		newBIOServiceId =bioServiceEntry.Id();
+
+		}
+
+	// No need to set Server Entry - still pointing at the root.
+	return newBIOServiceId;
+	}
+
+
+TMsvId CBioTestUtils::DefaultServiceForMTML(TUid aMtmUid, TBool aFindFirstServiceIfNoDefault)
+	{
+	TMsvId serviceId=KMsvUnknownServiceIndexEntryId;
+	if(iClientServer == EServerSide)
+		serviceId = DefaultServiceServerL(aMtmUid,aFindFirstServiceIfNoDefault);
+	else
+		serviceId = DefaultServiceClientL(aMtmUid,aFindFirstServiceIfNoDefault);
+	return serviceId;
+	}
+
+TMsvId CBioTestUtils::DefaultServiceServerL(TUid aMtmUid, TBool /*aFindFirstServiceIfNoDefault*/)
+	{
+	TMsvId serviceId=KMsvUnknownServiceIndexEntryId;
+	User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryId));
+
+		// Find first available service with the desired iMtm value:
+		CMsvEntrySelection* sel=new (ELeave) CMsvEntrySelection;
+		CleanupStack::PushL(sel);
+
+		iServerEntry->GetChildren(*sel);
+		
+		for (TInt count = 0; serviceId != 0 && count < sel->Count(); count++)
+			{
+			User::LeaveIfError(iServerEntry->SetEntry(sel->At(count)));
+			if (iServerEntry->Entry().iMtm == aMtmUid)
+				serviceId = sel->At(count);
+			}
+		CleanupStack::PopAndDestroy(); //  sel
+
+	//	Point back at something safe:
+	User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryId));
+
+	return serviceId;
+	}
+
+TMsvId CBioTestUtils::DefaultServiceClientL(TUid /*aMtmUid*/, TBool /*aFindFirstServiceIfNoDefault*/)
+	{
+	if (!iBioClientMtm)
+		{
+		InstantiateClientMtmsL();
+		}
+	return iBioClientMtm->DefaultServiceL();
+	}
+
+CMsvEntrySelection* CBioTestUtils::GetListOfAccountsWithMTMServerL(TUid aMtmUid)
+	{
+	// Gets a list of entries with the passed in MTM.
+	CMsvEntrySelection*	 returnSelection =new(ELeave) CMsvEntrySelection();
+	CleanupStack::PushL(returnSelection);
+
+	CMsvEntrySelection*	 rootKin = new (ELeave) CMsvEntrySelection();
+	CleanupStack::PushL(rootKin);
+
+	CMsvEntrySelection*	 entryKin = new (ELeave) CMsvEntrySelection();
+	CleanupStack::PushL(entryKin);
+	
+	TMsvSelectionOrdering  oldSortType = iServerEntry->Sort();
+	TMsvSelectionOrdering	sortType(KMsvGroupByType|KMsvGroupByStandardFolders, EMsvSortByDetailsReverse, ETrue);
+
+	// iCurrentEntry should be pointing towards the root, but make sure:
+	User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryIdValue));
+	iServerEntry->SetSort(sortType);
+	iServerEntry->GetChildren(*rootKin);  // Get the child entries of the root.
+
+	TBool visible=EFalse;
+	TInt err;
+	if ( rootKin->Count() !=0)
+		{
+		TMsvEntry tentry;
+		for (TInt cc=rootKin->Count(); --cc>=0; ) // N.B. decrements prior to entering loop.
+			{
+			// Set the context of our Server Entry to the next child entry of the root:
+			User::LeaveIfError(iServerEntry->SetEntry(rootKin->At(cc)) );
+			// Get the entry and check its mtm type:
+			tentry =iServerEntry->Entry();   
+			if (tentry.iMtm==aMtmUid)
+				{
+				// Is it a proper service entry?
+				if (tentry.iType.iUid==KUidMsvServiceEntryValue && tentry.Id()!=KMsvLocalServiceIndexEntryIdValue)
+					{
+					// If it's visible or it has no entry in the index - add to our return array:
+					if (tentry.Visible() || tentry.iRelatedId==KMsvNullIndexEntryId)
+						returnSelection->AppendL(tentry.Id());
+					else if (tentry.iRelatedId!=tentry.Id())
+						{
+						// Check if there are any related entries:
+						TRAP(err, iServerEntry->GetChildren(*entryKin) );
+						TInt count = entryKin->Count();
+						while (count--)
+							{
+							User::LeaveIfError(iServerEntry->SetEntry( entryKin->At(count) ) );
+							if (iServerEntry->Entry().Id() == tentry.iRelatedId)
+								break;
+							}
+						visible=iServerEntry->Entry().Visible();
+						if (err==KErrNone && !visible && returnSelection->Find(tentry.iRelatedId)!=KErrNone)
+							returnSelection->AppendL(tentry.Id());
+						}
+					}
+				}
+			}
+		}		
+
+	//	Point back at something safe:
+	User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryId));
+	iServerEntry->SetSort(oldSortType);
+	CleanupStack::PopAndDestroy(2); // entryKin, rootKin, 	
+	CleanupStack::Pop(); // returnSelection 
+
+	return returnSelection;
+	}
+
+CMsvEntrySelection* CBioTestUtils::GetListOfAccountsWithMTMClientL(TUid aMtmUid)
+	{
+	// Gets a list of entries with the passed in MTM
+	CMsvEntrySelection*	 returnSelection =new(ELeave) CMsvEntrySelection();
+	CleanupStack::PushL(returnSelection);
+
+	CMsvEntrySelection*	 rootKin;
+	CMsvEntrySelection*	 entryKin;
+
+	TMsvSelectionOrdering  oldSortType = iMsvEntry->SortType();
+	TMsvSelectionOrdering	sortType(KMsvGroupByType|KMsvGroupByStandardFolders, EMsvSortByDetailsReverse, ETrue);
+
+	// iCurrentEntry should be pointing towards the root, but make sure
+	iMsvEntry->SetEntryL(KMsvRootIndexEntryIdValue);
+	iMsvEntry->SetSortTypeL(sortType);
+	rootKin=iMsvEntry->ChildrenL();  // Get the child entries of the root
+	CleanupStack::PushL(rootKin);
+
+	TBool visible=EFalse;
+
+	if ( rootKin->Count() !=0)
+		{
+		TMsvEntry tentry;
+		for (TInt cc=rootKin->Count(); --cc>=0; ) // NB decrements prior to entering loop
+			{
+			// Set the context of our Server Entry to the next child entry of the root
+			iMsvEntry->SetEntryL(rootKin->At(cc)) ;
+			// get the entry and check it's mtm type
+			tentry =iMsvEntry->Entry();   
+			if (tentry.iMtm==aMtmUid)
+				{
+				// Is it a proper service entry
+				if (tentry.iType.iUid==KUidMsvServiceEntryValue && tentry.Id()!=KMsvLocalServiceIndexEntryIdValue)
+					{
+					// if it's visible or it has no entry in the index - add to our return array
+					if (tentry.Visible() || tentry.iRelatedId==KMsvNullIndexEntryId)
+						returnSelection->AppendL(tentry.Id());
+					else if (tentry.iRelatedId!=tentry.Id())
+						{
+						// Check if there are any related entries
+						entryKin=iMsvEntry->ChildrenL() ;
+						CleanupStack::PushL(entryKin);
+
+						TInt count = entryKin->Count();
+						while (count--)
+							{
+							iMsvEntry->SetEntryL( entryKin->At(count) );
+							if (iMsvEntry->Entry().Id() == tentry.iRelatedId)
+								break;
+							}
+						visible=iMsvEntry->Entry().Visible();
+						if (!visible && returnSelection->Find(tentry.iRelatedId)!=KErrNone)
+							returnSelection->AppendL(tentry.Id());
+						CleanupStack::PopAndDestroy(); // entryKin 	
+						}
+					}
+				}
+			}
+		}		
+
+	//	Point back at something safe.....
+	iMsvEntry->SetEntryL(KMsvRootIndexEntryId);
+	iMsvEntry->SetSortTypeL(oldSortType);
+	CleanupStack::PopAndDestroy(); // entryKin, rootKin, 	
+	CleanupStack::Pop(); //returnSelection 
+
+	return returnSelection;
+	}
+
+
+//*****************************************************************************
+//
+// File Read and Message Creation functions
+//
+//*****************************************************************************
+EXPORT_C void CBioTestUtils::SetSessionPath(const TDesC& aSessionPath)
+	{
+    iFs.SetSessionPath(aSessionPath);
+	}
+
+HBufC* CBioTestUtils::ReadFromFileL(const TDesC& aFile)
+	{
+	// Reads in data from a file and loads it into a buffer which is later used
+	// to create an SMS message in the  Inbox.  This function differs from the others
+	// in that it also gets any From: field by locating the token in the file. 
+	// NOTE: There is an inherent assumption that the From: token and the field will
+	// be on a single line in the text file (i.e. less than 1024 characters.
+	RFile           file;
+	TBuf8<1024>     lineBuffer;   // Buffer for Read function.
+	TInt			err=KErrNone;
+
+	err = file.Open(iFs,aFile,EFileStreamText|EFileRead|EFileShareAny);
+
+    if(err != KErrNone)  // Didn't find the file, so leave - should only get valid filenames!
+        {
+        User::Leave(KErrNotFound);
+		}
+
+	// In real life this is set by the Socket Port Observer, or the SMS server.
+	// So,in this test code we must do it by creating a random  telephone number.
+	//	iMessageDetails = CreateDummyPhoneNumberL();
+
+    HBufC*	bioBuf=HBufC::NewLC(65535); // Create a new descriptor on the heap.
+	HBufC*	copyBuffer=HBufC::NewLC(1024);
+
+    do // Read in the text from file, and also check if there is a name field:
+		{
+		err = file.Read(lineBuffer);// Read upto 256 chars, '\n' and all...
+		//err = ReadLineL(file,lineBuffer);
+		if (err==KErrNone)				// Made a valid read,
+			if (lineBuffer.Length()==0) // but read 0 chars
+				err=KErrEof;			// so set err value to end processing
+
+		if(err == KErrNone)
+			{
+			copyBuffer->Des().Copy(lineBuffer);// Copy, and overwrite existing text
+			if( (bioBuf->Length() + copyBuffer->Length()) > bioBuf->Des().MaxLength() )
+					{
+					bioBuf = bioBuf->ReAllocL(bioBuf->Length() + copyBuffer->Length());
+					}
+			bioBuf->Des().Append(*copyBuffer);
+            //bioBuf->Des().Append(_L("\n"));
+			}
+		}
+    while(err != KErrEof);
+
+	CleanupStack::PopAndDestroy(); // Destroy the copyBuffer.
+	CleanupStack::Pop();// Remove the bioBuf.
+    
+	file.Close();
+	return bioBuf;  // Transfer ownership and responsibility of the buffer.
+	}
+
+
+
+//*****************************************************************************
+//
+// Creating a dummy phone number for use in messages
+//
+//*****************************************************************************
+
+
+
+HBufC* CBioTestUtils::CreateDummyPhoneNumberL()
+	{
+	HBufC* number= HBufC::NewL(32); // Note: function doesn't own this, up to the caller to delete
+	TInt64 phoneNo;
+	TInt64 seed;
+	TTime tempTime;
+	tempTime.UniversalTime();
+	seed=tempTime.Int64();
+	phoneNo= Math::Rand(seed);
+	if (phoneNo <0)
+		phoneNo = -phoneNo;
+	number->Des().Num( phoneNo); 
+	number->Des().Insert(0,_L("+44"));// Add a leading '+' to make if an international numbers
+	return number;
+	}
+
+
+void CBioTestUtils::CreateBioEntryServerSideL(TMsvEntry& aEntry, CRichText& aBody)
+	{
+	//	Get the global inbox:
+	User::LeaveIfError(iServerEntry->SetEntry(KMsvGlobalInBoxIndexEntryId));
+	// Entry Context already set, create our entry:
+	User::LeaveIfError(iServerEntry->CreateEntry(aEntry)); 
+	// Set our context to the the new entry so we can create a store:
+	User::LeaveIfError(iServerEntry->SetEntry(aEntry.Id()) );
+	// Save all the changes:
+	CMsvStore* store;
+	store=iServerEntry->EditStoreL();
+	CleanupStack::PushL(store);
+
+	if (store->HasBodyTextL())
+		{
+		store->DeleteBodyTextL();
+		}
+	store->StoreBodyTextL(aBody);
+	store->CommitL();
+	CleanupStack::PopAndDestroy(); // Close and destroy the store.
+	// Set context to the new entry to allow updating of  the entry:
+	aEntry.SetComplete(ETrue);
+	iServerEntry->ChangeEntry(aEntry);
+	User::LeaveIfError(iServerEntry->SetEntry(KMsvRootIndexEntryId));
+	}
+
+void CBioTestUtils::CreateBioEntryClientSideL(TMsvEntry& aEntry, CRichText& aBody)
+	{
+		//	Get the global inbox.	
+	iMsvEntry->SetEntryL(KMsvGlobalInBoxIndexEntryId);
+	iMsvEntry->CreateL(aEntry); 
+	iMsvEntry->SetEntryL(aEntry.Id());
+
+	// Save all the changes
+	CMsvStore* store;
+	store=iMsvEntry->EditStoreL();
+	CleanupStack::PushL(store);
+
+	if (store->HasBodyTextL())
+		{
+		store->DeleteBodyTextL();
+		}
+	store->StoreBodyTextL(aBody);
+	store->CommitL();
+
+	CleanupStack::PopAndDestroy(); //store - close the store
+
+	aEntry.SetComplete(ETrue);
+	// Update the entry
+	iMsvEntry->ChangeL(aEntry);
+	iMsvEntry->SetEntryL(KMsvRootIndexEntryId);
+	}
+
+void CBioTestUtils::InstantiateClientMtmsL()
+	{
+	// client side
+	__ASSERT_ALWAYS(iMsvSession, User::Panic(BIOTEST_PANIC, KErrBIONotOnClientSide));
+	if(iClientMtmRegistry)
+		delete iClientMtmRegistry;
+	iClientMtmRegistry = CClientMtmRegistry::NewL(*iMsvSession);
+	iBioClientMtm = (CBIOClientMtm*) iClientMtmRegistry->NewMtmL(KUidMsgTypeSmartMessage);
+	}
+
+void CBioTestUtils::InstantiateServerMtmsL()
+	{
+	iBioServerMtm = (CBIOServerMtm*) InstantiateServerMtmL(KUidBIOMessageTypeMtm, iBioServiceId);
+	const CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection();
+	TRequestStatus st;
+	TMsvId s =0;
+	TRAP_IGNORE(iBioServerMtm->CopyFromLocalL(*selection,s, st));
+	TRAP_IGNORE(iBioServerMtm->CopyToLocalL(*selection,s, st));
+	TRAP_IGNORE(iBioServerMtm->CopyWithinServiceL(*selection,s, st));
+	TRAP_IGNORE(iBioServerMtm->MoveFromLocalL(*selection,s, st));
+	TRAP_IGNORE(iBioServerMtm->MoveToLocalL(*selection,s, st));
+	TRAP_IGNORE(iBioServerMtm->MoveWithinServiceL(*selection,s, st));
+	TRAP_IGNORE(iBioServerMtm->DeleteAllL(*selection,st));
+	
+	TInt intw =0;
+		
+	TRAP_IGNORE(iBioServerMtm->Cancel());
+	iBioServerMtm->CommandExpected();
+	TMsvEntry entry;
+	
+	TRAP_IGNORE(iBioServerMtm->ChangeL(entry,st));
+	TRAP_IGNORE(iBioServerMtm->CreateL(entry,st));
+	delete selection;
+	}
+
+void CBioTestUtils::DeleteServicesL()
+	{
+	DeleteServiceL(KUidBIOMessageTypeMtm);
+	}
+
+void CBioTestUtils::CreateServicesL()
+	{
+	iBioServiceId = CreateServiceL(KUidMsgTypeSmartMessage);
+	}
+
+void CBioTestUtils::FindExistingServicesL()
+	{
+	iBioServiceId = 0;
+	TRAPD(err,ServiceIdL(KUidMsgTypeSmartMessage, iBioServiceId));
+	if (err)
+		Printf(_L("No existing SMS services found!\n"));
+	}
+
+void CBioTestUtils::InstallMtmGroupsL()
+	{
+	InstallMtmGroupL(KDataComponentFileName);
+	}
+
+void CBioTestUtils::CreateServerMtmRegsL()
+	{
+	CreateBioServerMtmRegL();
+	}
+
+//
+// stuff to generate test BIO messages
+//
+
+EXPORT_C CMsvEntrySelection* CBioTestUtils::GenerateMessagesL()
+	{
+	return GenerateMessagesL(KBIOTxtFilePath);
+	}
+
+EXPORT_C CMsvEntrySelection*  CBioTestUtils::GenerateMessagesL(const TDesC& aFileDirectory, TBool aLogCreationDetails)
+	{
+	TBufC<KMaxFileName> currentFile;
+	TMsvId messageId;
+	TBIOMessageType currentMsgType;
+
+	CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection();
+	CleanupStack::PushL(selection);
+
+	TInt err = iFs.GetDir(aFileDirectory, KEntryAttMatchMask, ESortByName, iDir);
+	if (err == KErrPathNotFound)
+		{
+		TInt makeDirErr = iFs.MkDirAll(aFileDirectory);	
+		makeDirErr==KErrNone ? User::Leave(KErrNotFound): User::Leave(makeDirErr);
+		}
+	else if (err!=KErrNone)
+		{
+		User::Leave(err);
+		}
+
+	// Set the session path for the RFs
+	SetSessionPath(aFileDirectory);
+	if (iDir) 
+		delete iDir;
+	User::LeaveIfError(iFs.GetDir(_L("*.txt"), KEntryAttNormal, ESortByName, iDir));
+    TInt count = iDir->Count();
+    if(count == 0)
+        {
+        User::Leave(KErrNotFound);   // No files to process
+        }
+
+	TBuf<60> outputBuf;
+
+	for(TInt loop = 0; loop < count; loop++)
+		{
+		currentFile=( (*iDir)[iFilesProcessed].iName );
+		// Not processed all the messages - so keep the current state
+		iFilesProcessed++;   // Here because need to update the counter promptly
+		currentMsgType = SetMessageType(currentFile);
+		if (currentMsgType!=ENoMessage) // skip any dodgy filenames
+			{
+			messageId = CreateBIOEntryFromFileL( currentFile,currentMsgType);
+			selection->AppendL(messageId);
+			TPtrC tempPtr = (currentFile.Des() );
+			if (aLogCreationDetails)
+				{
+				outputBuf.Format(_L("TMsvId  %d   -    %S"), messageId, &tempPtr);
+				WriteComment(outputBuf);
+				}
+			}
+		}
+	CleanupStack::Pop(); // selection
+	return selection;
+    }
+
+EXPORT_C TBIOMessageType CBioTestUtils::SetMessageType(const TDesC& aFileName)
+	{
+
+	// Check each file prefix in turn with the filename passed as a parameter. 
+	// If cannot find the correct type set to ENoMessage to indicate an error. 
+	// GenerateNextMessage will then skip the file!
+
+	if (aFileName.MatchF(KBIOIapPrefix)==0)  // File starts with "iap"
+		{
+		return EBioIapSettingsMessage;
+		}
+	if(aFileName.MatchF(KBIOEnpPrefix)==0) // File name starts "enp"
+		{
+		return EBioEnpMessage;
+		}
+	if (aFileName.MatchF(KBIORingTonePrefix)==0)//Filename begins "rtone"
+		{
+		return EBioRingTonesMessage;
+		}
+	if (aFileName.MatchF(KBIOOpLogoPrefix)==0)	// Filename begins "oplogo"
+		{
+		return EBioOpLogoMessage;
+		}
+	if (aFileName.MatchF(KBIOcBusinessCardPrefix)==0)// Filename begins "cbc"
+		{
+		return EBioCompBusCardMessage;
+		}
+	if (aFileName.MatchF(KBIOvCardPrefix)==0)
+		{
+		return EBiovCardMessage;
+		}
+	if (aFileName.MatchF(KBIOvCalenderPrefix)==0)
+		{
+		return EBiovCalenderMessage;
+		}
+	if (aFileName.MatchF(KBIOWappPrefix)==0)
+		{
+		return EBioWAPSettingsMessage;
+		}
+	// if we've reached this point it's an unknown filename 
+	return ENoMessage;
+	}
+
+EXPORT_C void CBioTestUtils::DoAppendVariantName(TDes& aFileName)
+	{
+#if defined(__WINS__) && defined(__WINSCW__)
+	aFileName.Append(_L(".WINSCW."));
+#elif(__WINS__)
+	aFileName.Append(_L(".WINS."));
+#endif
+#if (defined(__THUMB__) || defined(__MARM_THUMB__))
+	aFileName.Append(_L(".THUMB."));
+#endif
+#if (defined(__ARMI__) || defined(__MARM_ARMI__))
+	aFileName.Append(_L(".ARMI."));
+#endif
+#if (defined(__ARM4__) || defined(__MISA__) || defined(__MARM_ARM4__))
+	aFileName.Append(_L(".ARM4."));
+#endif
+
+#if defined(_DEBUG)
+	aFileName.Append(_L("DEB."));
+#else
+	aFileName.Append(_L("REL."));
+#endif
+
+	aFileName.Append(_L("LOG"));
+	}
+
+//
+// Create a return the appropriate parser for the biomsg with id 
+//
+EXPORT_C CBaseScriptParser2* CBioTestUtils::CreateParserL(TMsvId aBioMsgId)
+	{
+	TMsvEntry myBioEntry;
+
+	if(iClientServer==EClientSide)
+		{
+		iMsvEntry->SetEntryL(aBioMsgId);
+		myBioEntry = iMsvEntry->Entry();
+		}
+	else
+		{
+		User::Leave(KErrNotSupported);
+		}
+
+	// check its the right type
+	if(myBioEntry.iMtm.iUid != KUidMsgTypeSmartMessage.iUid)
+		User::Leave(KBspInvalidMessage);
+
+	return CreateParserTypeL(myBioEntry.iBioType);
+	}
+
+EXPORT_C CBaseScriptParser2* CBioTestUtils::CreateParserTypeL(TInt32 aBioMsgType)
+	{
+	// get the bio type and create the parser
+	TUid messageUid = TUid::Uid(aBioMsgType);
+
+	// look up identification for parser
+	TFileName parserDllName(iBioDb->GetBioParserNameL(messageUid));
+
+	if (iRegisteredParserDll)  // Already have an old RegParserDll, delete it to stop memory leak.
+		{
+		delete iRegisteredParserDll;
+		iRegisteredParserDll = NULL;
+		}
+
+    iRegisteredParserDll = CRegisteredParserDll::NewL(parserDllName); // Create a new RegParserDll
+
+    RLibrary parserlibrary;
+    User::LeaveIfError(iRegisteredParserDll->GetLibrary(iFs, parserlibrary));
+
+    typedef CBaseScriptParser2* (*NewParserL)(CRegisteredParserDll& aRegisteredParserDll, CMsvEntry& aEntry, RFs& aFs);
+
+    TInt entrypointordinalnumber=1; // The one and only entry point
+    TLibraryFunction libFunc=parserlibrary.Lookup(entrypointordinalnumber);
+    if (libFunc==NULL)
+        User::Leave(KErrBadLibraryEntryPoint);
+    NewParserL pFunc=(NewParserL) libFunc;
+    TInt refcount=iRegisteredParserDll->DllRefCount();
+    CBaseScriptParser2* parser=NULL;
+    TRAPD(ret,parser=((*pFunc)(*iRegisteredParserDll, *iMsvEntry, iFs)));
+    if ((ret!=KErrNone) && (iRegisteredParserDll->DllRefCount()==refcount))
+        iRegisteredParserDll->ReleaseLibrary();
+
+	User::LeaveIfError(ret);
+    return parser;
+	}
+
+EXPORT_C TPtrC CBioTestUtils::MessageBodyL(TMsvId aBioMsgId)
+	{
+	CMsvStore* store = NULL;
+	if(iClientServer==EServerSide)
+		{
+		User::LeaveIfError(iServerEntry->SetEntry(aBioMsgId));
+		if(iServerEntry->Entry().iMtm.iUid != KUidMsgTypeSmartMessage.iUid)
+			User::Leave(KBspInvalidMessage);
+		store =  iServerEntry->ReadStoreL();
+		}
+	else
+		{
+		iMsvEntry->SetEntryL(aBioMsgId);
+		if(iMsvEntry->Entry().iMtm.iUid != KUidMsgTypeSmartMessage.iUid)
+			User::Leave(KBspInvalidMessage);
+		store = iMsvEntry->ReadStoreL();
+		}
+    //  Extract the body text or leave false if not
+	CleanupStack::PushL(store);
+	CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
+    CleanupStack::PushL(paraFormatLayer);
+    CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
+    CleanupStack::PushL(charFormatLayer);
+    CRichText* richText = CRichText::NewL(paraFormatLayer, charFormatLayer);
+    CleanupStack::PushL(richText);
+
+	store->HasBodyTextL() ? store->RestoreBodyTextL(*richText) : User::Leave( KErrNotFound);
+	
+	TInt messageLength = richText->DocumentLength();
+
+	delete iMessageBody;
+	iMessageBody = HBufC::NewL(messageLength);
+	TPtr messDes = iMessageBody->Des();
+
+	TInt length = messDes.Length();
+	while(length < messageLength)
+		{
+		TPtrC desc = richText->Read(length, messageLength-length);
+		messDes.Append(desc);
+		length+=desc.Length();
+		}
+
+	CleanupStack::PopAndDestroy(4);	// store, text, charFormatLayer, paraFormatLayer 
+	return messDes;
+	}
+
+EXPORT_C void CBioTestUtils::LogExtractedFieldsL(TMsvId aMessage)
+	{
+	// make sure we've got the right entry
+	CMsvStore* store = NULL;
+	if(iClientServer==EServerSide)
+		{
+		User::LeaveIfError(iServerEntry->SetEntry(aMessage));
+		if(iServerEntry->Entry().iMtm.iUid != KUidMsgTypeSmartMessage.iUid)
+			User::Leave(KBspInvalidMessage);
+		store =  iServerEntry->ReadStoreL();
+		}
+	else
+		{
+		iMsvEntry->SetEntryL(aMessage);
+		if(iMsvEntry->Entry().iMtm.iUid != KUidMsgTypeSmartMessage.iUid)
+			User::Leave(KBspInvalidMessage);
+		store = iMsvEntry->ReadStoreL();
+		}
+    //  Extract the body text or leave false if not
+	CleanupStack::PushL(store);
+
+	// try to get our array of parsed fields
+	RMsvReadStream in;
+	in.OpenLC( *store, KUidMsvBIODataStream );
+	InternalizeL(in);
+	CleanupStack::PopAndDestroy();
+
+	HBufC* fieldBuf  = NULL;
+	TInt length = 0;
+	WriteComment(_L("Extracted fields"));
+	for(TInt loop = 0; loop < iTestParsedFieldArray->Count(); loop++)
+		{
+		CParsedField& field = *(*iTestParsedFieldArray)[loop];
+		length = (field.FieldName().Length() + field.FieldValue().Length() + 1);
+
+		delete fieldBuf;
+		fieldBuf = HBufC::NewL(length);
+		TPtr des = fieldBuf->Des();
+		des.Append(field.FieldName());
+		des.Append(KCharSpace);
+		des.Append(field.FieldValue());
+		
+		//FieldValue may be bigger than '0x100' i.e logging script
+		//this may exeede max buffer, so we need to break it into chuncks
+		//of 64 chars and log the chuncks in sequence.
+		TInt desLength = des.Length();
+		TInt BufSize=64;
+		if (desLength > BufSize)
+			{
+			TBuf<64> tempBuf;
+			TInt count=0;
+			while(count <= desLength)
+				{
+				if(desLength-count > BufSize )
+					tempBuf= des.Mid(count,BufSize);
+				else
+					tempBuf= des.Mid(count,desLength-count);
+
+				WriteComment(tempBuf);
+				count+=BufSize;
+				}
+			}
+		else
+			WriteComment(des);
+
+		}
+	delete fieldBuf;
+	CleanupStack::PopAndDestroy();
+	}
+
+
+void CBioTestUtils::InternalizeL(RMsvReadStream& aReadStream)
+	{
+	if(iTestParsedFieldArray)
+		{
+		iTestParsedFieldArray->ResetAndDestroy();
+		delete iTestParsedFieldArray;
+		iTestParsedFieldArray=NULL;
+		}
+
+	iTestParsedFieldArray = new(ELeave) CArrayPtrSeg<CParsedField>(16);
+
+	CParsedField* parsedField = NULL;
+	TInt count = aReadStream.ReadUint8L();
+	for (TInt i=0; i < count; i++)
+		{
+		parsedField = new (ELeave) CParsedField();
+		TRAPD(err, parsedField->InternalizeL(aReadStream))
+		if(err)
+			{
+			delete parsedField; //deletes the last allocated object, privious ones will be deleted by iParsedFieldArray->ResetAndDestroy()
+			User::Leave(err);
+			}
+		iTestParsedFieldArray->AppendL(parsedField);
+		}
+	}
+
+EXPORT_C CArrayPtrSeg<CParsedField>& CBioTestUtils::ParsedFieldArray()
+	{
+	return *iTestParsedFieldArray;
+	}