--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/egl/egltest/endpointtestsuite/automated/src/localtestbase.cpp Tue Aug 31 16:31:06 2010 +0300
@@ -0,0 +1,559 @@
+// 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:
+//
+
+
+/** @file
+ @internalComponent - Internal Symbian test code */
+
+
+#include <e32base.h>
+#include <e32debug.h>
+#include <e32msgqueue.h>
+#include <ecom/ecom.h>
+#include <test/testexecuteserverbase.h>
+#include <e32math.h>
+#include "localtestbase.h"
+#include "egltest_commscommon.h"
+#include "egltest_endpoint_util.h"
+
+
+_LIT(KEglEndpointTestServerName,"eglendpointtestserver");
+
+
+CLocalTestStepBase::CLocalTestStepBase(enum TTestUid aUid) :
+ iTestId(aUid),
+ iIsInTestStep(EFalse)
+ {
+ }
+
+void CLocalTestStepBase::DoPreambleL()
+ {
+ //null implmentation for base class
+ }
+
+void CLocalTestStepBase::DoPostambleL()
+ {
+ //null implmentation for base class
+ }
+
+//function used for creating the queues.
+TVerdict CLocalTestStepBase::doTestStepPreambleL()
+ {
+ //Open the queues.
+ User::LeaveIfError(iResultOutQueue.OpenGlobal(KResultQueueName));
+ User::LeaveIfError(iParamsInQueue.OpenGlobal(KParamsQueueName));
+ SetTestStepResult(EPass);
+ iHasCurrentTestIds = EFalse;
+ iResultLog = CTestIdResultLogger::NewL(Logger());
+ DoPreambleL();
+ return EPass;
+ }
+
+TVerdict CLocalTestStepBase::doTestStepPostambleL()
+ {
+ //Log the result of the current tests.
+ if(iHasCurrentTestIds)
+ {
+ iResultLog->LogResult(iTestIdVerdict);
+ }
+
+ DoPostambleL();
+ delete iResultLog;
+ iResultLog = NULL;
+ iResultOutQueue.Close();
+ iParamsInQueue.Close();
+ return EPass;
+ }
+
+CLocalTestStepBase::~CLocalTestStepBase()
+ {
+ //closing an already closed handle is harmless
+ iResultOutQueue.Close();
+ iParamsInQueue.Close();
+ }
+
+TVerdict CLocalTestStepBase::StartRemoteTestStep(const TRemoteTestParams& aMessageIn)
+ {
+ //Starting the remote test step is implemented as a special case
+ //of running a test case, with TestCase = KStartTestStepCaseNumber.
+ iIsInTestStep = ETrue;
+ TVerdict retVal = RunRemoteTestCase(KStartTestStepCaseNumber, aMessageIn);
+ if(retVal != EPass)
+ {
+ iIsInTestStep = EFalse;
+ }
+ return retVal;
+ }
+
+TVerdict CLocalTestStepBase::EndRemoteTestStep(const TRemoteTestParams& aMessageIn)
+ {
+ //Ending the remote test step is implemented as a special case
+ //of running a test case, with TestCase = KEndTestStepCaseNumber.
+ TVerdict retVal = RunRemoteTestCase(KEndTestStepCaseNumber, aMessageIn);
+ iIsInTestStep = EFalse;
+ return retVal;
+ }
+
+TVerdict CLocalTestStepBase::RunRemoteTestCase(TInt aTestCase, const TRemoteTestParams& aMessageIn)
+ {
+ //Don't attempt to run any test cases if we are not in a test step.
+ if(!iIsInTestStep)
+ {
+ SetTestStepResult(EFail);
+ return TestStepResult();
+ }
+
+ //send the message
+ TRemoteTestParamsPacket message(iTestId, aTestCase, aMessageIn);
+ iParamsInQueue.SendBlocking(message);
+
+ TRemoteTestResult result;
+ do
+ {
+ //relying on TEF timeout if there are problems such as the render stage not loaded.
+ iResultOutQueue.ReceiveBlocking(result);
+
+ //if uid and test case doesn't match something has gone badly wrong
+ if (result.iUid != iTestId || result.iTestCase != aTestCase)
+ {
+ //test is out of Sync
+ User::Panic(_L("Test out of sync with render stage"), KErrGeneral);
+ }
+
+ //log the message if there is one
+ if (!result.iFinished)
+ {
+ //Convert the filename to a C string. The remote test env guarantees
+ //that there is a free space at the end of the descriptor to add NULL.
+ const TText8* file = result.iFile.PtrZ();
+
+ //Convert the message to unicode and log the message.
+ TBuf<KRSLogMessageLength> message;
+ message.Copy(result.iMessage);
+ Logger().LogExtra(file, result.iLine, result.iSeverity, _L("%S"), &message);
+ }
+ }while (!result.iFinished);
+
+ //Translate the RemoteTestStep verdict to a TVerdict.
+ TVerdict retVal = EPass;
+ switch (result.iVerdict)
+ {
+ case ERtvPass:
+ retVal = EPass;
+ break;
+
+ case ERtvFail:
+ retVal = EFail;
+ break;
+
+ case ERtvInconclusive:
+ retVal = EInconclusive;
+ break;
+
+ case ERtvAbort:
+ retVal = EAbort;
+ break;
+
+ case ERtvPanic:
+ //The remote test paniced, so we panic too.
+ //This means the output log relects what actually happened.
+ User::Panic(_L("Remote Test Step Paniced!"), KErrGeneral);
+ break;
+
+ case ERtvTimeout:
+ //The remote test timedout, so we sleep so that tef times us out too.
+ //This means the output log relects what actually happened.
+ User::After(KMaxTInt);
+ break;
+
+ case ERtvUnknownTestUid:
+ retVal = EIgnore;
+ break;
+
+ default:
+ User::Panic(_L("Invalid verdict returned from the remote test step!"), KErrGeneral);
+ break;
+ }
+
+ if(retVal != EPass)
+ {
+ SetTestStepResult(retVal);
+ }
+
+ return retVal;
+ }
+
+
+void CLocalTestStepBase::RegisterTestIdsL(const TDesC& aTestString)
+ {
+ iResultLog->RegisterTestIdsL(aTestString);
+ }
+
+
+void CLocalTestStepBase::SetCurrentTestIds(const TDesC& aTestString)
+ {
+ if(iHasCurrentTestIds)
+ {
+ iResultLog->LogResult(iTestIdVerdict);
+ }
+
+ iResultLog->SetCurrentTestIds(aTestString);
+ iHasCurrentTestIds = ETrue;
+ iTestIdVerdict = EPass;
+ }
+
+
+void CLocalTestStepBase::SetTestStepResult(TVerdict aVerdict)
+ {
+ iTestIdVerdict = aVerdict;
+ CTestStep::SetTestStepResult(aVerdict);
+ }
+
+
+//Used by the result logger to delimit the csv test id strings.
+class TCommaDelimiter
+ {
+private:
+ mutable TPtrC iRemaining;
+
+public:
+ TCommaDelimiter(const TDesC& aString)
+ {
+ //Set our remaining string to the whole string, or NULL if empty.
+ if(aString.Length() == 0)
+ {
+ iRemaining.Set(NULL, 0);
+ }
+ else
+ {
+ iRemaining.Set(aString);
+ }
+ }
+
+
+ TInt GetNext(TPtrC& aSegment) const
+ {
+ //Trim off any leading commas.
+ while(iRemaining.Length() >= 2 && iRemaining[0] == ',')
+ {
+ iRemaining.Set(&iRemaining[1], iRemaining.Length() - 1);
+ }
+
+ //If remaining string is empty or has one remaining comma, return.
+ if(iRemaining.Length() == 0 || iRemaining[0] == ',')
+ {
+ iRemaining.Set(NULL, 0);
+ return KErrNotFound;
+ }
+
+ //Find the first comma.
+ TInt pos = iRemaining.Locate(',');
+
+ //If comma not found, return all remaining string.
+ if(pos == KErrNotFound)
+ {
+ aSegment.Set(iRemaining);
+ iRemaining.Set(NULL, 0);
+ return KErrNone;
+ }
+
+ //Comma found. There must be non-comma chars between 0
+ //and pos since we trimmed leading commas previously.
+ aSegment.Set(&iRemaining[0], pos);
+ iRemaining.Set(&iRemaining[pos], iRemaining.Length() - pos);
+ return KErrNone;
+ }
+
+
+ TInt GetNextTrimmed(TPtrC& aSegment) const
+ {
+ //Keep calling GetNext() until we get a segment that has
+ //chars other than spaces or there are no more segments.
+ while(1)
+ {
+ TPtrC segment;
+ TInt err = GetNext(segment);
+ if(err != KErrNone)
+ {
+ return err;
+ }
+
+ TInt front;
+ TInt back;
+ for(front = 0; front < segment.Length() && segment[front] == ' '; front++) {}
+ for(back = segment.Length() - 1; back >= 0 && segment[back] == ' '; back--) {}
+
+ TInt length = (back + 1) - front;
+ if(length > 0 && segment[front] != ' ' && segment[back] != ' ')
+ {
+ aSegment.Set(&segment[front], length);
+ return KErrNone;
+ }
+ }
+ }
+ };
+
+
+CTestIdResultLogger* CTestIdResultLogger::NewL(CTestExecuteLogger& aLogger)
+ {
+ CTestIdResultLogger* self = new (ELeave) CTestIdResultLogger(aLogger);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+CTestIdResultLogger::CTestIdResultLogger(CTestExecuteLogger& aLogger) :
+ iOriginalThread(RThread().Id()),
+ iLogger(aLogger)
+ {
+ }
+
+
+void CTestIdResultLogger::ConstructL()
+ {
+ //Create panic monitor thread. Note that we share the heap with this
+ //thread so that the arrays remain in scope if this thread panics.
+ //Note also no need for explicit locking of arrays since the panic
+ //monitor will only access them if a panic occurs here.
+ static const TInt KStackSize = 0x2000; // 8KB
+ TUint32 random = Math::Random();
+ TName threadName;
+ _LIT(KThreadNameFormat, "%S-%u");
+ _LIT(KEnvName, "EpTestIdLogger");
+ threadName.Format(KThreadNameFormat, &KEnvName, random);
+ User::LeaveIfError(iPanicMonitor.Create(threadName, PanicMonitorMain, KStackSize, &User::Heap(), this, EOwnerThread));
+
+ //Rendezvous with panic thread.
+ TRequestStatus rendStat;
+ iPanicMonitor.Rendezvous(rendStat);
+ iPanicMonitor.Resume();
+ User::WaitForRequest(rendStat);
+ }
+
+
+CTestIdResultLogger::~CTestIdResultLogger()
+ {
+ TRequestStatus logonStat;
+ iPanicMonitor.Logon(logonStat);
+ iPanicMonitor.RequestComplete(iCloseMonitor, KErrNone);
+ User::WaitForRequest(logonStat);
+ iPanicMonitor.Close();
+ iRegisteredTestIds.Close();
+ iCurrentTestIds.Close();
+ }
+
+
+void CTestIdResultLogger::RegisterTestIdsL(const TDesC& aTestString)
+ {
+ //Set up delimitter.
+ TCommaDelimiter delimit(aTestString);
+
+ //Get every test id from the string and add it to the registered test ids array.
+ TPtrC testIdPtr;
+ while(delimit.GetNextTrimmed(testIdPtr) == KErrNone)
+ {
+ TTestId testId(testIdPtr);
+ iRegisteredTestIds.AppendL(testId);
+ }
+
+ //Reserve enough space in the current test ids array so that SCurrentTestIds() can not fail.
+ iCurrentTestIds.ReserveL(iRegisteredTestIds.Count());
+ }
+
+
+void CTestIdResultLogger::SetCurrentTestIds(const TDesC& aTestString)
+ {
+ ASSERT(iCurrentTestIds.Count() == 0);
+
+ //Set up delimitter.
+ TCommaDelimiter delimit(aTestString);
+
+ //Get every test id from the string and add it to the registered test ids array.
+ TPtrC testIdPtr;
+ while(delimit.GetNextTrimmed(testIdPtr) == KErrNone)
+ {
+ TTestId testId(testIdPtr);
+
+ //This cannot fail under legitimate circumstances, since enough
+ //space is reserved in this array when registering TestIds.
+ TInt err = iCurrentTestIds.Append(testId);
+ ASSERT(err == KErrNone);
+ }
+
+ //Make sure these tests were registered and remove from the registered array.
+ for(TInt i=0; i < iCurrentTestIds.Count(); i++)
+ {
+ TInt idx = iRegisteredTestIds.Find(iCurrentTestIds[i]);
+ ASSERT(idx != KErrNotFound);
+ iRegisteredTestIds.Remove(idx);
+ }
+ }
+
+
+void CTestIdResultLogger::LogResult(TVerdict aVerdict)
+ {
+ const TInt KMaxVerdictLength = 20;
+ TBuf<KMaxVerdictLength> verdict;
+ switch(aVerdict)
+ {
+ case EPass: verdict.Append(_L("PASS")); break;
+ case EFail: verdict.Append(_L("FAIL")); break;
+ case EInconclusive: verdict.Append(_L("INCONCLUSIVE")); break;
+ case ETestSuiteError: verdict.Append(_L("TEST SUTE ERROR")); break;
+ case EAbort: verdict.Append(_L("ABORT")); break;
+ case EIgnore: verdict.Append(_L("IGNORE")); break;
+ }
+
+ while(iCurrentTestIds.Count())
+ {
+ LogResult(iLogger, iCurrentTestIds[0], verdict);
+ iCurrentTestIds.Remove(0);
+ }
+ }
+
+
+void CTestIdResultLogger::LogResult(CTestExecuteLogger& aLogger, const TTestId& aTestId, const TDesC& aVerdict)
+ {
+ aLogger.LogExtra(((TText8*)"EGL ENDPOINT TEST RESULT >>>"), 0, ESevrInfo, _L("GRAPHICS-EGL-%S: %S"), &aTestId, &aVerdict);
+ }
+
+
+TInt CTestIdResultLogger::PanicMonitorMain(TAny* aSelf)
+ {
+ CTestIdResultLogger* self = static_cast<CTestIdResultLogger*>(aSelf);
+
+ //Create cleanup stack.
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ ASSERT(cleanup);
+
+ //Create active scheduler.
+ CActiveScheduler* scheduler = new CActiveScheduler();
+ ASSERT(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ TRAPD(err, self->PanicMonitorMainL());
+ __ASSERT_ALWAYS(err == KErrNone, User::Invariant());
+
+ delete scheduler;
+ delete cleanup;
+ return KErrNone;
+ }
+
+
+void CTestIdResultLogger::PanicMonitorMainL()
+ {
+ //Setup logging.
+ CTestExecuteLogger logger;
+ TEndpointUtil::SetLoggerForProcessWrapperL(logger);
+
+ //Tell parent how to close us.
+ TRequestStatus closeStatus = KRequestPending;
+ iCloseMonitor = &closeStatus;
+
+ //Open parent thread and logon.
+ RThread origThread;
+ User::LeaveIfError(origThread.Open(iOriginalThread, EOwnerThread));
+ TRequestStatus origStatus;
+ origThread.Logon(origStatus);
+
+ //Rendevous with our parent then wait for thread to exit or close command.
+ RThread().Rendezvous(KErrNone);
+ User::WaitForRequest(closeStatus, origStatus);
+
+ if (closeStatus != KRequestPending)
+ {
+ //Parent is shutting us down. Just cancel our outstanding request and exit.
+ origThread.LogonCancel(origStatus);
+ User::WaitForRequest(origStatus);
+ }
+ else if (origStatus != KRequestPending)
+ {
+ //We can only get here if parent panicked.
+ //Log that all current tests were panicked and all registered tests were not run.
+ _LIT(KPanicked, "PANIC");
+ _LIT(KNotRun, "NOT RUN DUE TO PREVIOUS PANIC");
+ while(iCurrentTestIds.Count())
+ {
+ LogResult(logger, iCurrentTestIds[0], KPanicked);
+ iCurrentTestIds.Remove(0);
+ }
+ while(iRegisteredTestIds.Count())
+ {
+ LogResult(logger, iRegisteredTestIds[0], KNotRun);
+ iRegisteredTestIds.Remove(0);
+ }
+ }
+
+ origThread.Close();
+ }
+
+
+CEglEndpointTestServer* CEglEndpointTestServer::NewL()
+ {
+ CEglEndpointTestServer* server = new(ELeave) CEglEndpointTestServer();
+ CleanupStack::PushL(server);
+ // CServer base class call
+ TParsePtrC serverName(RProcess().FileName());
+ server->StartL(serverName.Name());
+ CleanupStack::Pop(server);
+ return server;
+ }
+
+static void MainL()
+ {
+ CActiveScheduler* sched=NULL;
+ sched=new(ELeave) CActiveScheduler;
+ CActiveScheduler::Install(sched);
+
+ CEglEndpointTestServer* server = NULL;
+ // Create the CTestServer derived server
+ TRAPD(err, server = CEglEndpointTestServer::NewL());
+ if(!err)
+ {
+ // Sync with the client and enter the active scheduler
+ RProcess::Rendezvous(KErrNone);
+ sched->Start();
+ }
+ delete server;
+ delete sched;
+ }
+
+/**
+ @return Standard Epoc error code on process exit
+ Process entry point. Called by client using RProcess API
+ */
+TInt E32Main()
+ {
+ __UHEAP_MARK;
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ if(!cleanup)
+ {
+ return KErrNoMemory;
+ }
+ TRAPD(err,MainL());
+
+ if (err)
+ {
+ RDebug::Print(_L("CEglEndpointTestServer::MainL - Error: %d"), err);
+ User::Panic(KEglEndpointTestServerName, err);
+ }
+
+ delete cleanup;
+ REComSession::FinalClose();
+ __UHEAP_MARKEND;
+ return KErrNone;
+ }