// Copyright (c) 2000-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 <e32test.h>#include <e32svr.h> // for RDebug::Print#include <e32std.h>#include <flogger.h>#include "t_wappush.h"#include "pushtests.h"#include <push/pushmessage.h>#include <ecom/ecom.h>// service setup includes...#include <msvstd.h>#include <msvids.h>#include "t_serviceutils.h"#include <pushentry.h>#include "cwappushfailmessagetest.h"_LIT(KPushMtmDatFile, "z:\\system\\mtm\\WapPushMtmU.dat");_LIT(KWapPushTestTitle,"WAP Push tests");_LIT(KPushLogDir, "push");_LIT(KPushLogFile, "WapPushLogging.txt");_LIT(KSpace, " ");_LIT(KStartTest,"Test Results");_LIT(KFinishedTest,"Tests Completed");_LIT(KTestDirectory,"C:\\Logs\\push\\");_LIT(KTest,"> TEST ");_LIT(KPassed," PASSED\n");_LIT(KFailed," Failed\n RTEST: FAIL :"); // RTEST: FAIL : required for the DABS RTest result parser to work_LIT (KOOMTestStep, "OOM Test step at %d\n" );LOCAL_D RTest test( KWapPushTestTitle );// Test harness requirements//// Uses an active object state machine to run tests.// Creates a Connection Manager object.// Creates a Dummy wap stack via CDummyWapStack::NewL()// Feeds a push message to Dummy wap stack // Starts Connection Manager - just add active object to scheduler and start?// Needs to know when completed - and callback?// Verifies that CPushMessage received is the same as sent// Closes/Destroys connection manager - delete?//// Note : // -To run the test harness on hardware, build the ROM image using // TWappush.iby file in \Wap-Browser\WapPush\rom\.. directory.// -Build the Wappush component and the TWappush test harness for DEBUG mode// -Create a folder c:\logs\push\.. to get the WappushLogging.txt logfile.// class CTestScheduler : public CActiveScheduler { virtual void Error(TInt anError) const; };void CTestScheduler::Error(TInt anError) const { TBuf<80> buf; _LIT(KComment, "!! Error - %d\n-> Test Scheduler error handler called"); buf.Format(KComment, anError); // Write to log file RFileLogger::Write(KPushLogDir, KPushLogFile, EFileLoggingModeAppend, buf); _LIT(KTestPanic,"CTestScheduler RunL leave"); User::Panic(KTestPanic,anError); }// cwappushtestenginevoid CWapPushTestEngine::DoCancel() { // cancel the current test if (iCurrentTest) iCurrentTest->Cancel(); }void CWapPushTestEngine::RunL() { switch (iState) { case EIdle: { if(iTest!=EFinished) { test.Start(_L("Starting Unit Test")); } TRAPD(err,RunNextTestL()) if(iTest!=EFinished) { test.End(); test.Close(); } if (err!=KErrNone) iConsole->Printf(KTextFailedTest); } break; case ERunningTest: break; case EShuttingDown: // Clear Out the Plugin Cache// CPluginServerClient* psc = CPluginServerClient::NewL();// psc->PluginFactory().ClearCache();// delete psc; CActiveScheduler::Stop(); break; } }/** * Static factory function for a new test engine */CWapPushTestEngine* CWapPushTestEngine::NewL() { CWapPushTestEngine* self = new(ELeave) CWapPushTestEngine(); CleanupStack::PushL(self); self->ConstructL(); CleanupStack::Pop(self); return self; }/** * Constructor for the test engine * Creates a console and sets itself active */void CWapPushTestEngine::ConstructL() { // Write to log file RFileLogger::Write(KPushLogDir, KPushLogFile, EFileLoggingModeAppend, KStartTest); RFileLogger::Write(KPushLogDir, KPushLogFile, EFileLoggingModeAppend, KSpace); iConsole = Console::NewL(KWapPushTestTitle,TSize(KConsFullScreen,KConsFullScreen)); // set up service BEFORE active scheduler... InitialiseMsgServiceL(); // CActiveScheduler::Add(this); SetActive(); TRequestStatus* stat = &iStatus; User::RequestComplete(stat,KErrNone); }/** * Destructor for CWapPushTestEngine * Cancels any outstanding requests and deletes member variables */CWapPushTestEngine::~CWapPushTestEngine() { Cancel(); delete iCurrentTest; delete iConsole; }/** * This should be called by tests to indicate that they have * completed and whether they were sucessful or not */void CWapPushTestEngine::TestCompleted(TInt aResult) { if (aResult==KErrNone) { TBuf16<124> log; log = iCurrentTest->TestName(); log.Append(KTest); log.Append(iCurrentTest->TestName()); log.Append(KPassed); test.Printf(log); iState=EIdle; iTest=(TTest)(iTest+1); } else { TBuf16<124> log1; log1 = iCurrentTest->TestName(); log1.Append(KTest); log1.Append(iCurrentTest->TestName()); log1.Append(KFailed); test.Printf(log1); test.Printf(KTextFailedTest); iConsole->Printf(KTextFailedTest); iState = EShuttingDown; } // set active again TRequestStatus* stat = &iStatus; User::RequestComplete(stat,KErrNone); SetActive(); }/** * Run the next test * The switch statement lists all tests to be run * */void CWapPushTestEngine::RunNextTestL() { // delete any old tests delete iCurrentTest; iCurrentTest=NULL; // switch (iTest) { case EFailMessageTest: test.Next( _L("Test - Failing Messages (were causing panics) started")); iCurrentTest = new (ELeave)CWapPushFailMessageTest(); break; case ESIAMessage: test.Next( _L("Test - Service Intiation Application started")); iCurrentTest = new (ELeave) CWapPushSIAMessageTest(); break; case EUnknownMessage: test.Next( _L("Test - Unknown Handler Test started")); iCurrentTest = new (ELeave) CWapPushUnkMessageTest(); break; case ESLMessage: test.Next( _L("Test - Service Loading started")); iCurrentTest = new (ELeave) CWapPushSLMessageTest(); break; case ESLCMessage: test.Next (_L("Test - Service Loading Content started") ); iCurrentTest = new ( ELeave )CWapPushSLCMessageTest(); break; case ESIMessage: test.Next( _L("Test - Service Indication started")); iCurrentTest = new (ELeave) CWapPushSIMessageTest(); break; case ESICMessage: test.Next( _L("Test - Service Indication Content started")); iCurrentTest = new (ELeave) CWapPushSICMessageTest(); break; case EMultipartMixed: test.Next( _L("Test - Multi-part Mixed Message Test started")); iCurrentTest = new (ELeave) CWapPushMMMessageTest(); break; case EMultipartRelated: test.Next( _L("Test - Multi-part Related Message Test started")); iCurrentTest = new (ELeave) CWapPushMRMessageTest(); break; case EMultipartAlternative: test.Next( _L("Test - Multi-part Alternative Message Test started")); iCurrentTest = new (ELeave) CWapPushMAMessageTest(); break; case EReleaseThree: test.Next( _L("Test - Release Three started")); iCurrentTest = new (ELeave) CWapPushR3Test(); break; case ECorruptMsgs: test.Next( _L("Test - Corrupt Message Test started")); iCurrentTest = new (ELeave) CWapPushCorruptMessageTest(); break; case EClientMtmFind: test.Next( _L("Test - WapPushClientMtm Find Test started")); iCurrentTest = new (ELeave) CWapClientMtmFindTest(); break; case EINC081489: test.Next( _L("Duplicate SI messages [CINC081489]")); iCurrentTest = new (ELeave) CINC081489(); break; case EInvalidDTDMessage: test.Next ( _L("Invalid WAP DTD Message Test") ); iCurrentTest = new ( ELeave) CInvalidWAPDTDMessages(); break; case EDRMMessage: test.Next( _L("Test - DRM started")); iCurrentTest = new (ELeave) CWapPushDRMMessageTest(); break; case EReleaseTwo: default: // We've finished - set status to shut down and complete our own request SetPriority(EPriorityIdle); // Write to log file RFileLogger::Write(KPushLogDir, KPushLogFile, EFileLoggingModeAppend, KSpace); RFileLogger::Write(KPushLogDir, KPushLogFile, EFileLoggingModeAppend, KFinishedTest); iConsole->Printf(KTextFinishedTest); iState = EShuttingDown; TRequestStatus* stat = &iStatus; User::RequestComplete(stat,KErrNone); SetActive(); return; } iCurrentTest->SetEngine(this); iState = ERunningTest; iCurrentTest->BeginTest(); } /** * print a descriptor to the console - prefixes aString text with aName * @param aName the name of the test * @param aString the text to be displays */void CWapPushTestEngine::Printf(const TDesC& aName, const TDesC& aString) { TBuf<12> format; format.Zero(); format.AppendNum((TInt)iTest); _LIT(KTextCoreFormat,".%S: %S\n"); format.Append(KTextCoreFormat); iConsole->Printf(format,&aName,&aString); }/** * get a character from the console */TKeyCode CWapPushTestEngine::Getch() { return iConsole->Getch(); }/** * return a reference to the console used by the test harness */CConsoleBase& CWapPushTestEngine::Console() const { return *iConsole; }/** connect to the push message service if no message service set up then create one else use existing service and remove any existing messages */void CWapPushTestEngine::InitialiseMsgServiceL() { CMsvEntrySelection* idArray = new (ELeave) CMsvEntrySelection(); CleanupStack::PushL(idArray); CWapPushTestMsgUtils* msgUtils = CWapPushTestMsgUtils::NewL(); CleanupStack::PushL(msgUtils); TMsvId pushService = KMsvNullIndexEntryId; TMsvId pushFolder = KMsvNullIndexEntryId; // uncomment this if you want to remove existing service entries //msgUtils->ClearExistingServiceEntriesL(KUidMtmWapPush); msgUtils->PushServiceIdL(pushService, idArray); if ((pushService == KMsvNullIndexEntryId) && (idArray->Count() ==0) ) // Found no service { pushService = msgUtils->CreateServiceL(); } // install mtm - leaves if found to already exist TRAP_IGNORE(msgUtils->InstallMtmGroupL(KPushMtmDatFile)); idArray->Reset(); msgUtils->PushFolderIdL(pushFolder, idArray); if ((pushFolder == KMsvNullIndexEntryId) && (idArray->Count() ==0) ) // Found no service pushFolder = msgUtils->CreatePushMsgFolderL(); //Clean out all previous push entries from under the Push Service Entry msgUtils->RemoveServiceEntryChildrenL(pushService); // Clean the push msg folder of existing entries msgUtils->RemoveEntriesFromLocalServiceFolderL(pushFolder, KUidMtmWapPush); // Clean the inbox of all existing Wap Push entries.... msgUtils->RemoveEntriesFromLocalServiceFolderL(KMsvGlobalInBoxIndexEntryId, KUidMtmWapPush); CleanupStack::PopAndDestroy(2); //idarray, msgUtils }/** Add the test to the active scheduler and set it active * by completing its own request */void CWapPushTest::BeginTest() { CActiveScheduler::Add(this); SetActive(); TRequestStatus* stat = &iStatus; User::RequestComplete(stat,KErrNone); }/** * Print a descriptor to the console * @param aString descriptor to print */void CWapPushTest::Printf(const TDesC& aString) { iEngine->Printf(TestName(),aString); }/** * Check a test result and panic if false * @param aTestResult the result to check * @param aLine the line number - can be provided by MSVC macro __LINE__ * #define TEST(A) Test(A,__LINE__) * TEST(err=KErrNone) */void CWapPushTest::Test(TInt aTestResult,TInt aLine) { if (!aTestResult) { User::Panic(TestName(),aLine); } }/*** Printf* * @param aDescription The text to print/log*/void CWapPushTest::WPLPrintf(const TDesC& aDescription) { const TInt KWatcherLogBuffer = 256; // Write to log file RFileLogger::Write(KPushLogDir, KPushLogFile, EFileLoggingModeAppend, aDescription); // Write to console _LIT(KPushLogFmt,"Push:%S\n"); TPtrC buf = aDescription.Left(Min(KWatcherLogBuffer, aDescription.Length())); iEngine->Console().Printf(KPushLogFmt,&buf); }/** * Takes the data in a Push Message and prints it to console and the logs it to file. * Uses the accessor functions of the CPushMessage class and this classes Printf function * to perform this. Currently 4 headers and the message body are displayed and * logged. The headers are: * PushID, Content-Type, X-Application-ID, Expiry Date, * * @param CPushMessage& aMessage * in: a reference to a Push Message. */void CWapPushTest::WPLPrintfL(CPushMessage& aMessage) { const TInt KWatcherLogBuffer=256; TBuf<KWatcherLogBuffer> buf; // Content type _LIT(KLogContentFmt,"Content Type : \t%S"); TPtrC contentPointer; aMessage.GetContentType(contentPointer); buf.Format(KLogContentFmt,&contentPointer); buf.Append('\n'); WPLPrintf(buf); // Date Field _LIT(KLogDateTimeFmt," %-B%:0%J%:1%T%:2%S%+B %D %N %Y %4 %5 %3"); _LIT(KLogDateFmt,"Date :\t%S"); TBool foundField; TTime timeValue; foundField = aMessage.GetHeaderField(EHttpDate, timeValue); if (foundField) { TRAPD(err, timeValue.FormatL(buf, KLogDateTimeFmt)); if (err == KErrNone) { TBuf<KWatcherLogBuffer> dateBuf; dateBuf.Format(KLogDateFmt, &buf); WPLPrintf(dateBuf); } } //Expires Field aMessage.GetHeaderField(EHttpExpires, timeValue); if (foundField) { TRAPD(err, timeValue.FormatL(buf, KLogDateTimeFmt)); if (err == KErrNone) { TBuf<KWatcherLogBuffer> dateBuf; dateBuf.Format(KLogDateFmt, &buf); WPLPrintf(dateBuf); } } // X-Wap-Application-ID TBool isInt = EFalse; TInt ID = 0; TPtrC8 generalPtr; _LIT(KLogAppIdIntFmt,"App ID :\t%X"); TRAPD(err, foundField = aMessage.GetAppIdL(generalPtr, ID, isInt)); if ( err == KErrNone && foundField) // App ID is present { if (isInt) // Field in integer format { buf.Format(KLogAppIdIntFmt,ID); } else // should be descriptor format { buf.Copy(generalPtr); } WPLPrintf(buf); } // Content-Disposition TPtrC8 dispositionPtr; _LIT(KLogDisposition,"Content-Disposition:\t"); foundField = aMessage.GetHeaderField(EHttpContentDisposition, dispositionPtr); if (foundField) // App ID is present { // Convert 8 bit to 16 bit HBufC* tempAddr = HBufC::NewLC(dispositionPtr.Length()); tempAddr->Des().Copy(dispositionPtr); WPLPrintf(KLogDisposition); WPLPrintf(*tempAddr); CleanupStack::PopAndDestroy(tempAddr); } //Message Header Binary _LIT(KLogMsgHdr,"Header Binary:"); WPLPrintf(KLogMsgHdr); aMessage.GetHeader(generalPtr); HBufC* tempHdr = HBufC::NewLC(generalPtr.Length()); tempHdr->Des().Copy(generalPtr); WPLLogBinaryAsHex(*tempHdr); CleanupStack::PopAndDestroy(); //tempHdr //Message Body aMessage.GetMessageBody(generalPtr); // Dump Body As Text _LIT(KLogMsgBody,"Body Text:"); WPLPrintf(KLogMsgBody); HBufC* tempBody = HBufC::NewLC(generalPtr.Length()); tempBody->Des().Copy(generalPtr); WPLPrintf(*tempBody); // Dump Body As Hex _LIT(KBodyBinary,"\nBody Binary:"); WPLPrintf(KBodyBinary); WPLLogBinaryAsHex(*tempBody); CleanupStack::PopAndDestroy(); //tempBody } /** * Prints out Buffer data in the format: * %X %X %X %X %X %X %X\n etc * For example * AB CD 01 12 34 A2 * * @param aDescription * in: the descriptor to be dumped into the log */void CWapPushTest::WPLLogBinaryAsHex(const TDesC& aDescription) { const TInt KWatcherLogBuffer=256; _LIT(KHexSpace,"%02X "); TBuf<KWatcherLogBuffer> hexBuf; TBuf<KWatcherLogBuffer> buf; TInt i = 0, bodyLen = aDescription.Length(); for (; i < bodyLen; i++) { hexBuf.Format(KHexSpace,aDescription[i]); buf.Append(hexBuf); if ( i && ((i+1) % 8) == 0 ) { WPLPrintf(buf); buf.Zero(); } } if (buf.Length()) WPLPrintf(buf); }void CWapPushTest::WPLLogError(const TDesC& aDescription,TInt aError) { _LIT(KErrorLogFmt,"%S, Error\t%d"); const TInt KWatcherLogBuffer=256; TBuf<KWatcherLogBuffer> buf; buf.Format(KErrorLogFmt,&aDescription,aError); buf.Append('\n'); WPLPrintf(buf); }CWapPushOOMTestEngine* CWapPushOOMTestEngine::NewL () { CWapPushOOMTestEngine* self = new (ELeave)CWapPushOOMTestEngine; CleanupStack::PushL ( self ); self->ConstructL (); CleanupStack::Pop (); return self; }CWapPushOOMTestEngine::~CWapPushOOMTestEngine () { // Do nothing. }void CWapPushOOMTestEngine::TestCompleted ( TInt aResult ) { SetError ( aResult ); if ( aResult == KErrNone ) { // The test passed. Increment the test number to next. iTest=(TTest)(iTest+1); iState = EIdle; } else { // Something went wrong shutdown the engine iState = EShuttingDown; } // set active again TRequestStatus* stat = &iStatus; User::RequestComplete(stat,KErrNone); SetActive(); }void CWapPushOOMTestEngine::DoCancel () { CWapPushTestEngine::DoCancel (); }CWapPushTestEngine::TTest CWapPushOOMTestEngine::NextTest () const { return iTest; }void CWapPushOOMTestEngine::SetNextTest ( TInt aTest ) { iTest = (TTest)aTest; }void CWapPushOOMTestEngine::RunL () { switch (iState) { case CWapPushTestEngine::EIdle: { //Skip oom test for ESIMessage. it goes in loop if(iTest==ESIAMessage || iTest==ESICMessage || iTest==EDRMMessage) { iTest=(TTest)(iTest+1); } TRAPD( err,RunNextTestL() ); if ( err != KErrNone ) TestCompleted ( err ); } break; case CWapPushTestEngine::ERunningTest: break; case CWapPushTestEngine::EShuttingDown: // We are stopping. Stop the active scheduler and exit. CActiveScheduler::Stop(); break; } }TInt CWapPushOOMTestEngine::Error () const { return iError; }void CWapPushOOMTestEngine::SetError ( TInt aErr ) { iError = aErr; }LOCAL_C void StartOomTestL ( TInt& aNextTest ) { CWapPushOOMTestEngine* oomEngine = NULL; oomEngine = CWapPushOOMTestEngine::NewL(); CleanupStack::PushL ( oomEngine ); oomEngine->SetNextTest ( aNextTest ); // All the action happens within the main event loop CActiveScheduler::Start(); aNextTest = (TInt)oomEngine->NextTest (); User::LeaveIfError ( oomEngine->Error () ); CleanupStack::PopAndDestroy (); }// main loop//GLDEF_C TInt E32Main() {__UHEAP_MARK; // Install exception handler CTrapCleanup* theCleanup = CTrapCleanup::New(); test.Printf(_L("@SYMTestCaseID IWS-WAPBROWSER-WAPPUSH-TPUSH-T_WAPPUSH-0001 ")); // Create test directory TRAPD( error, RFs fs; User::LeaveIfError(fs.Connect()); CleanupClosePushL(fs); fs.MkDirAll(KTestDirectory); CleanupStack::PopAndDestroy(&fs); ); if (error != KErrNone) User::Panic(_L("Failed to create test directory"), error); CTestScheduler* as = new CTestScheduler; if (!as) User::Panic(_L("Failed to create active scheduler"),KErrNoMemory); CActiveScheduler::Install(as); // Install active scheduler CWapPushTestEngine* engine=NULL; TRAPD(err,engine = CWapPushTestEngine::NewL()); if (err != KErrNone) User::Panic(_L("Failed to create test engine object"),err); // All the action happens within the main event loop CActiveScheduler::Start(); // Returned from start so shutdown delete engine; // Run OOM test cases. TInt nextTest = 1; TInt failAt = 0; err = KErrNoMemory; test.Start(_L("Starting OOM Test")); while ( err != KErrNone ) { failAt++; test.Printf ( KOOMTestStep, failAt ); __UHEAP_SETFAIL( RHeap::EDeterministic, failAt ); __UHEAP_MARK; TRAP ( err, StartOomTestL ( nextTest ) ); REComSession::FinalClose(); __UHEAP_MARKEND; __UHEAP_RESET; } delete as; delete theCleanup; test.End(); test.Close(); __UHEAP_MARKEND; User::Heap().Check(); return(KErrNone); }