1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/egl/egltest/src/egltestcommonstep.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,819 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +/**
1.20 + @file
1.21 + @test
1.22 +*/
1.23 +
1.24 +#include <test/tefunit.h> // for ASSERT macros
1.25 +#include <iniparser.h>
1.26 +#include <apgtask.h>
1.27 +#include <e32math.h>
1.28 +#include <e32msgqueue.h>
1.29 +
1.30 +#include "egltestcommonstep.h"
1.31 +#include "egltestcommonsession.h"
1.32 +#include "egltestcommonutils.h"
1.33 +#include "egltestcommonprocess.h"
1.34 +
1.35 +static const TUint KDefaultHeapSize = 0x100000;
1.36 +CEglTestStep::TThreadStatus::TThreadStatus()
1.37 + {
1.38 + for(TInt i=0; i<ESize; i++)
1.39 + {
1.40 + iStatus[i] = 0;
1.41 + }
1.42 + }
1.43 +
1.44 +EXPORT_C CEglTestStep::CEglTestStep() :
1.45 + iWaitForCompletionOnPostamble(EFalse),
1.46 + iSourceFormat(KDefaultSourceFormat),
1.47 + iSurfaceFormat(KDefaultSurfaceFormat)
1.48 + {
1.49 + }
1.50 +
1.51 +EXPORT_C CEglTestStep::~CEglTestStep()
1.52 + {
1.53 + for (TInt i=0; i<KMaxProcessNumber; i++)
1.54 + {
1.55 + iProcessStatus[i].iProcess.Close();
1.56 + }
1.57 + TInt countThread = iThreadStatus.Count();
1.58 + for (TInt i=0; i<countThread; i++)
1.59 + {
1.60 + iThreadStatus[i].iThread.Close();
1.61 + }
1.62 + iThreadStatus.Close();
1.63 +
1.64 + iSemaphore[0].Close();
1.65 + iSemaphore[1].Close();
1.66 +
1.67 + CleanAll();
1.68 + CloseWsSession();
1.69 + }
1.70 +
1.71 +EXPORT_C TVerdict CEglTestStep::doTestStepPreambleL()
1.72 + {
1.73 + User::LeaveIfError(Logger().ShareAuto());
1.74 + //When EGL Logging is enabled this causes a file server session to be allocated
1.75 + //Which needs to be done before any handle checks otherwise the test will fail
1.76 + ASSERT_EGL_TRUE(eglReleaseThread());
1.77 + __UHEAP_MARK;
1.78 + HandleMark();
1.79 + return TestStepResult();
1.80 + }
1.81 +
1.82 +EXPORT_C TVerdict CEglTestStep::doTestStepPostambleL()
1.83 + {
1.84 + if(iWaitForCompletionOnPostamble && (iThreadStatus.Count() > 0))
1.85 + {
1.86 + INFO_PRINTF1(_L("Main thread waits for other threads to be terminated!!"));
1.87 + Test_MultiThread_WaitL(ETrue, TThreadStatus::ELogin);
1.88 + }
1.89 +
1.90 + if (iDisplay != EGL_NO_DISPLAY)
1.91 + {
1.92 + // Output a warning because this should be done by the test
1.93 + WARN_PRINTF1(_L("Terminating Display during doTestStepPostambleL"));
1.94 + ASSERT_EGL_TRUE(eglTerminate(iDisplay));
1.95 + iDisplay = EGL_NO_DISPLAY;
1.96 + }
1.97 +
1.98 + ASSERT_EGL_TRUE(eglReleaseThread());
1.99 +
1.100 + HandleMarkEnd();
1.101 + __UHEAP_MARKEND;
1.102 + return TestStepResult();
1.103 + }
1.104 +
1.105 +EXPORT_C void CEglTestStep::CleanAll()
1.106 + {
1.107 + delete iEglSess;
1.108 + iEglSess = NULL;
1.109 +
1.110 + if (iDisplay != EGL_NO_DISPLAY)
1.111 + {
1.112 + ASSERT_EGL_TRUE(eglTerminate(iDisplay));
1.113 + iDisplay = EGL_NO_DISPLAY;
1.114 + }
1.115 + ASSERT_EGL_TRUE(eglReleaseThread());
1.116 + }
1.117 +
1.118 +/*****************************************************************************
1.119 + ** Utility methods
1.120 + *****************************************************************************/
1.121 +
1.122 +void CEglTestStep::HandleMark()
1.123 + {
1.124 + RThread().HandleCount(iProcHandleMark, iThreadHandleMark);
1.125 + INFO_PRINTF3(_L("MARK: (%d) process-owned handle(s) / (%d) thread-owned handle(s)"), iProcHandleMark, iThreadHandleMark);
1.126 + }
1.127 +
1.128 +void CEglTestStep::HandleMarkEnd()
1.129 + {
1.130 + RThread().HandleCount(iProcHandleMarkEnd, iThreadHandleMarkEnd);
1.131 + INFO_PRINTF3(_L("MARK-END: (%d) process-owned handle(s) / (%d) thread-owned handle(s)"), iProcHandleMarkEnd, iThreadHandleMarkEnd);
1.132 +#ifdef __WINS__
1.133 + WARN_PRINTF1(_L("Process-owned handle test is ignored on WINS build due to Pls() behaviour."));
1.134 +#endif
1.135 + // When using Pls() on WINS build, it inteferes with handle count assert here due to Pls() behaviour which initialises PLS object
1.136 + // on first call of Pls() rather than during DLL loading, which cause extra count into iProcHandleMark.
1.137 + // ARMV5 build does not suffer this problem as proper WSD support is used.
1.138 +#ifndef __WINS__
1.139 + ASSERT_EQUALS(iProcHandleMarkEnd, iProcHandleMark);
1.140 +#endif
1.141 + ASSERT_EQUALS(iThreadHandleMarkEnd, iThreadHandleMark);
1.142 + }
1.143 +
1.144 +/** Initialises the window server session and window group objects. */
1.145 +EXPORT_C void CEglTestStep::OpenWsSessionL(TInt aGroupId)
1.146 + {
1.147 + User::LeaveIfError(iWsSession.Connect());
1.148 + iWindowGroup = RWindowGroup(iWsSession);
1.149 + User::LeaveIfError(iWindowGroup.Construct(aGroupId));
1.150 + }
1.151 +
1.152 +/** Uninitialises the window group object and the window server session. */
1.153 +EXPORT_C void CEglTestStep::CloseWsSession()
1.154 + {
1.155 + iWindowGroup.Close();
1.156 + iWsSession.Close();
1.157 + }
1.158 +
1.159 +/**
1.160 +Uses the Eikon Environment to construct a window and put it on top.
1.161 +@param aWindow A non-constructed window object
1.162 +@param aRect The intial position and size of the window
1.163 +@leave Standard system errors
1.164 +*/
1.165 +EXPORT_C void CEglTestStep::ConstructWindowL(RWindow& aWindow, const TRect& aRect)
1.166 + {
1.167 + INFO_PRINTF1(_L("CEglTestStep::CreateWindowL()"));
1.168 +
1.169 + const TUint32 ENullWsHandle = 0xFFFFFFFF; // Events delivered to this handle are thrown away
1.170 + aWindow = RWindow(iWsSession);
1.171 + CleanupClosePushL(aWindow);
1.172 + User::LeaveIfError(aWindow.Construct(iWindowGroup, ENullWsHandle));
1.173 + aWindow.SetExtent(aRect.iTl, aRect.Size());
1.174 + aWindow.Activate();
1.175 + CleanupStack::Pop(&aWindow);
1.176 + }
1.177 +
1.178 +/**
1.179 +Prints both the Source pixel format and the target pixel format
1.180 +*/
1.181 +EXPORT_C void CEglTestStep::PrintUsedPixelConfiguration()
1.182 + {
1.183 + INFO_PRINTF1(_L("******UsedPixelConfiguration******"));
1.184 + INFO_PRINTF1(_L("Source Pixel Format"));
1.185 + PrintPixelFormat(iSourceFormat);
1.186 +
1.187 + INFO_PRINTF1(_L("Target Format"));
1.188 + PrintVGImageFormat(iSurfaceFormat);
1.189 + INFO_PRINTF1(_L("**********************************"));
1.190 + }
1.191 +
1.192 +EXPORT_C void CEglTestStep::PrintPixelFormat(TUidPixelFormat aFormat)
1.193 + {
1.194 + switch(aFormat)
1.195 + {
1.196 + case EUidPixelFormatA_8:
1.197 + INFO_PRINTF1(_L("EUidPixelFormatA_8"));
1.198 + break;
1.199 + case EUidPixelFormatRGB_565:
1.200 + INFO_PRINTF1(_L("EUidPixelFormatRGB_565"));
1.201 + break;
1.202 + case EUidPixelFormatXRGB_8888:
1.203 + INFO_PRINTF1(_L("EUidPixelFormatXRGB_8888"));
1.204 + break;
1.205 + case EUidPixelFormatARGB_8888:
1.206 + INFO_PRINTF1(_L("EUidPixelFormatARGB_8888"));
1.207 + break;
1.208 + case EUidPixelFormatARGB_8888_PRE:
1.209 + INFO_PRINTF1(_L("EUidPixelFormatARGB_8888_PRE"));
1.210 + break;
1.211 + default:
1.212 + ERR_PRINTF2(_L("Unsupported pixel format (%d)"), aFormat);
1.213 + ASSERT_TRUE(EFalse);
1.214 + }
1.215 + }
1.216 +
1.217 +EXPORT_C void CEglTestStep::PrintVGImageFormat(VGImageFormat aAttr)
1.218 + {
1.219 + switch(aAttr)
1.220 + {
1.221 + case VG_sRGB_565:
1.222 + INFO_PRINTF1(_L("VG_sRGB_565"));
1.223 + break;
1.224 + case VG_sXRGB_8888:
1.225 + INFO_PRINTF1(_L("VG_sXRGB_8888"));
1.226 + break;
1.227 + case VG_sARGB_8888:
1.228 + INFO_PRINTF1(_L("VG_sARGB_8888"));
1.229 + break;
1.230 + case VG_sARGB_8888_PRE:
1.231 + INFO_PRINTF1(_L("VG_sARGB_8888_PRE"));
1.232 + break;
1.233 + default:
1.234 + ERR_PRINTF2(_L("Unsupported VGImage format (%d)"), aAttr);
1.235 + ASSERT_TRUE(EFalse);
1.236 + }
1.237 + }
1.238 +
1.239 +
1.240 +/*****************************************************************************
1.241 + ** Multiprocess test utils
1.242 + *****************************************************************************/
1.243 +
1.244 +/**
1.245 +Launches the specified number of processes, where each process will perform the actions specified in
1.246 +the doProcessFunctionL of the calling test. As no images TSgDrawableId has been passed, an
1.247 +an array of one (NULL) TSgDrawableId will be created.
1.248 +@param aProcessCount Number of processes
1.249 +@param aTestName Name of the calling test case (so that it can call it's doProcessFunctionL method
1.250 +@leave Standard system errors
1.251 +*/
1.252 +EXPORT_C void CEglTestStep::Test_MultiProcessL(const TDesC& aTestDllName, TInt aProcessCount, const TDesC& aTestStepName)
1.253 + {
1.254 + TSgDrawableId sgId;
1.255 + Mem::FillZ(&sgId, sizeof(TSgDrawableId));
1.256 + Test_MultiProcessL(aTestDllName, aProcessCount, aTestStepName, sgId);
1.257 + }
1.258 +
1.259 +/**
1.260 +Launches the specified number of processes, where each process will perform the actions specified in
1.261 +the doProcessFunctionL of the calling test.
1.262 +@param aProcessCount Number of processes
1.263 +@param aTestName Name of the calling test case (so that it can call it's doProcessFunctionL method
1.264 +@param aSgId Images TSgDrawableId which will be used to create an array of one TSgDrawableId
1.265 +@leave Standard system errors
1.266 +*/
1.267 +EXPORT_C void CEglTestStep::Test_MultiProcessL(const TDesC& aTestDllName, TInt aProcessCount, const TDesC& aTestStepName, const TSgDrawableId& aSgId)
1.268 + {
1.269 + // we assume we pass the same Id to all the processes (array of one)
1.270 + RArray<TSgDrawableId> sgIdList;
1.271 + ASSERT_EQUALS(sgIdList.Insert(aSgId,0), KErrNone);
1.272 + Test_MultiProcessL(aTestDllName, aProcessCount, aTestStepName, sgIdList);
1.273 + sgIdList.Close();
1.274 + }
1.275 +
1.276 +/**
1.277 +Launches the specified number of processes, where each process will perform the actions specified in
1.278 +the doProcessFunctionL of the calling test. The association of images and processes is done via the
1.279 +predefined ImageIndexFromProcessId() method.
1.280 +@param aProcessCount Number of processes
1.281 +@param aTestName Name of the calling test case (so that it can call it's doProcessFunctionL method
1.282 +@param aSgIdList Array containing the list of images' TSgDrawableId
1.283 +@leave Standard system errors
1.284 +*/
1.285 +EXPORT_C void CEglTestStep::Test_MultiProcessL(const TDesC& aTestDllName, TInt aProcessCount, const TDesC& aTestStepName, const RArray<TSgDrawableId>& aSgIdList)
1.286 + {
1.287 + TInt imageCount = aSgIdList.Count();
1.288 + if(aProcessCount <= 0 || imageCount <=0 || aProcessCount > KMaxProcessNumber || imageCount > aProcessCount)
1.289 + {
1.290 + ERR_PRINTF1(_L("Invalid process request!"));
1.291 + User::Leave(KErrArgument);
1.292 + }
1.293 +
1.294 + // create MsgQueue (only used in some test to pass data between 2 processes)
1.295 + RMsgQueue<TSgDrawableId> messageQueueSgId;
1.296 + TInt ret = messageQueueSgId.CreateGlobal(KNullDesC, 1, EOwnerProcess);
1.297 + ASSERT_EQUALS(ret, KErrNone);
1.298 + CleanupClosePushL(messageQueueSgId);
1.299 +
1.300 + RMsgQueue<TProcessId> messageQueueProcId;
1.301 + ret = messageQueueProcId.CreateGlobal(KNullDesC, 1, EOwnerProcess);
1.302 + ASSERT_EQUALS(ret, KErrNone);
1.303 + CleanupClosePushL(messageQueueProcId);
1.304 +
1.305 + // Create semphores that can be shared (only used in some test to synch between 2 process)
1.306 + ret = iSemaphore[0].CreateGlobal(KNullDesC(), 0, EOwnerProcess);
1.307 + ASSERT_EQUALS(ret, KErrNone);
1.308 + ret = iSemaphore[1].CreateGlobal(KNullDesC(), 0, EOwnerProcess);
1.309 + ASSERT_EQUALS(ret, KErrNone);
1.310 +
1.311 + // create MsgQueue (only used in some tests to pass data from client processes to the main process)
1.312 + RMsgQueue<TEglStepMessageBuffer> messageQueueClientProcParam;
1.313 + ret = messageQueueClientProcParam.CreateGlobal(KNullDesC, 1, EOwnerProcess);
1.314 + ASSERT_EQUALS(ret, KErrNone);
1.315 + CleanupClosePushL(messageQueueClientProcParam);
1.316 +
1.317 + for (TInt i=0; i<aProcessCount; i++)
1.318 + {
1.319 + TProcessInfo info;
1.320 + info.iIdx=i;
1.321 + info.iSgId= aSgIdList[ImageIndexFromProcessId(i, imageCount)];
1.322 +
1.323 + ret = iProcessStatus[i].iProcess.Create(KEglTestServerWrapperProcess, KNullDesC);
1.324 + User::LeaveIfError(ret);
1.325 +
1.326 + // Specify the test for the process
1.327 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotTestDllName, aTestDllName);
1.328 + User::LeaveIfError(ret);
1.329 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotTestStepName, aTestStepName);
1.330 + User::LeaveIfError(ret);
1.331 +
1.332 + // Specify the non-handle params passed to the process
1.333 + TPckg<TProcessInfo> pckgInfo(info);
1.334 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotParams, pckgInfo);
1.335 + User::LeaveIfError(ret);
1.336 +
1.337 + // Pass in the semaphores
1.338 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotSemaphore0, iSemaphore[0]);
1.339 + User::LeaveIfError(ret);
1.340 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotSemaphore1, iSemaphore[1]);
1.341 + User::LeaveIfError(ret);
1.342 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotMsgQueueSgId, messageQueueSgId);
1.343 + User::LeaveIfError(ret);
1.344 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotMsgQueueProcId, messageQueueProcId);
1.345 + User::LeaveIfError(ret);
1.346 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotSourceFormat, static_cast<TInt>(iSourceFormat));
1.347 + User::LeaveIfError(ret);
1.348 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotSurfaceFormat, static_cast<TInt>(iSurfaceFormat));
1.349 + User::LeaveIfError(ret);
1.350 + ret = iProcessStatus[i].iProcess.SetParameter(EProcSlotCustomClientParam, messageQueueClientProcParam);
1.351 + User::LeaveIfError(ret);
1.352 +
1.353 + iProcessStatus[i].iProcess.Logon(iProcessStatus[i].iStatus);
1.354 + iProcessStatus[i].iProcess.Resume();
1.355 + }
1.356 +
1.357 + //by default an empty implementation
1.358 + ReceiveMessageFromClient(messageQueueClientProcParam);
1.359 +
1.360 + // wait for all processes to complete (not worried about the order)
1.361 + // This is needed, as the only way to determine whether the process step has failed is to check
1.362 + // the return value (using TEST(EFalse) has no effect on the spawned process)
1.363 + for (TInt i=0; i<aProcessCount; i++)
1.364 + {
1.365 + User::WaitForRequest(iProcessStatus[i].iStatus);
1.366 + CheckProcessStatusL(i, iProcessStatus[i].iStatus, iProcessStatus[i].iProcess);
1.367 + RDebug::Print(_L(">>>>>(%d)>> status :%d"), i, iProcessStatus[i].iStatus.Int());
1.368 + iProcessStatus[i].iProcess.Close();
1.369 + }
1.370 +
1.371 + // close MsgQueue and semaphores (as used in some test with 2 spawned processes)
1.372 + CleanupStack::PopAndDestroy(3, &messageQueueSgId); //messageQueueClientProcParam, messageQueueProcId
1.373 + iSemaphore[1].Close();
1.374 + iSemaphore[0].Close();
1.375 + }
1.376 +
1.377 +/**
1.378 +Check the status of a process running as part of the current teststep.
1.379 +@param aIndex Index of the process
1.380 +@param aStatus The request status of the process in question.
1.381 +@param aProcess The process object itself.
1.382 +@leave Standard system errors
1.383 +*/
1.384 +void CEglTestStep::CheckProcessStatusL(TInt aIndex, const TRequestStatus& aStatus, const RProcess& aProcess)
1.385 + {
1.386 + TInt status = aStatus.Int();
1.387 + if (status == KErrNone)
1.388 + {
1.389 + return;
1.390 + }
1.391 + if (status == KRequestPending)
1.392 + {
1.393 + // If the process is still running, that's an error, as we waited for the status
1.394 + ERR_PRINTF2(_L("Error in process %d - status should not be KRequestPending"), aIndex);
1.395 + User::Leave(KErrTEFUnitFail);
1.396 + }
1.397 + // Something went wrong
1.398 + switch (aProcess.ExitType())
1.399 + {
1.400 + case EExitPanic: // The thread or process has been panicked.
1.401 + {
1.402 + TPtrC ptrExitCategory = aProcess.ExitCategory();
1.403 + ERR_PRINTF4(_L("Panic in process %d - category:[%S] reason: %d"), aIndex, &ptrExitCategory, aProcess.ExitReason());
1.404 + // Propagate the panic
1.405 + User::Panic(aProcess.ExitCategory(), aProcess.ExitReason());
1.406 + }
1.407 + // follow through
1.408 + case EExitKill: // The thread or process has ended as a result of a kill, i.e. Kill() has been called on the RThread or RProcess handle. Or a thread was ended as a result of calling User::Exit().
1.409 + case EExitTerminate: // The thread or process has ended as a result of a terminate, i.e. Terminate() has been called on the RThread or RProcess handle.
1.410 + case EExitPending: // The thread or process is alive.
1.411 + default:
1.412 + // Propagate the error
1.413 + ERR_PRINTF3(_L("Error in process %d - code %d"), aIndex, aStatus.Int());
1.414 + User::Leave(aStatus.Int());
1.415 + }
1.416 + ASSERT(0);
1.417 + }
1.418 +
1.419 +
1.420 +/*****************************************************************************
1.421 + ** Multithread test utils
1.422 + *****************************************************************************/
1.423 +
1.424 +/**
1.425 +Launches the specified number of threads, where each thread will perform the actions specified in
1.426 +the doThreadFunctionL of the calling test.
1.427 +@param aThreadCount Number of threads
1.428 +@param aWaitForCompletion To wait until the launched thread has completed
1.429 +@leave Standard system errors
1.430 +*/
1.431 +EXPORT_C void CEglTestStep::Test_MultiThreadL(TInt aThreadCount, TBool aWaitForCompletion)
1.432 + {
1.433 + if(aThreadCount <= 0 || aThreadCount > KMaxThreadNumber)
1.434 + {
1.435 + ERR_PRINTF1(_L("Invalid thread request!"));
1.436 + User::Leave(KErrArgument);
1.437 + }
1.438 +
1.439 + iWaitForCompletionOnPostamble = !aWaitForCompletion;
1.440 +
1.441 + //we just care for these 2 semaphores
1.442 + ASSERT_EQUALS(iSemaphore[0].CreateLocal(0, EOwnerProcess), KErrNone);
1.443 + ASSERT_EQUALS(iSemaphore[1].CreateLocal(0, EOwnerProcess), KErrNone);
1.444 +
1.445 + _LIT(KThread, "CEglTestStep_Thread");
1.446 + _LIT(KUnderScore, "_");
1.447 +
1.448 + TInt ret = KErrNone;
1.449 + ASSERT_EQUALS(iThreadStatus.Count(),0);
1.450 + // Reserve space to avoid reallocation of iThreadStatus.iStatus
1.451 + iThreadStatus.ReserveL(aThreadCount);
1.452 + for (TInt i=0; i<aThreadCount; i++)
1.453 + {
1.454 + iThreadInfos[i].iSelf=this;
1.455 + iThreadInfos[i].iIdx=i;
1.456 +
1.457 + TTime tm;
1.458 + TBuf<32> bufTime;
1.459 + tm.UniversalTime();
1.460 + tm.FormatL(bufTime, _L("_%H%T%S%C_"));
1.461 +
1.462 + // guaranteed unique thread name (useful if several threads are created with aWaitForCompletion = false)
1.463 + TName threadName(KThread);
1.464 + threadName.Append(KUnderScore);
1.465 + threadName.AppendNum(i, EDecimal);
1.466 + threadName.Append(KUnderScore);
1.467 + threadName.Append(bufTime);
1.468 + threadName.AppendNum(Math::Random(), EHex);
1.469 +
1.470 + iThreadStatus.AppendL(TThreadStatus());
1.471 + ret = iThreadStatus[i].iThread.Create(threadName, ThreadFunction, KDefaultStackSize, KMinHeapSize, KDefaultHeapSize, &iThreadInfos[i], EOwnerProcess);
1.472 + User::LeaveIfError(ret);
1.473 +
1.474 + if(!aWaitForCompletion)
1.475 + {
1.476 + // We want to wait for the notification that the extra thread is about to be launched
1.477 + // Improves timing issues within a hardware WDP environment
1.478 + iThreadStatus[i].iThread.Rendezvous(iThreadStatus[i].iStatus[TThreadStatus::ERendezvous]);
1.479 + }
1.480 + iThreadStatus[i].iThread.Logon(iThreadStatus[i].iStatus[TThreadStatus::ELogin]);
1.481 + iThreadStatus[i].iThread.Resume();
1.482 + }
1.483 + Test_MultiThread_WaitL(aWaitForCompletion, aWaitForCompletion ? TThreadStatus::ELogin : TThreadStatus::ERendezvous);
1.484 + }
1.485 +
1.486 +EXPORT_C void CEglTestStep::Test_MultiThread_WaitL(TBool aCloseThreads, TThreadStatus::TStatusId aStatusId)
1.487 + {
1.488 + // Close handles and wait for all threads to complete (not worried about the order). Note that some
1.489 + // tests do not require to wait for completion. Nevertheless, care should be taken to ensure that the
1.490 + // spawned thread is capable of modifying the main TEF process TestStepResult.
1.491 +
1.492 + TInt countThread = iThreadStatus.Count();
1.493 + for (TInt i=0; i<countThread; i++)
1.494 + {
1.495 + User::WaitForRequest(iThreadStatus[i].iStatus[aStatusId]);
1.496 + CheckThreadStatusL(i, iThreadStatus[i].iStatus[aStatusId], iThreadStatus[i].iThread);
1.497 + INFO_PRINTF3(_L(">>>>>(%d)>> status :%d"), i, iThreadStatus[i].iStatus[aStatusId].Int());
1.498 +
1.499 + if(aCloseThreads)
1.500 + {
1.501 + iThreadStatus[i].iThread.Close();
1.502 + }
1.503 + }
1.504 + if(aCloseThreads)
1.505 + {
1.506 + iThreadStatus.Reset();
1.507 +
1.508 + iSemaphore[0].Close();
1.509 + iSemaphore[1].Close();
1.510 + }
1.511 + }
1.512 +
1.513 +/**
1.514 +Check the status of a thread running as part of the current teststep.
1.515 +@param aIndex Index of the thread
1.516 +@param aStatus The request status of the thread in question.
1.517 +@param aThread The thread object itself.
1.518 +@leave Standard system errors
1.519 +*/
1.520 +void CEglTestStep::CheckThreadStatusL(TInt aIndex, const TRequestStatus& aStatus, const RThread& aThread)
1.521 + {
1.522 + TInt status = aStatus.Int();
1.523 + if (status == KErrNone)
1.524 + {
1.525 + // All went well
1.526 + return;
1.527 + }
1.528 + if (status == KRequestPending)
1.529 + {
1.530 + // If the thread is still running, that's an error, as we waited for the status
1.531 + ERR_PRINTF2(_L("Error in thread %d - status should not be KRequestPending"), aIndex);
1.532 + User::Leave(KErrTEFUnitFail);
1.533 + }
1.534 + // Something went wrong
1.535 + switch (aThread.ExitType())
1.536 + {
1.537 + case EExitPanic: // The thread or process has been panicked.
1.538 + {
1.539 + TPtrC ptrExitCategory = aThread.ExitCategory();
1.540 + ERR_PRINTF4(_L("Panic in thread %d - category:[%S] reason: %d"), aIndex, &ptrExitCategory, aThread.ExitReason());
1.541 + User::Panic(aThread.ExitCategory(), aThread.ExitReason());
1.542 + }
1.543 + // follow through
1.544 + case EExitKill: // The thread or process has ended as a result of a kill, i.e. Kill() has been called on the RThread or RProcess handle. Or a thread was ended as a result of calling User::Exit().
1.545 + case EExitTerminate: // The thread or process has ended as a result of a terminate, i.e. Terminate() has been called on the RThread or RProcess handle.
1.546 + case EExitPending: // The thread or process is alive.
1.547 + default:
1.548 + // Propagate the error
1.549 + ERR_PRINTF3(_L("Error in thread %d - code %d"), aIndex, status);
1.550 + User::Leave(aStatus.Int());
1.551 + }
1.552 + // We should not get here!
1.553 + ASSERT(0);
1.554 + }
1.555 +
1.556 +TInt CEglTestStep::ThreadFunction(TAny* aInfo)
1.557 +// static
1.558 + {
1.559 + __UHEAP_MARK;
1.560 + CTrapCleanup* cleanup = CTrapCleanup::New();
1.561 + if(cleanup == NULL)
1.562 + {
1.563 + return KErrNoMemory;
1.564 + }
1.565 +
1.566 + CEglTestStep::TThreadInfo* info = reinterpret_cast<CEglTestStep::TThreadInfo*>(aInfo);
1.567 + TRAPD(err, info->iSelf->ThreadFunctionL(*info));
1.568 +
1.569 + delete cleanup;
1.570 + __UHEAP_MARKEND;
1.571 + return err;
1.572 + }
1.573 +
1.574 +void CEglTestStep::ThreadFunctionL(TThreadInfo& aInfo)
1.575 + {
1.576 + // Mark the handle count for this thread
1.577 + TInt processHandleMark=0;
1.578 + TInt threadHandleMark=0;
1.579 + RThread().HandleCount(processHandleMark, threadHandleMark);
1.580 + INFO_PRINTF4(_L("MARK: THREAD %d: (%d) process-owned handle(s) / (%d) thread-owned handle(s)"), aInfo.iIdx, processHandleMark, threadHandleMark);
1.581 +
1.582 + // Notify the main thread that we are about to launch the extra thread
1.583 + RThread::Rendezvous(KErrNone);
1.584 +
1.585 + // Run the real thread funciton
1.586 + aInfo.iSelf->doThreadFunctionL(aInfo.iIdx);
1.587 +
1.588 + // Release EGL thread state
1.589 + INFO_PRINTF2(_L("thread %d: Calling eglReleaseThread()"), aInfo.iIdx);
1.590 + ASSERT_EGL_TRUE(eglReleaseThread());
1.591 +
1.592 + // Check the handle count for this thread has not changed
1.593 + TInt processHandleMarkEnd=0;
1.594 + TInt threadHandleMarkEnd=0;
1.595 + RThread().HandleCount(processHandleMarkEnd, threadHandleMarkEnd);
1.596 + INFO_PRINTF4(_L("MARK-END: THREAD %d: (%d) process-owned handle(s) / (%d) thread-owned handle(s)"), aInfo.iIdx, processHandleMarkEnd, threadHandleMarkEnd);
1.597 +
1.598 + //Not testing equality of process-owned handles as these should only be tested from the main thread.
1.599 + //Process handlecount is dependent on all threads, therefore process handle imbalances could be the responsibility of other threads.
1.600 + ASSERT_EQUALS(threadHandleMark, threadHandleMarkEnd);
1.601 + }
1.602 +
1.603 +/**
1.604 +Tests should override this method for multithreaded testing
1.605 +*/
1.606 +EXPORT_C void CEglTestStep::doThreadFunctionL(TInt aIdx)
1.607 + {
1.608 + // Not supported for this test step
1.609 + ERR_PRINTF2(_L("thread %d: Calling CEglTestStep::doThreadFunctionL() - should be overriden"), aIdx);
1.610 + User::Leave(KErrNotSupported);
1.611 + }
1.612 +
1.613 +EXPORT_C void CEglTestStep::doThreadFunctionL(TInt aIdx,const TSgDrawableId& aSgId)
1.614 + {
1.615 + // Not supported for this test step
1.616 + ERR_PRINTF3(_L("thread %d: Calling CEglTestStep::doThreadFunctionL() - should be overriden, TSgDrawableId %lu."), aIdx, aSgId.iId);
1.617 + User::Leave(KErrNotSupported);
1.618 + }
1.619 +
1.620 +/**
1.621 +Tests should override this method for multiprocess testing
1.622 +*/
1.623 +EXPORT_C void CEglTestStep::doProcessFunctionL(TInt aIdx)
1.624 + {
1.625 + // Not supported for this test step
1.626 + ERR_PRINTF2(_L("Process %d: Calling CEglTestStep::doProcessFunctionL() - should be overriden"), aIdx);
1.627 + User::Leave(KErrNotSupported);
1.628 + }
1.629 +
1.630 +EXPORT_C void CEglTestStep::doProcessFunctionL(TInt aIdx,const TSgDrawableId& aSgId)
1.631 + {
1.632 + // Not supported for this test step
1.633 + ERR_PRINTF3(_L("Process %d: Calling CEglTestStep::doProcessFunctionL() - should be overriden, TSgDrawableId %lu."), aIdx, aSgId.iId);
1.634 + User::Leave(KErrNotSupported);
1.635 + }
1.636 +
1.637 +
1.638 +/**
1.639 +Rendezvous: Ensures that both threads get to this point before continuing
1.640 +@param aIdx The thread index value that was passed into
1.641 + the override of CEglTestStep::doThreadFunctionL()
1.642 +*/
1.643 +EXPORT_C void CEglTestStep::Rendezvous(TInt aIdx)
1.644 + {
1.645 + if(aIdx >= 2)
1.646 + {
1.647 + // Currently Rendezvous is only supported between threads with index 0 and index 1
1.648 + INFO_PRINTF2(_L("CEglTestStep::Rendezvous() - aIdx (%d) is too big!!"), aIdx);
1.649 + ASSERT(0);
1.650 + }
1.651 + INFO_PRINTF2(_L("thread %d: ...At Rendezvous..."), aIdx);
1.652 + iSemaphore[aIdx].Signal();
1.653 + iSemaphore[1-aIdx].Wait();
1.654 + }
1.655 +
1.656 +
1.657 +/*****************************************************************************
1.658 + ** Egl Helpers
1.659 + *****************************************************************************/
1.660 +
1.661 +/**
1.662 +Temporarily initializes the EGL thread and display in order to check for the
1.663 +supplied extension string.
1.664 +The display is then released and terminated.
1.665 +Use this method to pre-check for the existence of an extension string prior
1.666 +to starting a test.
1.667 +There are 2 ways to ask for an extension, via the ID (the default way to do it)
1.668 +or passing a string containing the full name of the extension (used in some tests only)
1.669 +@param aExtensions The extension ID to look for
1.670 +@param aExtensionName The extension name to look for
1.671 +@return Whether the extension string can be found
1.672 +*/
1.673 +EXPORT_C TBool CEglTestStep::CheckForExtensionL(TInt aExtensions, const TDesC& aExtensionName)
1.674 + {
1.675 + ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
1.676 + GetDisplayL();
1.677 + CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, -1);
1.678 + eglSess->InitializeL();
1.679 +
1.680 + TBool bFoundExtensions = eglSess->CheckNeededExtensionL(aExtensions, aExtensionName);
1.681 +
1.682 + // Cleanup EGL Completely
1.683 + CleanupStack::PopAndDestroy(eglSess);
1.684 + eglSess = NULL;
1.685 + TerminateDisplayL();
1.686 + ASSERT_EGL_TRUE(eglReleaseThread());
1.687 +
1.688 + // return whether the extension string was found
1.689 + return bFoundExtensions;
1.690 + }
1.691 +
1.692 +/**
1.693 +Uses eglGetDisplay() to initialise iDisplay, and to check the result of the call
1.694 +*/
1.695 +EXPORT_C void CEglTestStep::GetDisplayL()
1.696 + {
1.697 + INFO_PRINTF1(_L("Calling eglGetDisplay..."));
1.698 +
1.699 + iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1.700 + ASSERT_EGL_TRUE(iDisplay != EGL_NO_DISPLAY);
1.701 + }
1.702 +
1.703 +/**
1.704 +If the iDisplay has been initialised then this method uses eglTerminate()
1.705 +to terminate iDisplay, and to check the result of the call.
1.706 +This method also resets the value of iDisplay to EGL_NO_DISPLAY to indicate
1.707 +that the display is no longer initialised.
1.708 +*/
1.709 +EXPORT_C void CEglTestStep::TerminateDisplayL()
1.710 + {
1.711 + if (iDisplay != EGL_NO_DISPLAY)
1.712 + {
1.713 + INFO_PRINTF1(_L("Calling eglTerminate..."));
1.714 + ASSERT_EGL_TRUE(eglTerminate(iDisplay));
1.715 + iDisplay = EGL_NO_DISPLAY;
1.716 + }
1.717 + }
1.718 +
1.719 +/**
1.720 +Cut and paste from CTestStep::SetLogger() - which is not exported
1.721 +As the name suggests, this is for use by the egl test process wrapper
1.722 +*/
1.723 +void CEglTestStep::SetLoggerForProcessWrapperL()
1.724 + {
1.725 + // Create a cinidata object for parsing the testexecute.ini
1.726 + CTestExecuteIniData* parseTestExecuteIni = NULL;
1.727 + TBuf<KMaxTestExecuteNameLength> resultFilePath;
1.728 + TBuf<KMaxTestExecuteNameLength> xmlFilePath;
1.729 + TInt logMode;
1.730 + TInt logLevel;
1.731 +
1.732 + TRAPD(err,parseTestExecuteIni = CTestExecuteIniData::NewL());
1.733 + if (err == KErrNone)
1.734 + {
1.735 + CleanupStack::PushL(parseTestExecuteIni);
1.736 + parseTestExecuteIni->ExtractValuesFromIni();
1.737 + parseTestExecuteIni->GetKeyValueFromIni(KTEFHtmlKey, resultFilePath);
1.738 + parseTestExecuteIni->GetKeyValueFromIni(KTEFXmlKey, xmlFilePath);
1.739 + parseTestExecuteIni->GetKeyValueFromIni(KTEFLogMode, logMode);
1.740 + parseTestExecuteIni->GetKeyValueFromIni(KTEFLogSeverityKey, logLevel);
1.741 + parseTestExecuteIni->GetKeyValueFromIni(KTEFEnableIniAccessLog, IniAccessLog());
1.742 + }
1.743 + else
1.744 + {
1.745 + resultFilePath.Copy(KTestExecuteLogPath);
1.746 + xmlFilePath.Copy(KTestExecuteLogPath);
1.747 + logMode = TLoggerOptions(ELogHTMLOnly);
1.748 + logLevel = RFileFlogger::TLogSeverity(ESevrAll);
1.749 + IniAccessLog() = ETrue;
1.750 + }
1.751 + Logger().SetLoggerOptions(logMode);
1.752 +
1.753 + // Initialise a handle to the file logger
1.754 + User::LeaveIfError(Logger().Connect());
1.755 + RFs fS;
1.756 + User::LeaveIfError(fS.Connect());
1.757 + CleanupClosePushL(fS);
1.758 + RFile file;
1.759 + TBuf<KMaxTestExecuteNameLength> xmlLogFile(xmlFilePath);
1.760 + TBuf<KMaxTestExecuteNameLength> logFile;
1.761 + TBuf<KMaxTestExecuteNameLength> logFileNameFile(resultFilePath);
1.762 + logFileNameFile.Append(KTestExecuteScheduleTestLogCompatibilityNameFile);
1.763 + if(file.Open(fS,logFileNameFile,EFileRead | EFileShareAny) != KErrNone)
1.764 + {
1.765 + // For the old flogger we have to create an individual file
1.766 + logFile.Copy(TestStepName());
1.767 + _LIT(KTxtExtension,".txt");
1.768 + logFile.Append(KTxtExtension);
1.769 + logMode = TLoggerOptions(0);
1.770 + Logger().SetLoggerOptions(logMode);
1.771 + }
1.772 + else
1.773 + {
1.774 + CleanupClosePushL(file);
1.775 + TBuf8<KMaxTestExecuteNameLength> logFile8;
1.776 + TInt fileSize;
1.777 + User::LeaveIfError(file.Size(fileSize));
1.778 + User::LeaveIfError(file.Read(logFile8,fileSize));
1.779 + logFile.Copy(logFile8);
1.780 + xmlLogFile.Append(logFile);
1.781 + _LIT(KXmlExtension,".xml");
1.782 + xmlLogFile.Append(KXmlExtension);
1.783 + _LIT(KHtmExtension,".htm");
1.784 + logFile.Append(KHtmExtension);
1.785 + CleanupStack::Pop(&file);
1.786 + file.Close();
1.787 + }
1.788 + TBuf<KMaxTestExecuteLogFilePath> logFilePath(resultFilePath);
1.789 + logFilePath.Append(logFile);
1.790 + CleanupStack::Pop(&fS);
1.791 + fS.Close();
1.792 +
1.793 + if (logMode == 0 || logMode == 2)
1.794 + {
1.795 + User::LeaveIfError(Logger().HtmlLogger().CreateLog(logFilePath,RTestExecuteLogServ::ELogModeAppend));
1.796 + Logger().HtmlLogger().SetLogLevel(TLogSeverity(logLevel));
1.797 + }
1.798 + if (logMode == 1 || logMode == 2)
1.799 + {
1.800 + User::LeaveIfError(Logger().XmlLogger().CreateLog(xmlLogFile,RFileFlogger::ELogModeAppend));
1.801 + Logger().XmlLogger().SetLogLevel(RFileFlogger::TLogSeverity(logLevel));
1.802 + }
1.803 + if (parseTestExecuteIni != NULL)
1.804 + {
1.805 + CleanupStack::PopAndDestroy(parseTestExecuteIni);
1.806 + }
1.807 + }
1.808 +
1.809 +EXPORT_C void CEglTestStep::PartialInitialiseL(const TDesC& aStepName)
1.810 + {
1.811 + SetTestStepName(aStepName);
1.812 + SetLoggerForProcessWrapperL();
1.813 + // Assume pass
1.814 + SetTestStepResult(EPass);
1.815 + }
1.816 +
1.817 +EXPORT_C void CEglTestStep::CreateEglSessionL(TInt aIdx)
1.818 + {
1.819 + delete iEglSess; //just in case it was called twice
1.820 + iEglSess = CTestEglSession::NewL(Logger(), iDisplay, aIdx);
1.821 + }
1.822 +