kerneltest/e32test/system/t_svr_connect.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 14 May 2010 17:13:29 +0300
changeset 109 b3a1d9898418
parent 0 a41df078684a
permissions -rw-r--r--
Revision: 201019 Kit: 201019

// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32test\system\t_svr_connect.cpp
// Overview:
// Tests correct operation of server when interleaving connect/disconnect/
// other messages and creating the user-side session object (setting the
// session cookie) in interesting manners.
// Tests that clients/servers are panicked when performing illegal operations
// w.r.t. server connection, i.e. a client thread may not send more than one
// connect message simultaneously, nor may it send another connect message
// once a connect message has been successfully completed. Similarly, a server
// may not set the cookie twice nor may it set the cookie to be NULL. Also, a
// server may only set the cookie from a connect message and from no other.
// API Information:
// RServer2
// Details:
// - Test asynchronous server connect in various ways. Verify results
// are as expected.
// - Test illegal client/server behaviour. Verify threads are panicked,
// as expected.
// Platforms/Drives/Compatibility:
// All.
// Assumptions/Requirement/Pre-requisites:
// None.
// Failures and causes:
// Failure of this test would be caused by an incorrect modification of
// the internal client/server mechanism in the kernel.
// Base Port information:
// This is a unit test of the client/server mechanism within the kernel.
// It should be invariant to base ports. If the kernel proper has not been
// modified, this test should not fail with any new base port.
// 
//

#include <e32test.h>
#include "../misc/int_svr_calls.h"
#include <e32kpan.h>

_LIT(KTestName, "t_svr_connect");
LOCAL_D RTest test(KTestName);
LOCAL_D RTest test_client(KTestName);
LOCAL_D RTest test_server(KTestName);

_LIT(KServerName, "t_svr_connect");
_LIT8(KServerName8, "t_svr_connect");
_LIT(KMainThread, "main thread");
_LIT(KServerThread, "server thread");
_LIT(KClientThread, "client thread");
_LIT(KClientThread2, "client thread2");
_LIT(KClientThread3, "client thread3");

class RTestServer : public RSessionBase
	{
public:
	inline static TInt CreateSession(TInt aMsgSlots) { return SessionCreate(KServerName8,aMsgSlots,NULL,EIpcSession_Sharable); }
	};

// Messages to send:
//
//		connect,				1
//		a.n.other,				2
//		disconnect				3
//
// Things to do in the server:
//
//		recieve connect			4
//		set cookie				5
//		complete connect		6
//		receive a.n.other		7
//		complete a.n.other		8
//		receive disconnect		9
//		complete disconnect		10
//		

enum TMsgType
	{
	EConnect = -1,
	EDisConnect = -2,
	EANOther = 1,
	EANOther2 = 2,
	EMsgCount = 4
	};

enum TServerControl
	{
	EReceiveMsg = 0,
	EReceiveBlocked = 1,
	EWaitForReceive = 2,
	ESetCookie = 3,
	ESetNullCookie = 4,
	ECompleteMsg = 5,
	EServerDie = 6
	};

enum TClientControl
	{
	ESendMsg = 0,
	EWaitMsg = 1,
	ECreateSession = 2,
	EClientDie = 3,
	ESetCritical = 4
	};

static TMsgType TheMsgType;
static TServerControl TheServerControl;
static TClientControl TheClientControl;
static RSemaphore ServerSemaphore;
static RSemaphore ClientSemaphore;
static RSemaphore TaskCompletionSemaphore;
static RMessage2 Msgs[EMsgCount];
static RServer2 Server;
static RThread ServerThread;
static RThread ClientThread;
static RTestServer ServerHandle;
static TRequestStatus ConnectStatus;
static TRequestStatus ANOtherStatus;
static TRequestStatus ANOther2Status;
static TRequestStatus ServerReceiveStatus;
static TInt TheNumberOfMsgSlots;
static TInt ErrorExpected;
static User::TCritical CriticalLevel;


static const TAny* const KSessionCookie = (const TAny*)0x12345;
static TRequestStatus* volatile KNullReference = 0;

void DoServerAction();
void DoClientAction();
TInt Index();

TInt TestThreadServer(TAny*)
	{
	test_server(Server.CreateGlobal(KServerName) == KErrNone);
	RThread::Rendezvous(KErrNone);

	for (;;)
		{
		ServerSemaphore.Wait();
		DoServerAction();
		TaskCompletionSemaphore.Signal();
		}
	}

TInt Index()
	{
	switch (TheMsgType)
		{
	case EConnect:
		return 0;
	case EDisConnect:
		return 3;
	case EANOther:
		return 1;
	case EANOther2:
		return 2;
	default:
		return -1;
		};
	}

TRequestStatus& RequestStatus()
	{
	switch (TheMsgType)
		{
	case EConnect:
		return ConnectStatus;
	case EANOther:
		return ANOtherStatus;
	case EANOther2:
		return ANOther2Status;
	default:
		User::Invariant();
		};
	return *(TRequestStatus*)KNullReference;
	}

void DoServerAction()
	{
	switch (TheServerControl)
		{
	case EReceiveMsg:
		{
		RMessage2& msg = Msgs[Index()];
		Server.Receive(msg);
		test_server(msg.Function() == TheMsgType);
		}
		break;
	case EReceiveBlocked:
		{
		RMessage2& msg = Msgs[Index()];
		Server.Receive(msg, ServerReceiveStatus);
		test_server(ServerReceiveStatus.Int() == KRequestPending);
		}
		break;
	case EWaitForReceive:
		{
		User::WaitForRequest(ServerReceiveStatus);
		test_server(ServerReceiveStatus.Int() == KErrNone);
		test_server(Msgs[Index()].Function() == TheMsgType);
		}
		break;
	case ESetCookie:
		{
		SetSessionPtr(Msgs[Index()].Handle(), KSessionCookie);
		}
		break;
	case ESetNullCookie:
		{
		SetSessionPtr(Msgs[Index()].Handle(), NULL);
		}
		break;
	case ECompleteMsg:
		{
		Msgs[Index()].Complete(KErrNone);
		}
		break;
	case EServerDie:
		{
		User::Exit(0);
		}
		break;
	default:
		{
		}
		break;
		};
	}

void StartServer()
	{
	ServerThread.Create(KServerThread, TestThreadServer, KDefaultStackSize, 4096, 4096, NULL);

	TRequestStatus started;
	ServerThread.Rendezvous(started);

	ServerThread.Resume();
	User::WaitForRequest(started);

	test(started.Int() == KErrNone);
	}

void StopServer()
	{
	TRequestStatus logon;
	ServerThread.Logon(logon);

	TheServerControl = EServerDie;
	ServerSemaphore.Signal();

	User::WaitForRequest(logon);
	test(logon.Int() == KErrNone);

	CLOSE_AND_WAIT(ServerThread);
	}

TInt TestThreadClient(TAny*)
	{
	RThread::Rendezvous(KErrNone);

	for (;;)
		{
		ClientSemaphore.Wait();
		DoClientAction();
		TaskCompletionSemaphore.Signal();
		}
	}

void DoClientAction()
	{
	switch (TheClientControl)
		{
	case ESendMsg:
		{
		if (TheMsgType == EDisConnect)
			ServerHandle.Close();
		else
			SessionSend(ServerHandle.Handle(), TheMsgType, NULL, &RequestStatus());
		}
		break;
	case EWaitMsg:
		{
		User::WaitForRequest(RequestStatus());
		}
		break;
	case ECreateSession:
		{
		TInt err = ServerHandle.SetReturnedHandle(RTestServer::CreateSession(TheNumberOfMsgSlots));
		
		if (err != ErrorExpected)
			{
			test_client.Printf(_L("Error returned = %d\n"),err);
			test_client(EFalse,__LINE__);
			}
		}
		break;
	case EClientDie:
		{
		User::SetCritical(User::ENotCritical);
		User::Exit(0);
		}
		break;
	case ESetCritical:
		{
		User::SetCritical(CriticalLevel);
		break;
		}
	default:
		{
		}
		break;
		};
	}

// I'm lazy and I haven't completed all the IPC the client thread does,
// so even when the client thread panics, the DObject is still kept alive
// until the server goes away. Therefore if I want another client I rename.
void StartClient(const TDesC& aName)
	{
	ClientThread.Create(aName, TestThreadClient, KDefaultStackSize, 4096, 4096, NULL);

	TRequestStatus started;
	ClientThread.Rendezvous(started);

	ClientThread.Resume();
	User::WaitForRequest(started);

	test(started.Int() == KErrNone);
	}

void StartClient()
	{
	StartClient(KClientThread);
	}

void StopClient()
	{
	TRequestStatus logon;
	ClientThread.Logon(logon);

	TheClientControl = EClientDie;
	ClientSemaphore.Signal();

	User::WaitForRequest(logon);
	test(logon.Int() == KErrNone);

	CLOSE_AND_WAIT(ClientThread);
	}

void CreateSemaphores()
	{
	TInt err = ServerSemaphore.CreateLocal(0);
	test(err == KErrNone);
	err = ClientSemaphore.CreateLocal(0);
	test(err == KErrNone);
	err = TaskCompletionSemaphore.CreateLocal(0);
	test(err == KErrNone);
	}

void CloseSemaphores()
	{
	ServerSemaphore.Close();
	ClientSemaphore.Close();
	TaskCompletionSemaphore.Close();
	}

void CreateSession(TInt aErrorExpected=KErrNone, TInt aMsgSlots=-1)
	{
	TheClientControl = ECreateSession;
	TheNumberOfMsgSlots = aMsgSlots;
	ErrorExpected=aErrorExpected;
	ClientSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void SendMsg(TMsgType aType)
	{
	TheClientControl = ESendMsg;
	TheMsgType = aType;
	ClientSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void SendMsg_NoWait(TMsgType aType)
	{
	TheClientControl = ESendMsg;
	TheMsgType = aType;
	ClientSemaphore.Signal();
	}

void WaitMsg(TMsgType aType)
	{
	TheClientControl = EWaitMsg;
	TheMsgType = aType;
	ClientSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void ReceiveBlocked(TMsgType aType)
	{
	TheServerControl = EReceiveBlocked;
	TheMsgType = aType;
	ServerSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void WaitForReceive(TMsgType aType)
	{
	TheServerControl = EWaitForReceive;
	TheMsgType = aType;
	ServerSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void ReceiveMsg(TMsgType aType)
	{
	TheServerControl = EReceiveMsg;
	TheMsgType = aType;
	ServerSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void CompleteMsg(TMsgType aType)
	{
	TheServerControl = ECompleteMsg;
	TheMsgType = aType;
	ServerSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void SetCookie()
	{
	TheServerControl = ESetCookie;
	TheMsgType = EConnect;
	ServerSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}

void SetCookie_NoWait()
	{
	TheServerControl = ESetCookie;
	TheMsgType = EConnect;
	ServerSemaphore.Signal();
	}

void SetNullCookie()
	{
	TheServerControl = ESetNullCookie;
	TheMsgType = EConnect;
	ServerSemaphore.Signal();
	}

void SetBadCookie(TMsgType aType)
	{
	TheServerControl = ESetCookie;
	test(aType != EConnect);
	TheMsgType = aType;
	ServerSemaphore.Signal();
	}
void SetClientCritical(User::TCritical aCritical)
	{	
	TheClientControl = ESetCritical;
	CriticalLevel=aCritical;
	ClientSemaphore.Signal();
	TaskCompletionSemaphore.Wait();
	}
	
void Test1()
	{
	test.Next(_L("Create session with test server"));
	CreateSession();
	test.Next(_L("Send connect message"));
	SendMsg(EConnect);
	test.Next(_L("Send A.N.Other message"));
	SendMsg(EANOther);
	test.Next(_L("Sending disconnect message"));
	SendMsg(EDisConnect);
	test.Next(_L("Receive A.N.Other message"));
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	test.Next(_L("Receive disconnect message"));
	ReceiveMsg(EDisConnect);
	test.Next(_L("Check the session has gone"));
	test(Msgs[Index()].Session() == NULL);
	test.Next(_L("Set up receive for next test"));
	ReceiveBlocked(EConnect);
	}

void Test2()
	{
	test.Next(_L("Create session with test server"));
	CreateSession();
	test.Next(_L("Send connect message"));
	SendMsg(EConnect);
	test.Next(_L("Send A.N.Other message"));
	SendMsg(EANOther);
	test.Next(_L("Receive connect message"));
	WaitForReceive(EConnect);
	test(Msgs[Index()].Session() == NULL);
	test.Next(_L("Receive A.N.Other message"));
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	test.Next(_L("Sending disconnect message"));
	SendMsg(EDisConnect);
	test.Next(_L("Await disconnect message"));
	ReceiveBlocked(EDisConnect);
	test.Next(_L("Set cookie"));
	SetCookie();
	test.Next(_L("Check disconnect message received"));
	WaitForReceive(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	test.Next(_L("Complete connect message"));
	CompleteMsg(EConnect);
	}

void Test2a()
	{
	CreateSession();
	SendMsg(EConnect);
	SendMsg(EANOther);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EDisConnect);
	ReceiveBlocked(EDisConnect);
	CompleteMsg(EConnect);
	WaitForReceive(EDisConnect);
	test(Msgs[Index()].Session() == NULL);
	}

void Test2b()
	{
	CreateSession();
	SendMsg(EConnect);
	SendMsg(EANOther);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SetCookie();
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == KSessionCookie);
	SendMsg(EDisConnect);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	}

void Test3()
	{
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EANOther);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EDisConnect);
	ReceiveBlocked(EDisConnect);
	SetCookie();
	WaitForReceive(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	CompleteMsg(EConnect);
	}

void Test3a()
	{
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EANOther);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EDisConnect);
	ReceiveBlocked(EDisConnect);
	CompleteMsg(EConnect);
	WaitForReceive(EDisConnect);
	test(Msgs[Index()].Session() == NULL);
	}

void Test3b()
	{
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SetCookie();
	SendMsg(EANOther);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == KSessionCookie);
	SendMsg(EDisConnect);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	}

void Test4()
	{
	CreateSession();
	SendMsg(EANOther);
	SendMsg(EConnect);
	SendMsg(EANOther2);
	SendMsg(EDisConnect);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == NULL);
	}

void Test5()
	{
	CreateSession();
	SendMsg(EANOther);
	SendMsg(EConnect);
	SendMsg(EANOther2);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EDisConnect);
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == NULL);
	ReceiveBlocked(EANOther);
	}

void Test6()
	{
	CreateSession();
	SendMsg(EANOther);
	SendMsg(EConnect);
	SendMsg(EANOther2);
	WaitForReceive(EANOther);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EDisConnect);
	ReceiveBlocked(EDisConnect);
	SetCookie();
	WaitForReceive(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	CompleteMsg(EConnect);
	}

void Test6a()
	{
	CreateSession();
	SendMsg(EANOther);
	SendMsg(EConnect);
	SendMsg(EANOther2);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EDisConnect);
	ReceiveBlocked(EDisConnect);
	CompleteMsg(EConnect);
	WaitForReceive(EDisConnect);
	test(Msgs[Index()].Session() == NULL);
	}

void Test6b()
	{
	CreateSession();
	SendMsg(EANOther);
	SendMsg(EConnect);
	SendMsg(EANOther2);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SetCookie();
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == KSessionCookie);
	SendMsg(EDisConnect);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	}

void Test7()
	{
	CreateSession();
	SendMsg(EANOther);
	SendMsg(EConnect);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EANOther2);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SetCookie();
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == KSessionCookie);
	SendMsg(EDisConnect);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	}

void Test8()
	{
	CreateSession();
	SendMsg(EANOther);
	SendMsg(EConnect);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SetCookie();
	SendMsg(EANOther2);
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == KSessionCookie);
	SendMsg(EDisConnect);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	}

void Test9()
	{
	CreateSession();
	SendMsg(EANOther);
	ReceiveMsg(EANOther);
	test(Msgs[Index()].Session() == NULL);
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	test(Msgs[Index()].Session() == NULL);
	SetCookie();
	SendMsg(EANOther2);
	ReceiveMsg(EANOther2);
	test(Msgs[Index()].Session() == KSessionCookie);
	SendMsg(EDisConnect);
	ReceiveMsg(EDisConnect);
	test(Msgs[Index()].Session() == KSessionCookie);
	}

void Test10()
	{
	// Try connecting with too many message slots
	// (Check for DEF091903 regression)
	CreateSession(KErrArgument, 1000);
	}

_LIT(KKernExec, "KERN-EXEC");

void CheckClientDeath(TInt aReason)
	{
	TRequestStatus logon;

	ClientThread.Logon(logon);
	User::WaitForRequest(logon);

	test(ClientThread.ExitType() == EExitPanic);
	test(ClientThread.ExitCategory() == KKernExec);
	test(ClientThread.ExitReason() == aReason);

	ClientThread.Close();
	ClientThread.SetHandle(KNullHandle);
	}

void CheckServerDeath(TInt aReason)
	{
	TRequestStatus logon;

	ServerThread.Logon(logon);
	User::WaitForRequest(logon);

	test(ServerThread.ExitType() == EExitPanic);
	test(ServerThread.ExitCategory() == KKernExec);
	test(ServerThread.ExitReason() == aReason);

	CLOSE_AND_WAIT(ServerThread);
	ServerThread.SetHandle(KNullHandle);
	}

void TestNaughty()
	{
	TBool jit = User::JustInTime();
	User::SetJustInTime(EFalse);

	SetClientCritical(User::ENotCritical);
	test.Next(_L("Two connect msgs at once is naughty"));
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	SetCookie();
	SendMsg_NoWait(EConnect);
	CheckClientDeath(ERequestAlreadyPending);
	StartClient(KClientThread2);
	test.Next(_L("Another connect message after a sucessful connect msg is naughty"));
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	SetCookie();
	CompleteMsg(EConnect);
	SendMsg_NoWait(EConnect);
	CheckClientDeath(ESessionAlreadyConnected);
	StartClient(KClientThread3);

	test.Next(_L("A null session cookie is naughty"));
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	SetNullCookie();
	CheckServerDeath(ESessionNullCookie);
	StartServer();

	test.Next(_L("Setting the session cookie twice is naughty"));
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	SetCookie();
	SetCookie_NoWait();
	CheckServerDeath(ESessionCookieAlreadySet);
	StartServer();

	test.Next(_L("Trying to set the session cookie from a non-connect message is naughty"));
	CreateSession();
	SendMsg(EConnect);
	ReceiveMsg(EConnect);
	SendMsg(EANOther);
	ReceiveMsg(EANOther);
	SetBadCookie(EANOther);
	CheckServerDeath(ESessionInvalidCookieMsg);
	StartServer();

	User::SetJustInTime(jit);
	}

TInt E32Main()
    {
	User::RenameThread(KMainThread);

	__UHEAP_MARK;

	test.Title();

	test.Start(_L("Creating semaphores"));
	CreateSemaphores();

	test.Next(_L("Starting test server"));
	StartServer();

	test.Next(_L("Starting test client"));
	StartClient();
	SetClientCritical(User::EProcessCritical);
	// test combinations of receiving messages with messages sent by the client in the
	// correct order (w.r.t to each other, but not necessarily to when messages are received)
	test.Next(_L("Sending in order"));
	test.Next(_L("1"));
	Test1();
	test.Next(_L("2"));
	Test2();
	test.Next(_L("2a"));
	Test2a();
	test.Next(_L("2b"));
	Test2b();
	test.Next(_L("3"));
	Test3();
	test.Next(_L("3a"));
	Test3a();
	test.Next(_L("3b"));
	Test3b();

	// test combinations of receiving messages with messages sent by the client in the
	// wrong order (w.r.t to each other, but not necessarily to when messages are received)
	test.Next(_L("Sending out of order"));
	test.Next(_L("4"));
	Test4();
	test.Next(_L("5"));
	Test5();
	test.Next(_L("6"));
	Test6();
	test.Next(_L("6a"));
	Test6a();
	test.Next(_L("6b"));
	Test6b();
	test.Next(_L("7"));
	Test7();
	test.Next(_L("8"));
	Test8();
	test.Next(_L("9"));
	Test9();
	test.Next(_L("10"));
	Test10();

	test.Next(_L("Test other naughty behaviour is trapped"));
	TestNaughty();

	test.Next(_L("Stopping test client"));
	StopClient();

	test.Next(_L("Stopping test server"));
	StopServer();

	test.Next(_L("Closing semaphores"));
	CloseSemaphores();

	test.End();
	test.Close();

	__UHEAP_MARKEND;

	return KErrNone;
    }