Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


test.cpp

// test.cpp
//
// Copyright (c) 2000 - 2006 Symbian Software Ltd.  All rights reserved.
//

// Transient server example - test program

#include <e32base.h>
#include <e32test.h>
#include <f32file.h>
#include "testclient.h"

_LIT(KTest,"Transient server test");
static RTest test(KTest);

const TInt KMaxMessage=100;
typedef TBuf<KMaxMessage> TMessage;

_LIT(KMessage1,"message 1");
_LIT(KMessage2,"message 2");
_LIT(KMessage3,"message 3");

_LIT(KThread1,"Thread 1");
_LIT(KThread2,"Thread 2");

static CClient* NewClientL()
    {
    _LIT(KClientDll,"t-testc");
    return CClient::NewL(KClientDll);
    }

static CClient* NewClientLC()
    {
    CClient* c=NewClientL();
    CleanupClosePushL(*c);
    return c;
    }

typedef void (*ThreadTestL)(void);

static TInt ThreadFunc(TAny* aFuncL)
    {
    ThreadTestL f=ThreadTestL(aFuncL);
    CTrapCleanup* c=CTrapCleanup::New();
    ASSERT(c!=0);
#ifdef _DEBUG
    TRAPD(r,f());
    ASSERT(r==0);
#else
    TRAP_IGNORE(f());
#endif
    delete c;
    return KErrNone;
    }

static RThread TestThread(const TDesC& aName,ThreadTestL aTestL,TThreadPriority aPriority=EPriorityNormal)
    {
    const TInt KStackSize=0x2000;         //  8KB
    const TInt KInitHeapSize=0x1000;      //  4KB
    const TInt KHeapSize=0x1000000;           // 16MB

    RThread t;
    test (t.Create(aName,&ThreadFunc,KStackSize,KInitHeapSize,KHeapSize,(TAny*)aTestL)==KErrNone);
    t.SetPriority(aPriority);
    t.Resume();
    return t;
    }

static RThread FindServer()
    {
    RThread t;
    t.SetHandle(0);
    _LIT(KServerName,"*t-server");
    TFindThread find(KServerName);
    TFullName n;
    if (find.Next(n)==KErrNone)
        t.Open(find);
    return t;
    }

static void WaitForClose()
    {
    RThread t(FindServer());
    if (t.Handle()!=0)
        {
        TRequestStatus s;
        t.Logon(s);
        if (t.ExitType()==EExitPending || s!=KRequestPending)
            User::WaitForRequest(s);
        t.Close();
        }
    }

static void CheckInterfaceL()
    {
    test.Start(_L("Single session"));
    CClient* c=NewClientLC();
    test (c->Send(KMessage1)==KErrNone);
    TRequestStatus s;
    TMessage msg;
    c->Receive(s,msg);
    test (s==KRequestPending);
    test (c->Send(KMessage2)==KErrNone);
    test (s==KErrNone);
    test (msg==KMessage2);
    test (c->Send(KMessage1)==KErrNone);
    test (s==KErrNone);
    test (msg==KMessage2);
    User::WaitForRequest(s);
    c->CancelReceive();
    test (s==KErrNone);
    test (msg==KMessage2);
    c->Receive(s,msg);
    test (s==KRequestPending);
    c->CancelReceive();
    test (s==KErrCancel);
    test (c->Send(KMessage1)==KErrNone);
    test (s==KErrCancel);
    User::WaitForRequest(s);
    c->CancelReceive();
    CleanupStack::PopAndDestroy(); // c
//
    test.Next(_L("Second session"));
    c=NewClientLC();
    CClient* c2=NewClientLC();
    c->Receive(s,msg);
    test (s==KRequestPending);
    test (c2->Send(KMessage3)==KErrNone);
    test (s==KErrNone);
    test (msg==KMessage3);
    TRequestStatus s2;
    TMessage msg2;
    c->Receive(s,msg);
    test (s==KRequestPending);
    c2->Receive(s2,msg2);
    test (s2==KRequestPending);
    test (c->Send(KMessage1)==KErrNone);
    test (s==KErrNone);
    test (msg==KMessage1);
    test (s2==KErrNone);
    test (msg2==KMessage1);
//
    CleanupStack::PopAndDestroy(2); // c2, c
    WaitForClose();
    test.End();
    }

static RSemaphore StartSem;
static RSemaphore GoSem;

static void Start1L()
    {
    StartSem.Wait();
    CClient* c=NewClientLC();
    GoSem.Wait();
    c->Send(KMessage1);
    TMessage m;
    TRequestStatus s;
    c->Receive(s,m);
    GoSem.Signal();
    User::WaitForRequest(s);
    ASSERT(m==KMessage2);
    CleanupStack::PopAndDestroy();  // c
    }

static void Start2L()
    {
    StartSem.Wait();
    CClient* c=NewClientLC();
    TMessage m;
    TRequestStatus s;
    c->Receive(s,m);
    GoSem.Signal();
    User::WaitForRequest(s);
    ASSERT(m==KMessage1);
    GoSem.Wait();
    c->Send(KMessage2);
    CleanupStack::PopAndDestroy();  // c
    }

static void SimultaneousStartL()
    {
    test.Start(_L("Set up threads"));
    test (StartSem.CreateLocal(0,EOwnerProcess)==KErrNone);
    test (GoSem.CreateLocal(0,EOwnerProcess)==KErrNone);
    RThread t=TestThread(KThread1,&Start1L,EPriorityMore);
    TRequestStatus s1;
    t.Logon(s1);
    t.Close();
    t=TestThread(KThread2,&Start2L,EPriorityMore);
    TRequestStatus s2;
    t.Logon(s2);
    t.Close();
//
    test.Next(_L("Set them off"));
    StartSem.Signal(2);
    User::WaitForRequest(s1);
    test (s1==KErrNone);
    User::WaitForRequest(s2);
    test (s2==KErrNone);
//
    GoSem.Close();
    StartSem.Close();
    WaitForClose();
    test.End();
    }

static void StartWhileStoppingL()
    {
    test.Start(_L("Start & stop server and wait for exit"));
    NewClientL()->Close();
    RThread t(FindServer());
    test (t.Handle()!=0);
    TRequestStatus s;
    t.Logon(s);
    if (t.ExitType()==EExitPending || s!=KRequestPending)
        User::WaitForRequest(s);
    test.Next(_L("attempt to restart with dead thread/server"));
    TRAPD(r,NewClientL()->Close());
    test (r==KErrNone);
    test.Next(_L("attempt to restart after cleanup"));
    t.Close();
    WaitForClose();
    TRAP(r,NewClientL()->Close());
    test (r==KErrNone);
    WaitForClose();
    test.End();
    }

static void MainL()
    {
    test.Next(_L("Validate interface"));
    CheckInterfaceL();
    test.Next(_L("Simultaneous Start"));
    SimultaneousStartL();
    test.Next(_L("Start while stopping"));
    StartWhileStoppingL();
    }

TInt E32Main()
    {
    test.Title();
    test.Start(_L("initialising"));
    // start the loader
    RFs fs;
    test (fs.Connect()==KErrNone);
    fs.Close();
    CTrapCleanup* c=CTrapCleanup::New();
    test (c!=0);
    TRAPD(r,MainL());
    test (r==0);
    delete c;
    test.End();
    test.Close();
    return KErrNone;
    }