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.