// 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 "httptestutils.h"
#include "httptestcore.h"
#if !defined __E32BASE_H__
#include <e32base.h>
#endif
// for StartC32()
#if !defined __C32COMM_H__
#include <c32comm.h>
#endif
#if !defined __IN_SOCK_H__
#include <in_sock.h>
#endif
//
// Constants
_LIT(KTestPanic, "HttpTestUtils");
const TInt KFailedTestsGranularity = 10;
const TInt KMaxLogEntrySize = 256;
#if defined (__WINS__)
#define PDD_NAME _L("ECDRV")
#else
#define PDD_NAME _L("EUART1")
#define PDD2_NAME _L("EUART2")
#define PDD3_NAME _L("EUART3")
#define PDD4_NAME _L("EUART4")
#endif
#define LDD_NAME _L("ECOMM")
const TInt KMaxTempBuffize = 256;
_LIT(KTestFileInputBase, "HttpTest");
_LIT(KPathSep,"\\");
//
// CHTTPTestUtils
//
CHTTPTestUtils::CHTTPTestUtils(const TDesC& aTitle)
: iTest(aTitle)
//
// Default c'tor
{
iTest.Title();
iCanStartTest = ETrue;
}
CHTTPTestUtils::~CHTTPTestUtils()
//
// D'tor
{
TTime endtime;
endtime.UniversalTime();
// Do resource handle leak test?
if (iDoResourceLeakTest)
ResourceLeakTest();
// End of tests - see if failed or ok
if (iFailedTests->Count())
{
TestHarnessFailed();
}
else
{
TestHarnessComplete();
}
// Log finish time
TDateTime t = endtime.DateTime();
LogIt(_L("Ended @ %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
TTime difftime(endtime.Int64() - iStartTime.Int64());
t = difftime.DateTime();
LogIt(_L("Execution time %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
// Close test harness
iTest.Close();
// Cleanup
iFailedTests->ResetAndDestroy();
delete iFailedTests;
// Close fileserver connection
iFs.Close();
}
EXPORT_C CHTTPTestUtils* CHTTPTestUtils::NewLC(const TDesC& aTitle)
//
// Static factory c'tor
{
CHTTPTestUtils* self = new (ELeave) CHTTPTestUtils(aTitle);
CleanupStack::PushL(self);
self->ConstructL(aTitle);
return self;
}
EXPORT_C CHTTPTestUtils* CHTTPTestUtils::NewL(const TDesC& aTitle)
//
// Static factiry c'tor
{
CHTTPTestUtils* self = CHTTPTestUtils::NewLC(aTitle);
CleanupStack::Pop();
return self;
}
void CHTTPTestUtils::CreateLogFiles(const TDesC& aTestName)
{
TBuf<128> logName(aTestName);
DefaultLogFileName(logName);
__OPEN_LOG2(logName);
logName.Append(_L(".SUMMARY"));
TInt error = iTestSummaryLogger.Connect();
if(error == KErrNone)
{
TParse p;
p.Set(logName, NULL, NULL);
iTestSummaryLogger.CreateLog(KHttpLogsDirName, p.NameAndExt(), EFileLoggingModeOverwrite);
iTestSummaryLogger.SetDateAndTime(ETrue, ETrue);
iTestSummaryLogger.Write(KTestHeader);
}
else
User::InfoPrint(_L("Log file create failed"));
}
void CHTTPTestUtils::ConstructL(const TDesC& aTitle)
//
// Non-trivial c'tor
{
iCurrentTest=NULL;
// Create iFailedTests
iFailedTests = new (ELeave) CArrayPtrFlat<CTestInfo> (KFailedTestsGranularity);
// Start up logging server connection
CreateLogFiles(aTitle);
iStartTime.UniversalTime();
TDateTime t = iStartTime.DateTime();
LogIt(_L("Started @ %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
// Find number of open resource handles
TInt processHandleCount=0;
RThread().HandleCount(processHandleCount,iStartHandleCount);
// Connect to file server for test scripts, ini-files etc.
User::LeaveIfError(iFs.Connect());
}
EXPORT_C void CHTTPTestUtils::JustStartTestL(const TDesC& aName)
{
if (iCanStartTest)
{
iCurrentTest= CTestInfo::NewL(aName, iTestCount, 0);
// Stop new test being started until this one has ended
iCanStartTest = EFalse;
}
else
{
// Panic client - bad usage - not allowed to nest tests
Panic(EBadStartTest);
}
}
EXPORT_C void CHTTPTestUtils::StartTestL(const TDesC& aName)
//
// Logs start of test aName
{
if (iCanStartTest)
{
// Add this test to failed test list - set errorcode to zero
CTestInfo* temp = CTestInfo::NewLC(aName, iTestCount + 1, 0);
iFailedTests->AppendL(temp);
CleanupStack::Pop(); // temp
iCurrentTest= temp;
// Increase RTest's test depth by Start-ing - increment test count
iTest.Start(aName);
++iTestCount;
// Stop new test being started until this one has ended
iCanStartTest = EFalse;
TBuf<KMaxFileName + 4> buf;
buf.Format(KTestStartingWithDesc, iTestCount, &aName);
WriteComment(buf);
// Reset iStepNumber - start at 1
iStepNumber = 1;
}
else
{
// Panic client - bad usage - not allowed to nest tests
Panic(EBadStartTest);
}
}
EXPORT_C void CHTTPTestUtils::NextStep(const TDesC& aStepName)
//
// Logs the next step in a test - for informative use.
{
if (!iCanStartTest)
{
TBuf<KMaxFileName + 4> buf;
buf.Format(KNextTestStepWithDesc, iTestCount, iStepNumber, &aStepName);
WriteComment(buf);
iTest.Next(aStepName);
++iStepNumber;
}
else
{
// Panic client - bad usage - test not started
Panic(EBadStartTest);
}
}
EXPORT_C void CHTTPTestUtils::JustEndTest()
{
// Allow new test to start
iCurrentTest = NULL;
iCanStartTest = ETrue;
}
EXPORT_C void CHTTPTestUtils::EndTest(TInt aErrorCode)
//
// Logs end of test
{
if (!iCanStartTest)
{
// Get ptr to this test's entry in failed list - will be the last entry
TBuf<KMaxFileName + 4> buf;
TInt index = iFailedTests->Count();
CTestInfo* ptr = iFailedTests->At(--index);
if (aErrorCode)
{
// Set the error code
ptr->SetErrorCode(aErrorCode);
buf.Format(KTestFailed, iTestCount, aErrorCode);
iTest.Printf(KRTestFailed, aErrorCode);
}
else
{
// Remove entry from list of failed tests
delete ptr;
iFailedTests->Delete(index);
buf.Format(KTestPassed, iTestCount);
}
WriteComment(buf);
// Decrease RTest's test depth by End-ing
iTest.End();
// Allow new test to start. There's no iCurrentTest until StartTestL is invoked again
iCurrentTest = NULL;
iCanStartTest = ETrue;
}
else
{
// Panic client - bad usage - test not started
Panic(EBadEndTest);
}
}
EXPORT_C void CHTTPTestUtils::LogIt(TRefByValue<const TDesC> aFmt, ...)
// Messages to the front end emulator and to the WAP log
{
VA_LIST list;
VA_START(list,aFmt);
TBuf<2*KMaxFileName> buf;
buf.Zero();
if(iCurrentTest)
buf.Append(iCurrentTest->Name());
buf.Append(_L("> "));
buf.AppendFormatList(aFmt,list,this);
VA_END(list);
//write to the console and file, if not silent
if (!iSilent)
WriteComment(buf);
else // otherwise log to the file only
__LOG(buf);
}
EXPORT_C void CHTTPTestUtils::Overflow(TDes& aDes)
{
_LIT(KErrOverflowMsg, "...");
if( aDes.MaxLength() >= KErrOverflowMsg().Length() + aDes.Length() )
aDes.Append(KErrOverflowMsg);
}
EXPORT_C void CHTTPTestUtils::operator()(TInt aResult,TInt aLineNum)
//
// Overload operator ()
{
iTest(aResult, aLineNum);
}
EXPORT_C void CHTTPTestUtils::operator()(TInt aResult)
//
// Overload operator ()
{
iTest(aResult);
}
EXPORT_C void CHTTPTestUtils::PressAnyKey()
//
// Request a key press from user and wait - unless we are running a script or we are being silent
{
if (!iScriptRunning && !iSilent)
{
iTest.Printf(TRefByValue<const TDesC>_L("\nPress a key"));
iTest.Getch();
}
}
EXPORT_C void CHTTPTestUtils::DumpData(const TDesC8& aData, TBool logIt)
//
// Do a formatted dump of binary data, optionally logging it
{
// Iterate the supplied block of data in blocks of 16 bytes
TInt pos = 0;
TBuf<KMaxLogEntrySize> logLine;
TBuf<KMaxLogEntrySize> anEntry;
while (pos < aData.Length())
{
anEntry.Format(TRefByValue<const TDesC>_L("%04x : "), pos);
logLine.Append(anEntry);
// Hex output
TInt offset;
for (offset = 0; offset < 16; offset++)
{
if (pos + offset < aData.Length())
{
TInt nextByte = aData[pos + offset];
anEntry.Format(TRefByValue<const TDesC>_L("%02x "), nextByte);
logLine.Append(anEntry);
}
else
{
anEntry.Format(TRefByValue<const TDesC>_L(" "));
logLine.Append(anEntry);
}
}
anEntry.Format(TRefByValue<const TDesC>_L(": "));
logLine.Append(anEntry);
// Char output
for (offset = 0; offset < 16; offset++)
{
if (pos + offset < aData.Length())
{
TInt nextByte = aData[pos + offset];
if ((nextByte >= 32) && (nextByte <= 127))
{
anEntry.Format(TRefByValue<const TDesC>_L("%c"), nextByte);
logLine.Append(anEntry);
}
else
{
anEntry.Format(TRefByValue<const TDesC>_L("."));
logLine.Append(anEntry);
}
}
else
{
anEntry.Format(TRefByValue<const TDesC>_L(" "));
logLine.Append(anEntry);
}
}
if (logIt)
{
LogIt(TRefByValue<const TDesC>_L("%S"), &logLine);
}
else if (!iSilent)
{
iTest.Printf(TRefByValue<const TDesC>_L("%S\n"), &logLine);
}
logLine.Zero();
// Advance to next 16 byte segment
pos += 16;
}
}
EXPORT_C void CHTTPTestUtils::GetAnEntry(const TDesC& ourPrompt, TDes& currentstring)
//
// Get an input string from the user, displaying a supplied prompt and default string value
{
// If we're scripting, try reading from script first
TInt readScriptErr = KErrNotFound;
if (iScriptRunning)
{
readScriptErr = ReadLineFromScript(currentstring);
}
if (!readScriptErr)
return;
// Either not scripting, or hit end of script - continue with user input
TBuf16<KMaxUserEntrySize> ourLine;
TBuf<KMaxUserEntrySize> tempstring; //tempstring is a unicode descriptor
//create a temporary buffer where the
//unicode strings are stored in order to
//be displayed
ourLine.Zero ();
tempstring.Copy(currentstring); //Copy current string to Unicode buffer
TKeyCode key = EKeyNull; //current string buffer is 8 bits wide.
//Unicode string bufffer (tempstring) is 16 bits wide.
for (;;)
{
if (ourLine.Length () == 0)
{
iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
iTest.Console()->Printf (_L ("%S"), &ourPrompt);
if (tempstring.Length () != 0) //get tempstring's number of items
iTest.Console()->Printf (_L (" = %S"), &tempstring); //if not zero print them to iTest.Console()
iTest.Console()->Printf (_L (" : "));
iTest.Console()->ClearToEndOfLine ();
}
key = iTest.Getch();
if (key == EKeyBackspace)
{
if (ourLine.Length() !=0)
{
ourLine.SetLength(ourLine.Length()-1);
iTest.Console()->Printf (_L ("%c"), key);
iTest.Console()->SetPos(iTest.Console()->WhereX(),iTest.Console()->WhereY());
iTest.Console()->ClearToEndOfLine();
} // end if (ourLine.Length() !=0)
} // end if (key == KeyBackSpace)
if (key == EKeyDelete)
{
ourLine.Zero();
iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
iTest.Console()->ClearToEndOfLine ();
tempstring.Copy(ourLine);
break;
}
if (key == EKeyEnter)
break;
if (key < 32)
{
continue;
}
ourLine.Append (key);
iTest.Console()->Printf (_L ("%c"), key);
iTest.Console()->SetPos(iTest.Console()->WhereX(),iTest.Console()->WhereY());
iTest.Console()->ClearToEndOfLine();
if (ourLine.Length () == ourLine.MaxLength ())
break;
} // end of for statement
if ((key == EKeyEnter) && (ourLine.Length () == 0))
tempstring.Copy (currentstring); //copy contents of 8 bit "ourLine" descriptor
iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
iTest.Console()->ClearToEndOfLine ();
iTest.Console()->Printf (_L ("%S"), &ourPrompt);
if ((key == EKeyEnter) && (ourLine.Length() !=0))
tempstring.Copy(ourLine);
if (tempstring.Length () != 0) //if temstring length is not zero
{
iTest.Console()->Printf (_L (" = %S\n"), &tempstring); //print the contents to iTest.Console()
LogIt(_L ("%S = %S\n"), &ourPrompt, &tempstring);
}
else
//iTest.Console()->Printf (_L (" is empty"));
iTest.Console()->Printf (_L ("\n"));
currentstring.Copy(tempstring); //copy 16 bit tempstring descriptor back
}
EXPORT_C TInt CHTTPTestUtils::GetSelection(const TDesC& ourPrompt, const TDesC& validChoices)
//
// Present the user with a list of options, and get their selection
{
// If we're scripting, try reading from script first
TInt readScriptErr = KErrNotFound;
if (iScriptRunning)
{
TBuf<1> oneCharBuf;
readScriptErr = ReadLineFromScript(oneCharBuf);
if (!readScriptErr)
{
return validChoices.Locate((TChar)oneCharBuf[0]);
}
}
// Either not scripting, or hit end of script - continue with user input
TKeyCode key = EKeyNull;
iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
Print(ourPrompt);
iTest.Console()->Printf(_L("[%S] :"), &validChoices);
TInt retVal = KErrNotFound;
while (retVal == KErrNotFound)
{
key = iTest.Getch();
// Check that key is in the list of valid choices
retVal = validChoices.Locate((TChar)key);
}
iTest.Console()->Printf(_L("%c\n\n"), key);
return retVal;
}
EXPORT_C void CHTTPTestUtils::SetScript(RFile& scriptFile)
//
// Sets the file to be used for a test script - ie. a file that contains commands used by
// GetEntry() and GetSelection()
{
iScriptFile = &scriptFile;
iScriptRunning = ETrue;
LogIt(_L("***SCRIPT STARTING***\n"));
}
EXPORT_C void CHTTPTestUtils::InitCommsL()
{
TInt ret = User::LoadPhysicalDevice(PDD_NAME);
User::LeaveIfError(ret == KErrAlreadyExists?KErrNone:ret);
#ifndef __WINS__
ret = User::LoadPhysicalDevice(PDD2_NAME);
ret = User::LoadPhysicalDevice(PDD3_NAME);
ret = User::LoadPhysicalDevice(PDD4_NAME);
#endif
ret = User::LoadLogicalDevice(LDD_NAME);
User::LeaveIfError(ret == KErrAlreadyExists?KErrNone:ret);
ret = StartC32();
User::LeaveIfError(ret == KErrAlreadyExists?KErrNone:ret);
}
EXPORT_C void CHTTPTestUtils::HoldOpenConnectionL()
{
RSocketServ sockSrvHnd;
TInt err = sockSrvHnd.Connect();
if (err != KErrNone)
{
User::Leave(err);
}
// Start UDP protocol stack
TProtocolDesc desc;
_LIT(KUdp, "udp");
err = sockSrvHnd.FindProtocol(KUdp(), desc);
User::LeaveIfError(err);
TRequestStatus stat;
sockSrvHnd.StartProtocol(desc.iAddrFamily, desc.iSockType, desc.iProtocol, stat);
User::WaitForRequest(stat);
}
EXPORT_C void CHTTPTestUtils::ReleaseConnectionL()
{
RSocketServ sockSrvHnd;
TInt err = sockSrvHnd.Connect();
if (err != KErrNone)
{
User::Leave(err);
}
// Stop UDP protocol stack
TProtocolDesc desc;
_LIT(KUdp, "udp");
err = sockSrvHnd.FindProtocol(KUdp(), desc);
User::LeaveIfError(err);
TRequestStatus stat;
sockSrvHnd.StopProtocol(desc.iAddrFamily, desc.iSockType, desc.iProtocol, stat);
User::WaitForRequest(stat);
}
TInt CHTTPTestUtils::ReadLineFromScript(TDes& aBuffer)
//
// Reads the next line from the script file, and sets the passed-in descriptor with its contents.
// Returns KErrNone if reading succeeded; KErrNotFound if the EOF was reached. When EOF is reached,
// the file is closed.
{
// *********************************
// Assume script is 8-bit text file
// *********************************
TBool isAComment = ETrue;
TInt err = KErrNone;
TBuf<512> line;
while (isAComment && !err)
{
TFileText text;
text.Set(*iScriptFile);
line.SetLength(0);
for(;;)
{
TBuf8<2> c;
err = iScriptFile->Read(c,1);
if (err && err != KErrEof)
{
iTest.Printf(_L("Error reading file: %d\n"), err);
break;
}
if (c.Length() == 0)
{
err = KErrEof;
break;
}
else
{
if (c[0] == '\n') // break out if it is CR
break;
else if (c[0] != 0x0d) // otherwise append the char, _unless_ it is a LF
line.Append(c[0]);
}
}
if (err == KErrNone && line.Locate('/') != 0) // comment (only works if it's the first character)
{
isAComment = EFalse;
}
}
// The line read is not a comment, or have hit end of file
if (!err)
{
// copy to passed in descriptor, but do not allow an overflow
aBuffer.Copy(line.Left(aBuffer.MaxLength()));
LogIt(_L("***SCRIPT : read command '%S' ***\n"), &aBuffer);
}
else
{
iScriptFile->Close();
err = KErrNotFound;
iScriptRunning = EFalse;
LogIt(_L("***SCRIPT ENDED***\n"));
}
return err;
}
void CHTTPTestUtils::Panic(TInt aPanic)
//
// Panic the client program.
{
User::Panic(KTestPanic,aPanic);
}
void CHTTPTestUtils::TestHarnessComplete()
//
// Test harness completed without failures
{
WriteComment(KTestHarnessCompleted);
}
void CHTTPTestUtils::TestHarnessFailed()
//
// Test harness has a failure - log information
{
TBuf<KMaxFileName + 4> buf;
buf.Format(KTestHarnessFailed, iFailedTests->Count());
WriteComment(buf);
// Log fialed tests' information
for (TInt ii=0; ii<iFailedTests->Count(); ++ii)
{
CTestInfo* failed = iFailedTests->At(ii);
TPtrC name = failed->Name();
LogIt(KTestFailInfo, failed->Number(), &name, failed->ErrorCode());
}
}
void CHTTPTestUtils::ResourceLeakTest()
//
// Creates a new test that fails if any there are any leaked resource handles
{
// Start new test
_LIT(KResourceTestName, "Resource Handle Leak Test");
TRAPD(error,StartTestL(KResourceTestName));
if (error !=KErrNone)
Panic(EBadStartTest);
// Find number of opened handles
TInt processHandleCount=0;
TInt threadHandleCount=0;
RThread().HandleCount(processHandleCount,threadHandleCount);
TInt err = KErrNone;
TInt openHandleCount = iStartHandleCount-threadHandleCount;
if ( openHandleCount !=0)
{
err = KErrGeneral;
LogIt(_L("Number leaked handles is %D"), openHandleCount);
}
EndTest(err);
}
EXPORT_C
TInt CHTTPTestUtils::ResolveFile(const TDesC& aComponent, const TDesC& aFileName, TParse& aParseOut)
{
TFileName* savedPath = new TFileName;
TFileName* fileName = new TFileName;
if ((savedPath == NULL) || (fileName == NULL))
return KErrNoMemory;
fileName->Append(KPathSep);
fileName->Append(KTestFileInputBase);
fileName->Append(KPathSep);
fileName->Append(aComponent);
fileName->Append(KPathSep);
fileName->Append(aFileName);
// file finder will look in the session drive first, then Y->A,Z
// so set session drive to Y (save old and restore it afterwards)
iFs.SessionPath(*savedPath);
_LIT(KTopDrive,"Y:\\");
iFs.SetSessionPath(KTopDrive);
TFindFile file_finder(iFs);
TInt err = file_finder.FindByDir(*fileName,KNullDesC);
if(err==KErrNone)
aParseOut.Set(file_finder.File(),NULL,NULL);
iFs.SetSessionPath(*savedPath);
delete savedPath;
delete fileName;
return(err);
}
EXPORT_C
HBufC8* CHTTPTestUtils::ReadFileLC(const TDesC& aFile)
{
//Returns a HBufC8 with the contents of aFile
RFile file;
User::LeaveIfError(file.Open(iFs, aFile, EFileShareAny | EFileRead));
CleanupClosePushL(file);
TInt size = 0;
TInt err = file.Size(size);
if (err)
{
iTest.Printf(_L("ReadFileLC(%S) leaving with %d. Unable to size file\n"), &aFile, err);
User::Leave(err);
}
HBufC8* contents = HBufC8::NewLC(size + 4);
TPtr8 contentsPtr(contents->Des());
err = file.Read(0, contentsPtr);
if (err)
{
iTest.Printf(_L("ReadFileLC(%S) leaving with %d. Unable to read file\n"), &aFile, err);
User::Leave(err);
}
CleanupStack::Pop(); //contents
CleanupStack::PopAndDestroy(); //file
CleanupStack::PushL(contents);
return contents;
}
//
// CTestInfo
//
CHTTPTestUtils::CTestInfo::CTestInfo()
//
// Default c'tor
{
}
CHTTPTestUtils::CTestInfo::~CTestInfo()
//
// D'tor
{
delete iName;
}
CHTTPTestUtils::CTestInfo* CHTTPTestUtils::CTestInfo::NewLC(const TDesC& aName, TInt aNumber, TInt aErrorCode)
//
// Static factory c'tor
{
CTestInfo* self = new (ELeave) CTestInfo();
CleanupStack::PushL(self);
self->ConstructL(aName, aNumber, aErrorCode);
return self;
}
CHTTPTestUtils::CTestInfo* CHTTPTestUtils::CTestInfo::NewL(const TDesC& aName, TInt aNumber, TInt aErrorCode)
//
// Static factory c'tor
{
CTestInfo* self = NewLC(aName, aNumber, aErrorCode);
CleanupStack::Pop(); // self
return self;
}
void CHTTPTestUtils::CTestInfo::ConstructL(const TDesC& aName, TInt aNumber, TInt aErrorCode)
//
// Non-trivial c'tor
{
iName = aName.AllocLC();
CleanupStack::Pop(); // iName
iNumber = aNumber;
iErrorCode = aErrorCode;
}
void CHTTPTestUtils::CTestInfo::SetNameL(const TDesC& aName)
//
// Sets iName
{
HBufC* temp = aName.AllocLC();
CleanupStack::Pop(); // temp
delete iName;
iName = temp;
}
void CHTTPTestUtils::CTestInfo::SetNumber(TInt aNumber)
//
// Sets iNumber
{
iNumber = aNumber;
}
void CHTTPTestUtils::CTestInfo::SetErrorCode(TInt aErrorCode)
//
// Sets iErrorCode
{
iErrorCode = aErrorCode;
}
#ifndef EKA2
GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
//
// Main Dll entry point
{
return(KErrNone);
}
#endif // EKA2
void CHTTPTestUtils::Print(const TDesC& aDescriptor)
{
TBuf<KMaxTempBuffize> chunkOfPrompt;
TInt length = aDescriptor.Length();
TInt num=length/KMaxTempBuffize;
TInt rest=length%KMaxTempBuffize;
TInt iter;
if(num>0)
for(iter=0;iter<num;++iter)
{
chunkOfPrompt.Copy(aDescriptor.Mid(iter*KMaxTempBuffize,KMaxTempBuffize-1));
iTest.Console()->Printf(_L("%S "), & chunkOfPrompt);
}
chunkOfPrompt.Copy(aDescriptor.Mid(length-rest,rest));
iTest.Console()->Printf(_L("%S "), & chunkOfPrompt);
}