os/graphics/egl/egltest/endpointtestsuite/automated/src/remotetestbase.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
sl@0
    13
sl@0
    14
/**
sl@0
    15
 @file
sl@0
    16
 @test
sl@0
    17
 @internalComponent - Internal Symbian test code
sl@0
    18
*/
sl@0
    19
sl@0
    20
sl@0
    21
/*
sl@0
    22
 * This file contains the parts of CRemoteTestEnv and CRemoteTestStepBase
sl@0
    23
 * that do not need editting when adding new tests.
sl@0
    24
 *
sl@0
    25
 * CRemoteTestEnv acts as the controller. It provides the means of communicating
sl@0
    26
 * with the local side and it instantiates remote test steps and executes them in
sl@0
    27
 * their own thread. It monitors this thread for panic / timeout. If this
sl@0
    28
 * happens, it informs the local side.
sl@0
    29
 */
sl@0
    30
sl@0
    31
sl@0
    32
#include "remotetestbase.h"
sl@0
    33
#include <e32debug.h>
sl@0
    34
#include <e32math.h>
sl@0
    35
sl@0
    36
sl@0
    37
// Default timout for remote test steps. This MUST be smaller
sl@0
    38
// than any timeout passed to TEF for the local test step
sl@0
    39
// in the script file. Remote test steps can override this 
sl@0
    40
// value by implementing the Timeout() function in their 
sl@0
    41
// derrived class.
sl@0
    42
const TInt KRemoteTestStepTimeout = 10 * 1000000;
sl@0
    43
sl@0
    44
sl@0
    45
//Active object used to generate a timeout if worker thread takes too long. ------
sl@0
    46
sl@0
    47
CTimeoutTimer* CTimeoutTimer::NewL(CRemoteTestEnv& aEnv, TInt aPriority)
sl@0
    48
    {
sl@0
    49
    CTimeoutTimer* obj = new (ELeave) CTimeoutTimer(aEnv, aPriority);
sl@0
    50
    CleanupStack::PushL(obj);
sl@0
    51
    obj->ConstructL();
sl@0
    52
    CleanupStack::Pop(obj);
sl@0
    53
    return obj;
sl@0
    54
    }
sl@0
    55
sl@0
    56
sl@0
    57
CTimeoutTimer::CTimeoutTimer(CRemoteTestEnv& aEnv, TInt aPriority) :
sl@0
    58
    CTimer(aPriority),
sl@0
    59
    iEnv(aEnv)
sl@0
    60
    {
sl@0
    61
    }
sl@0
    62
sl@0
    63
sl@0
    64
void CTimeoutTimer::ConstructL()
sl@0
    65
    {
sl@0
    66
    CTimer::ConstructL();
sl@0
    67
    CActiveScheduler::Add(this);
sl@0
    68
    }
sl@0
    69
sl@0
    70
sl@0
    71
CTimeoutTimer::~CTimeoutTimer()
sl@0
    72
    {
sl@0
    73
    Cancel();
sl@0
    74
    }
sl@0
    75
sl@0
    76
sl@0
    77
void CTimeoutTimer::RunL()
sl@0
    78
    {
sl@0
    79
    ENDPOINT_ASSERT_DEBUG(iStatus.Int() == KErrNone, User::Invariant());
sl@0
    80
    iEnv.TestCaseTimedOut();
sl@0
    81
    }
sl@0
    82
sl@0
    83
//--------------------------------------------------------------------------------
sl@0
    84
sl@0
    85
sl@0
    86
//Active object used to listen to the worker thread to see if it panics. ---------
sl@0
    87
sl@0
    88
CWorkerListener* CWorkerListener::NewL(CRemoteTestEnv& aEnv, TInt aPriority)
sl@0
    89
    {
sl@0
    90
    CWorkerListener* obj = new (ELeave) CWorkerListener(aEnv, aPriority);
sl@0
    91
    CleanupStack::PushL(obj);
sl@0
    92
    obj->ConstructL();
sl@0
    93
    CleanupStack::Pop(obj);
sl@0
    94
    return obj;
sl@0
    95
    }
sl@0
    96
sl@0
    97
sl@0
    98
CWorkerListener::CWorkerListener(CRemoteTestEnv& aEnv, TInt aPriority) :
sl@0
    99
    CActive(aPriority),
sl@0
   100
    iEnv(aEnv)
sl@0
   101
    {
sl@0
   102
    }
sl@0
   103
sl@0
   104
sl@0
   105
CWorkerListener::~CWorkerListener()
sl@0
   106
    {
sl@0
   107
    Cancel();
sl@0
   108
    }
sl@0
   109
sl@0
   110
sl@0
   111
void CWorkerListener::ConstructL()
sl@0
   112
    {
sl@0
   113
    CActiveScheduler::Add(this);
sl@0
   114
    }
sl@0
   115
sl@0
   116
sl@0
   117
void CWorkerListener::Listen(RThread& aThread)
sl@0
   118
    {
sl@0
   119
    ENDPOINT_ASSERT_DEBUG(!IsActive(), User::Invariant());
sl@0
   120
    iThread = &aThread;
sl@0
   121
    iThread->Logon(iStatus);
sl@0
   122
    SetActive();
sl@0
   123
    }
sl@0
   124
sl@0
   125
sl@0
   126
void CWorkerListener::RunL()
sl@0
   127
    {
sl@0
   128
    iEnv.WorkerExitted();
sl@0
   129
    }
sl@0
   130
sl@0
   131
sl@0
   132
void CWorkerListener::DoCancel()
sl@0
   133
    {
sl@0
   134
    iThread->LogonCancel(iStatus);
sl@0
   135
    }
sl@0
   136
sl@0
   137
//--------------------------------------------------------------------------------
sl@0
   138
sl@0
   139
sl@0
   140
//Active object used to listen for test case completion from the worker thread. --
sl@0
   141
sl@0
   142
CTestCaseListener* CTestCaseListener::NewL(CRemoteTestEnv& aEnv, TInt aPriority)
sl@0
   143
    {
sl@0
   144
    CTestCaseListener* obj = new (ELeave) CTestCaseListener(aEnv, aPriority);
sl@0
   145
    CleanupStack::PushL(obj);
sl@0
   146
    obj->ConstructL();
sl@0
   147
    CleanupStack::Pop(obj);
sl@0
   148
    return obj;
sl@0
   149
    }
sl@0
   150
sl@0
   151
sl@0
   152
CTestCaseListener::CTestCaseListener(CRemoteTestEnv& aEnv, TInt aPriority) :
sl@0
   153
    CActive(aPriority),
sl@0
   154
    iEnv(aEnv)
sl@0
   155
    {
sl@0
   156
    }
sl@0
   157
sl@0
   158
sl@0
   159
CTestCaseListener::~CTestCaseListener()
sl@0
   160
    {
sl@0
   161
    Cancel();
sl@0
   162
    }
sl@0
   163
sl@0
   164
sl@0
   165
void CTestCaseListener::ConstructL()
sl@0
   166
    {
sl@0
   167
    CActiveScheduler::Add(this);
sl@0
   168
    }
sl@0
   169
sl@0
   170
sl@0
   171
void CTestCaseListener::Listen()
sl@0
   172
    {
sl@0
   173
    ENDPOINT_ASSERT_DEBUG(!IsActive(), User::Invariant());
sl@0
   174
    iStatus = KRequestPending;
sl@0
   175
    SetActive();
sl@0
   176
    }
sl@0
   177
sl@0
   178
sl@0
   179
void CTestCaseListener::RunL()
sl@0
   180
    {
sl@0
   181
    ENDPOINT_ASSERT_DEBUG(iStatus.Int() == KErrNone, User::Invariant());
sl@0
   182
    iEnv.TestCaseCompleted();
sl@0
   183
    }
sl@0
   184
sl@0
   185
sl@0
   186
void CTestCaseListener::DoCancel()
sl@0
   187
    {
sl@0
   188
    //There is no way to actually cancel a test case,
sl@0
   189
    //But this AO will only be cancelled when the thread
sl@0
   190
    //has panicked or timed out - which is as good as a
sl@0
   191
    //cancel. We still need to call canel on the AO though
sl@0
   192
    //to set it as inactive.
sl@0
   193
sl@0
   194
    //Also need to do a request complete if the worker has not already
sl@0
   195
    //done it. There is no danger of the worker completing between our
sl@0
   196
    //check (the if) and actually completing because the worker is dead.
sl@0
   197
    if(iStatus.Int() == KRequestPending)
sl@0
   198
        {
sl@0
   199
        TRequestStatus* myStatus = &iStatus;
sl@0
   200
        User::RequestComplete(myStatus, KErrCancel);
sl@0
   201
        }
sl@0
   202
    }
sl@0
   203
sl@0
   204
//--------------------------------------------------------------------------------
sl@0
   205
sl@0
   206
sl@0
   207
//CRemoteTestEnv -----------------------------------------------------------------
sl@0
   208
sl@0
   209
CRemoteTestEnv* CRemoteTestEnv::NewL()
sl@0
   210
    {
sl@0
   211
    CRemoteTestEnv* obj = new (ELeave) CRemoteTestEnv();
sl@0
   212
    CleanupStack::PushL(obj);
sl@0
   213
    obj->ConstructL();
sl@0
   214
    CleanupStack::Pop(obj);
sl@0
   215
    return obj;
sl@0
   216
    }
sl@0
   217
sl@0
   218
sl@0
   219
CRemoteTestEnv::CRemoteTestEnv() :
sl@0
   220
    CActive(CActive::EPriorityStandard)
sl@0
   221
    {
sl@0
   222
    }
sl@0
   223
sl@0
   224
sl@0
   225
void CRemoteTestEnv::ConstructL()
sl@0
   226
    {
sl@0
   227
    //Create the message queues.
sl@0
   228
    User::LeaveIfError(iResultOutQueue.CreateGlobal(KResultQueueName, 5));
sl@0
   229
    User::LeaveIfError(iParamsInQueue.CreateGlobal(KParamsQueueName, 1));
sl@0
   230
sl@0
   231
    iSupervisorId = RThread().Id();
sl@0
   232
sl@0
   233
    //Create AOs that monitor for events.
sl@0
   234
    //These priorities are important, since if, for example, the worker
sl@0
   235
    //thread exits by returning from the thread entrypoint after
sl@0
   236
    //successfully completing the EndTestStep() case, but before the
sl@0
   237
    //supervisor runs, the supervisor's AS will find that both iWorkerListener
sl@0
   238
    //and iTestCaseListener have completed. We use the priorities to determine
sl@0
   239
    //which signal to run first. (The one we run will cancel the others).
sl@0
   240
    iTimeoutTimer = CTimeoutTimer::NewL(*this, CActive::EPriorityLow);
sl@0
   241
    iWorkerListener = CWorkerListener::NewL(*this, CActive::EPriorityStandard);
sl@0
   242
    iTestCaseListener = CTestCaseListener::NewL(*this, CActive::EPriorityHigh);
sl@0
   243
sl@0
   244
    //Add self to active scheduler.
sl@0
   245
    CActiveScheduler::Add(this);
sl@0
   246
    }
sl@0
   247
sl@0
   248
sl@0
   249
CRemoteTestEnv::~CRemoteTestEnv()
sl@0
   250
    {
sl@0
   251
    Cancel();
sl@0
   252
    delete iTimeoutTimer;
sl@0
   253
    delete iWorkerListener;
sl@0
   254
    delete iTestCaseListener;
sl@0
   255
    iParamsInQueue.Close();
sl@0
   256
    iResultOutQueue.Close();
sl@0
   257
    }
sl@0
   258
sl@0
   259
sl@0
   260
void CRemoteTestEnv::StartReceivingCmds()
sl@0
   261
    {
sl@0
   262
    ReceiveCmd();
sl@0
   263
    CActiveScheduler::Start();
sl@0
   264
    }
sl@0
   265
sl@0
   266
sl@0
   267
void CRemoteTestEnv::ReceiveCmd()
sl@0
   268
    {
sl@0
   269
    ENDPOINT_ASSERT_DEBUG(!IsActive(), User::Invariant());
sl@0
   270
    iParamsInQueue.NotifyDataAvailable(iStatus);
sl@0
   271
    SetActive();
sl@0
   272
    }
sl@0
   273
sl@0
   274
sl@0
   275
//This is run when an packet arrives in the queue from the local side.
sl@0
   276
//It is not rearmed until the test step has run to completion.
sl@0
   277
void CRemoteTestEnv::RunL()
sl@0
   278
    {
sl@0
   279
    //Retrieve the packet from the queue.
sl@0
   280
    TInt err = iParamsInQueue.Receive(iCurTestCaseParamsPacket);
sl@0
   281
    ENDPOINT_ASSERT_DEBUG(err == KErrNone, User::Invariant());
sl@0
   282
    
sl@0
   283
    //Create the appropriate TestStep and launch thread if this is a "StartTestStep".
sl@0
   284
    if(iCurTestCaseParamsPacket.iTestCase == KStartTestStepCaseNumber)
sl@0
   285
        {
sl@0
   286
        //At this point in a well behaved system, iCurTestStep must be NULL.
sl@0
   287
        //If it is not, comms has gone wrong (most likely the local side has 
sl@0
   288
        //panicked midway through the test step). If iCurTestStep is not NULL
sl@0
   289
        //we can also guarantee that the thread is still running. Recover 
sl@0
   290
        //from this by getting the thread to do some special teardown, 
sl@0
   291
        //followed by tidying up in this thread.
sl@0
   292
        if(iCurTestStep)
sl@0
   293
            {
sl@0
   294
            //Logon to worker then signal to abort the test case
sl@0
   295
            //and wait for completion.
sl@0
   296
            TRequestStatus threadStat;
sl@0
   297
            iCurWorker.Logon(threadStat);
sl@0
   298
            TRequestStatus* notifyRunTestCase = &iNotifyRunTestCase;
sl@0
   299
            iCurWorker.RequestComplete(notifyRunTestCase, KErrAbort);
sl@0
   300
            User::WaitForRequest(threadStat);
sl@0
   301
            
sl@0
   302
            //Tidy up.
sl@0
   303
            iCurWorker.Close();
sl@0
   304
            delete iCurTestStep;
sl@0
   305
            iCurTestStep = NULL;
sl@0
   306
            }
sl@0
   307
        
sl@0
   308
        TBool result = SetupTestStep();
sl@0
   309
sl@0
   310
        //If we failed to setup the test step (invalid uid),
sl@0
   311
        //just register for another command and return.
sl@0
   312
        if(!result)
sl@0
   313
            {
sl@0
   314
            //Register to receive another packet from the message queue.
sl@0
   315
            ReceiveCmd();
sl@0
   316
            return;
sl@0
   317
            }
sl@0
   318
        }
sl@0
   319
sl@0
   320
    //Activate the TimoutTimer, TestCaseListener and WorkerListener.
sl@0
   321
    iTimeoutTimer->After(iCurTestStep->Timeout());
sl@0
   322
    iTestCaseListener->Listen();
sl@0
   323
    iWorkerListener->Listen(iCurWorker);
sl@0
   324
sl@0
   325
    //Signal the worker thread to start a test case.
sl@0
   326
    TRequestStatus* notifyRunTestCase = &iNotifyRunTestCase;
sl@0
   327
    iCurWorker.RequestComplete(notifyRunTestCase, KErrNone);
sl@0
   328
    }
sl@0
   329
sl@0
   330
sl@0
   331
void CRemoteTestEnv::DoCancel()
sl@0
   332
    {
sl@0
   333
    iParamsInQueue.CancelDataAvailable();
sl@0
   334
    }
sl@0
   335
sl@0
   336
sl@0
   337
//The test case can end in three ways:
sl@0
   338
//    1. Test Case compeletes normally (this includes failing).
sl@0
   339
//    2. The Test Case times out (in which case the thread is panicked).
sl@0
   340
//    3. The Test Case panics the worker thread.
sl@0
   341
//Three AOs listen for each of these possibilities and one of the functions below.
sl@0
   342
sl@0
   343
sl@0
   344
//This is called for case 1.
sl@0
   345
void CRemoteTestEnv::TestCaseCompleted()
sl@0
   346
    {
sl@0
   347
    //Cancel the TimeoutTimer and WorkerListener.
sl@0
   348
    iTimeoutTimer->Cancel();
sl@0
   349
    iWorkerListener->Cancel();
sl@0
   350
sl@0
   351
    //Test case completed correctly, so send test result.
sl@0
   352
    SendResult(iCurTestCaseVerdict);
sl@0
   353
sl@0
   354
    //Tidy up if this is the end of the test step.
sl@0
   355
    if(iCurTestCaseParamsPacket.iTestCase == KEndTestStepCaseNumber)
sl@0
   356
        {
sl@0
   357
        iCurWorker.Close();
sl@0
   358
        delete iCurTestStep;
sl@0
   359
        iCurTestStep = NULL;
sl@0
   360
        }
sl@0
   361
sl@0
   362
    //Register to receive another packet from the message queue.
sl@0
   363
    ReceiveCmd();
sl@0
   364
    }
sl@0
   365
sl@0
   366
sl@0
   367
//This is called for case 2.
sl@0
   368
void CRemoteTestEnv::TestCaseTimedOut()
sl@0
   369
    {
sl@0
   370
    //Cancel the TestCaseListener and WorkerListener.
sl@0
   371
    iTestCaseListener->Cancel();
sl@0
   372
    iWorkerListener->Cancel();
sl@0
   373
sl@0
   374
    //Thread timed out so log that it timed out and send the ERtvTimeout result.
sl@0
   375
    iCurTestStep->REMOTE_ERR_PRINTF1(_L("Remote test step timed out."));
sl@0
   376
    SendResult(ERtvTimeout);
sl@0
   377
sl@0
   378
    //Tidy up. Because we timed out, we abandon the test step, so
sl@0
   379
    //kill the thread and release even if this was not an EndTestStep
sl@0
   380
    iCurWorker.Kill(KErrTimedOut);
sl@0
   381
    iCurWorker.Close();
sl@0
   382
    delete iCurTestStep;
sl@0
   383
    iCurTestStep = NULL;
sl@0
   384
sl@0
   385
    //Register to receive another packet from the message queue.
sl@0
   386
    ReceiveCmd();
sl@0
   387
    }
sl@0
   388
sl@0
   389
sl@0
   390
//This is called for case 3.
sl@0
   391
void CRemoteTestEnv::WorkerExitted()
sl@0
   392
    {
sl@0
   393
    //Cancel the TimeoutTimer and TestCaseListener.
sl@0
   394
    iTimeoutTimer->Cancel();
sl@0
   395
    iTestCaseListener->Cancel();
sl@0
   396
sl@0
   397
    //Even if we were running a EndTestStep (ie the thread will exit normally), TestCaseListener should still
sl@0
   398
    //fire first, and it will cancel the WorkerListener - so we know that if we get here, it is because the
sl@0
   399
    //thread exitted abnormally.
sl@0
   400
sl@0
   401
    //Thread was panicked, so log the panic category before sending the ERtvPanic result.
sl@0
   402
    TExitCategoryName exitCategory = iCurWorker.ExitCategory();
sl@0
   403
    iCurTestStep->REMOTE_ERR_PRINTF3(_L("Remote test step panicked with: %S, code = %d."), &exitCategory, iCurWorker.ExitReason());
sl@0
   404
    SendResult(ERtvPanic);
sl@0
   405
sl@0
   406
    //Tidy up. Because we panicked, we abandon the test step, so
sl@0
   407
    //release resources even if this was not an EndTestStep
sl@0
   408
    iCurWorker.Close();
sl@0
   409
    delete iCurTestStep;
sl@0
   410
    iCurTestStep = NULL;
sl@0
   411
sl@0
   412
    //Register to receive another packet from the message queue.
sl@0
   413
    ReceiveCmd();
sl@0
   414
    }
sl@0
   415
sl@0
   416
sl@0
   417
TBool CRemoteTestEnv::SetupTestStep()
sl@0
   418
    {
sl@0
   419
    //Set the TRequestStatus that the worker thread triggers off for the first time.
sl@0
   420
    //After this, the worker thread will set it back to KRequestPending itself.
sl@0
   421
    iNotifyRunTestCase = KRequestPending;
sl@0
   422
sl@0
   423
    //Create TestStep
sl@0
   424
    TRAPD(err, iCurTestStep = CreateRemoteTestStepL(iCurTestCaseParamsPacket.iUid));
sl@0
   425
    if(err == KErrUnknown)
sl@0
   426
        {
sl@0
   427
        //Unknown test step. Tell the driver app.
sl@0
   428
        SendResult(ERtvUnknownTestUid);
sl@0
   429
        return EFalse;
sl@0
   430
        }
sl@0
   431
    else if(err != KErrNone || !iCurTestStep)
sl@0
   432
        {
sl@0
   433
        User::Invariant();
sl@0
   434
        }
sl@0
   435
sl@0
   436
    //Construct the test step base class.
sl@0
   437
    TRAP(err, iCurTestStep->ConstructL(*this));
sl@0
   438
    __ASSERT_ALWAYS(err == KErrNone, User::Invariant());
sl@0
   439
sl@0
   440
    //Create Test Thread.
sl@0
   441
    static const TInt KStackSize =   0x2000;      //  8KB
sl@0
   442
    static const TInt KHeapMinSize = 0x1000;      //  4KB
sl@0
   443
    static const TInt KHeapMaxSize = 0x1000000;   // 16MB
sl@0
   444
    TUint32 random = Math::Random();
sl@0
   445
    TName threadName;
sl@0
   446
    _LIT(KThreadNameFormat, "%S-%u");
sl@0
   447
    _LIT(KExecName, "EpTestRemoteExec");
sl@0
   448
    threadName.Format(KThreadNameFormat, &KExecName, random);
sl@0
   449
    err = iCurWorker.Create(threadName, TestThreadEntryPoint, KStackSize, KHeapMinSize, KHeapMaxSize, this);
sl@0
   450
    __ASSERT_ALWAYS(err == KErrNone, User::Invariant());
sl@0
   451
sl@0
   452
    //Start the test thread.
sl@0
   453
    iCurWorker.Resume();
sl@0
   454
sl@0
   455
    return ETrue;
sl@0
   456
    }
sl@0
   457
sl@0
   458
sl@0
   459
// The DoEglHeapMark and DoEglHeapCheck are intended to make sure memory
sl@0
   460
// allocations are freed when the testing is complete. The current
sl@0
   461
// implementation only supports the Symbian/Nokia reference implementation.
sl@0
   462
// An implementor of another EGL implementation is free to add their own
sl@0
   463
// variant of heapchecking here, with suitable #if around it.
sl@0
   464
// The function in egl should call __DbgMarkStart() and __DbgMarkEnd()
sl@0
   465
// on the heap for the egl implementation - or the equivalent if the
sl@0
   466
// heap is not a typical Symbian heap.
sl@0
   467
void CRemoteTestEnv::DoEglHeapMark()
sl@0
   468
    {
sl@0
   469
#if USE_EGLHEAP_CHECKING
sl@0
   470
    typedef void (*TEglDebugHeapMarkStartPtr)();
sl@0
   471
sl@0
   472
    TEglDebugHeapMarkStartPtr  heapMarkStart = reinterpret_cast<TEglDebugHeapMarkStartPtr>(eglGetProcAddress("egliDebugHeapMarkStart"));
sl@0
   473
    if (heapMarkStart)
sl@0
   474
        {
sl@0
   475
        heapMarkStart();
sl@0
   476
        }
sl@0
   477
#endif
sl@0
   478
    }
sl@0
   479
sl@0
   480
void CRemoteTestEnv::DoEglHeapCheck()
sl@0
   481
    {
sl@0
   482
#if USE_EGLHEAP_CHECKING
sl@0
   483
    typedef EGLint (*TEglDebugHeapMarkEndPtr)(EGLint count);
sl@0
   484
sl@0
   485
    TEglDebugHeapMarkEndPtr heapMarkEnd = reinterpret_cast<TEglDebugHeapMarkEndPtr>(eglGetProcAddress("egliDebugHeapMarkEnd"));
sl@0
   486
    if (heapMarkEnd)
sl@0
   487
        {
sl@0
   488
        (void)heapMarkEnd(0);
sl@0
   489
        }
sl@0
   490
#endif
sl@0
   491
    }
sl@0
   492
sl@0
   493
#define __EGLHEAP_MARK   DoEglHeapMark()
sl@0
   494
#define __EGLHEAP_MARKEND  DoEglHeapCheck()
sl@0
   495
sl@0
   496
sl@0
   497
void CRemoteTestEnv::RunCurrentTestStepL()
sl@0
   498
    {
sl@0
   499
    TInt processHandleMarkDummy;
sl@0
   500
    TInt threadHandleMarkStart;
sl@0
   501
    TInt threadHandleMarkEnd;
sl@0
   502
    TBool finished = EFalse;
sl@0
   503
sl@0
   504
    while(!finished)
sl@0
   505
        {
sl@0
   506
        //Wait to be signalled to run a test case.
sl@0
   507
        User::WaitForRequest(iNotifyRunTestCase);
sl@0
   508
        
sl@0
   509
        //We are aborting the test step. Tidy up EGL and exit.
sl@0
   510
        if(iNotifyRunTestCase.Int() == KErrAbort)
sl@0
   511
            {
sl@0
   512
            iCurTestStep->EglEndL();
sl@0
   513
            iNotifyRunTestCase = KRequestPending;
sl@0
   514
            return;
sl@0
   515
            }
sl@0
   516
        
sl@0
   517
        //Rearm the TRequestStatus (The first arming is done in the supervisor thread).
sl@0
   518
        iNotifyRunTestCase = KRequestPending;
sl@0
   519
sl@0
   520
        //Run the test case and panic if it leaves. Start/End are just special test cases.
sl@0
   521
        if(iCurTestCaseParamsPacket.iTestCase == KStartTestStepCaseNumber)
sl@0
   522
            {
sl@0
   523
            //Mark the user heap & thread handle count (we don't care about the process handle count).
sl@0
   524
            RThread().HandleCount(processHandleMarkDummy, threadHandleMarkStart);
sl@0
   525
            __UHEAP_MARK;
sl@0
   526
            __EGLHEAP_MARK;
sl@0
   527
sl@0
   528
            //StartRemoteTest.
sl@0
   529
            TRAPD(err, iCurTestCaseVerdict = iCurTestStep->DoStartRemoteTestStepL(iCurTestCaseParamsPacket.iParams));
sl@0
   530
            __ASSERT_ALWAYS(err == KErrNone, User::Panic(_L("tried to leave."), __LINE__));
sl@0
   531
            }
sl@0
   532
        else if(iCurTestCaseParamsPacket.iTestCase == KEndTestStepCaseNumber)
sl@0
   533
            {
sl@0
   534
            //EndRemoteTest.
sl@0
   535
            TRAPD(err, iCurTestCaseVerdict = iCurTestStep->DoEndRemoteTestStepL(iCurTestCaseParamsPacket.iParams));
sl@0
   536
            __ASSERT_ALWAYS(err == KErrNone, User::Panic(_L("tried to leave."), __LINE__));
sl@0
   537
sl@0
   538
            //This will cause a panic if the test step leaked memory or thread handles.
sl@0
   539
            __UHEAP_MARKEND;
sl@0
   540
            __EGLHEAP_MARKEND;
sl@0
   541
            RThread().HandleCount(processHandleMarkDummy, threadHandleMarkEnd);
sl@0
   542
            __ASSERT_ALWAYS(threadHandleMarkStart == threadHandleMarkEnd, User::Panic(_L("leaked handles."), KErrBadHandle));
sl@0
   543
sl@0
   544
            //Exit the loop (and eventually the thread).
sl@0
   545
            finished = ETrue;
sl@0
   546
            }
sl@0
   547
        else
sl@0
   548
            {
sl@0
   549
            //Run a regular Test Case.
sl@0
   550
            TRAPD(err, iCurTestCaseVerdict = iCurTestStep->DoRunRemoteTestCaseL(iCurTestCaseParamsPacket.iTestCase, iCurTestCaseParamsPacket.iParams));
sl@0
   551
            __ASSERT_ALWAYS(err == KErrNone, User::Panic(_L("tried to leave."), __LINE__));
sl@0
   552
            }
sl@0
   553
sl@0
   554
        //Notify the supervisor that we have completed the test case.
sl@0
   555
        RThread supervisor;
sl@0
   556
        TInt err = supervisor.Open(iSupervisorId);
sl@0
   557
        __ASSERT_ALWAYS(err == KErrNone, User::Panic(_L("framework error."), __LINE__));
sl@0
   558
        TRequestStatus* notifyFinishTestCase = &iTestCaseListener->iStatus;
sl@0
   559
        supervisor.RequestComplete(notifyFinishTestCase, KErrNone);
sl@0
   560
        supervisor.Close();
sl@0
   561
        }
sl@0
   562
    }
sl@0
   563
sl@0
   564
sl@0
   565
TInt CRemoteTestEnv::TestThreadEntryPoint(TAny* aSelf)
sl@0
   566
    {
sl@0
   567
    CRemoteTestEnv* self = static_cast<CRemoteTestEnv*>(aSelf);
sl@0
   568
    
sl@0
   569
    //Create cleanup stack.
sl@0
   570
    CTrapCleanup* cleanup = CTrapCleanup::New();
sl@0
   571
    ASSERT(cleanup);
sl@0
   572
    
sl@0
   573
    //Create active scheduler.
sl@0
   574
    CActiveScheduler* scheduler = new CActiveScheduler();
sl@0
   575
    ASSERT(scheduler);
sl@0
   576
    CActiveScheduler::Install(scheduler);
sl@0
   577
    
sl@0
   578
    TRAPD(err, self->RunCurrentTestStepL());
sl@0
   579
    __ASSERT_ALWAYS(err == KErrNone, User::Invariant());
sl@0
   580
sl@0
   581
    //Clean up.
sl@0
   582
    delete scheduler;
sl@0
   583
    delete cleanup;
sl@0
   584
    return KErrNone;
sl@0
   585
    }
sl@0
   586
sl@0
   587
sl@0
   588
void CRemoteTestEnv::SendResult(TRemoteTestVerdict aVerdict)
sl@0
   589
    {
sl@0
   590
    iResultOutQueue.SendBlocking(TRemoteTestResult(iCurTestCaseParamsPacket.iUid, iCurTestCaseParamsPacket.iTestCase, aVerdict));
sl@0
   591
    }
sl@0
   592
sl@0
   593
sl@0
   594
void CRemoteTestEnv::SendLog(const TDesC8& aFile, TInt aLine, TInt aSeverity, const TDesC& aMessage)
sl@0
   595
    {
sl@0
   596
    iResultOutQueue.SendBlocking(TRemoteTestResult(iCurTestCaseParamsPacket.iUid, iCurTestCaseParamsPacket.iTestCase, aFile, aLine, aSeverity, aMessage));
sl@0
   597
    }
sl@0
   598
sl@0
   599
//--------------------------------------------------------------------------------
sl@0
   600
sl@0
   601
sl@0
   602
//CRemoteTestStepBase ------------------------------------------------------------
sl@0
   603
sl@0
   604
CRemoteTestStepBase::CRemoteTestStepBase(TTestUid aUid) :
sl@0
   605
    iUid(aUid)
sl@0
   606
    {
sl@0
   607
    }
sl@0
   608
sl@0
   609
sl@0
   610
void CRemoteTestStepBase::ConstructL(CRemoteTestEnv& aTestEnv)
sl@0
   611
    {
sl@0
   612
    iTestEnv = &aTestEnv;
sl@0
   613
    if (iEndpoint.Error() != KErrNone)
sl@0
   614
        {
sl@0
   615
        RDebug::Printf("Could not construct CRemoteTestStepBase"
sl@0
   616
                " - is EglEndpointNOK enabled?? -- Error: %d", iEndpoint.Error());
sl@0
   617
        User::Leave(iEndpoint.Error());
sl@0
   618
        }
sl@0
   619
    }
sl@0
   620
sl@0
   621
sl@0
   622
CRemoteTestStepBase::~CRemoteTestStepBase()
sl@0
   623
    {
sl@0
   624
    }
sl@0
   625
sl@0
   626
sl@0
   627
TRemoteTestVerdict CRemoteTestStepBase::DoStartRemoteTestStepL(const TRemoteTestParams& /*aMessageIn*/)
sl@0
   628
    {
sl@0
   629
    //Default implementation does nothing.
sl@0
   630
    return ERtvPass;
sl@0
   631
    }
sl@0
   632
sl@0
   633
sl@0
   634
TRemoteTestVerdict CRemoteTestStepBase::DoEndRemoteTestStepL(const TRemoteTestParams& /*aMessageIn*/)
sl@0
   635
    {
sl@0
   636
    //Default implementation does nothing.
sl@0
   637
    return ERtvPass;
sl@0
   638
    }
sl@0
   639
sl@0
   640
sl@0
   641
TInt CRemoteTestStepBase::Timeout() const
sl@0
   642
    {
sl@0
   643
    return KRemoteTestStepTimeout;
sl@0
   644
    }
sl@0
   645
sl@0
   646
sl@0
   647
class TOverflowTruncate : public TDesOverflow
sl@0
   648
    {
sl@0
   649
public:
sl@0
   650
    virtual void Overflow(TDes& /*aDes*/)
sl@0
   651
        {
sl@0
   652
        //Do nothing - just let it truncate.
sl@0
   653
        }
sl@0
   654
    };
sl@0
   655
sl@0
   656
sl@0
   657
void CRemoteTestStepBase::Log(const TText8* aFile, TInt aLine, TInt aSeverity, TRefByValue<const TDesC> aFmt, ...)
sl@0
   658
    {
sl@0
   659
    if(iTestEnv)
sl@0
   660
        {
sl@0
   661
        TOverflowTruncate overflow;
sl@0
   662
        VA_LIST list;
sl@0
   663
        VA_START(list, aFmt);
sl@0
   664
        TBuf<0x100> buf;
sl@0
   665
        buf.AppendFormatList(aFmt, list, &overflow);
sl@0
   666
        TPtrC8 file(aFile);
sl@0
   667
        iTestEnv->SendLog(file, aLine, aSeverity, buf);
sl@0
   668
        }
sl@0
   669
    }
sl@0
   670
sl@0
   671
sl@0
   672
void CRemoteTestStepBase::EglStartL()
sl@0
   673
    {
sl@0
   674
    eglInitialize(eglGetDisplay(EGL_DEFAULT_DISPLAY), NULL, NULL);
sl@0
   675
    if (eglGetError()!=EGL_SUCCESS)
sl@0
   676
        {
sl@0
   677
        REMOTE_INFO_PRINTF1(_L("could not initialise egl"));
sl@0
   678
        User::Leave(KErrGeneral);
sl@0
   679
        }
sl@0
   680
    }
sl@0
   681
sl@0
   682
sl@0
   683
void CRemoteTestStepBase::EglEndL()
sl@0
   684
    {
sl@0
   685
    eglTerminate(eglGetDisplay(EGL_DEFAULT_DISPLAY));
sl@0
   686
    if (eglGetError()!=EGL_SUCCESS)
sl@0
   687
        {
sl@0
   688
        REMOTE_INFO_PRINTF1(_L("could not terminate egl"));
sl@0
   689
        User::Leave(KErrGeneral);
sl@0
   690
        }
sl@0
   691
    eglReleaseThread();
sl@0
   692
    }
sl@0
   693
sl@0
   694
sl@0
   695
const TEglEndpointWrap& CRemoteTestStepBase::EglEndpoint() const
sl@0
   696
    {
sl@0
   697
    return iEndpoint;
sl@0
   698
    }
sl@0
   699
sl@0
   700
//--------------------------------------------------------------------------------