Creating a Test Server Project

TEF-based test programs are server programs that implement two abstract classes contained in the TestExecuteUtils library. The test developer must implement a CTestServer-derived class for creating test steps, and must implement one or more CTestStep-derived classes that contain the test code itself. The developer is also required to provide the server entry-point code.

This section describes the basic steps required to create a new test. The subsequent sections describe how to create individual test steps in the test.

Project file

A test server project is specified in the normal Symbian OS way using a project (mmp) file as illustrated in the following code:

SampleServer.mmp 
TARGET SampleServer.exe
TARGETTYPE exe
UID      0x1000007A 0x101F777C

SOURCEPATH  ..\src
SOURCE      SampleServer.cpp
SOURCE      SampleStep.cpp    


USERINCLUDE   ..\inc  
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\test

LIBRARY        euser.lib
LIBRARY     testexecuteutils.lib
LIBRARY     efsrv.lib
LIBRARY     testexecutelogclient.lib

The project should specify the target executable name, capabilities required for the test server, UID for the test server, source code, and the required libraries.

Note: The required libraries must include testexecuteutils.lib, which provides the test step APIs.

Test server unique name

Each test server must declare a system-wide unique string in the cpp file. For example:

LIT(KServerName,”SampleServer”);

This string is used as:

  • A unique system-wide Symbian OS server friendly name.

  • A unique system-wide binary name for loading by a client, for example, SampleServer which is a cpp file.

Note: The name is unique and is case sensitive.

Server entry-point

All Symbian OS executable programs are required to have a global E32Main() function which is a basic entry point function for an executable.

GLDEF_C TInt E32Main()
/**
 * @return - Standard Epoc error code on exit
 */
 {
 CTrapCleanup* cleanup = CTrapCleanup::New();
 if(cleanup == NULL)
  {
  return KErrNoMemory;
  }
 TRAP_IGNORE(MainL());
 delete cleanup;
 return KErrNone;
    }

The conventional way to do this is to call the MainL() function inside a TRAP harness. The MainL() function then installs an active scheduler and creates the test server object, as illustrated in the following code:

LOCAL_C void MainL()
    {
    CActiveScheduler* sched=NULL;
    sched=new(ELeave) CActiveScheduler;
    CActiveScheduler::Install(sched);
    CSampleServer* server = NULL;
    // Create the CTestServer derived server
    TRAPD(err,server = CSampleServer::NewL());
    if(!err)
        {
        // Sync with the client and enter the active scheduler
        RProcess::Rendezvous(KErrNone);
        sched->Start();
        }
    delete server;
    delete sched;
    }

Note that the MainL() function uses the RProcess API to synchronise with the client before entering the Active Scheduler.

Implementing a test server

The test servers must provide an implementation of the CTestServer abstract class. The conventional way to do this is to have a definition header file xxxServer.h with the implementation in the xxxServer.cpp file. Examples of these are given below:

Example definition file

#include <TestExecuteServerBase.h>
class CSampleServer : public CTestServer
    {
public:
    static CSampleServer* NewL(); // First phase constructor
    // Base class pure virtual
    virtual CTestStep* CreateTestStep(const TDesC& aStepName);
private:
    };

Example implementation file

The server object creation code is as follows:

CSampleServer* CSampleServer::NewL()
    {
    CSampleServer * server = new (ELeave) CSampleServer();
    CleanupStack::PushL(server);
    // CServer base class call
    // Name the server using the system-wide unique string
    // Clients use this to create server sessions.

// Use ConstructL. Server based logging is not available in StartL() which is now deprecated
    server->ConstructL(KServerName);
    CleanupStack::Pop(server);
    return server;
    }

Note: The server name is passed to the base class ConstructL() function.

The server object also defines a factory for creating its test steps, by implementing the base class CreateTestStep() function:

CTestStep* CSampleServer::CreateTestStep(const TDesC& aStepName)
    {
    CTestStep* testStep = NULL;
    // Test step name constant in the test step header file
    // Created "just in time"
    // Just one created here but create as many as required.
    if(aStepName == KSampleStep1)
        testStep = new CSampleStep1();
    else if(aStepName == KsampleStep2)
        testStep = new CSampleStep2(*this); // Reference to parent
    return testStep;
    }

For details on the log output refer to Log Output documentation.