os/kernelhwsrv/kerneltest/e32test/thread/t_threadedserver.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\thread\t_threadedserver.cpp
    15 // Tests the multi-threaded server/session support in CServer2/CSession2
    16 // Overview:
    17 // Tests the CServer2::SetMaster and CSession2:SetServer functions
    18 // API Information:
    19 // CServer2, CSession2
    20 // Details:
    21 // - Test creating multiple sessions with a single-threaded server
    22 // - Test creating multiple sessions with a multi-threaded server
    23 // - Verify that requests to a multi-threaded server can run in parallel and complete out-of-order
    24 // Platforms/Drives/Compatibility:
    25 // All.
    26 // Assumptions/Requirement/Pre-requisites:
    27 // Failures and causes:
    28 // Base Port information:
    29 //
    30 
    31 
    32 
    33 #define __E32TEST_EXTENSION__
    34 #include <e32test.h>
    35 #include <e32panic.h>
    36 #include <e32debug.h>
    37 
    38 _LIT(KMyName, "T_THREADEDSERVER");
    39 _LIT(KServerName,"MyServer");
    40 const TInt KHeapSize = 4096;
    41 
    42 LOCAL_D RTest test(KMyName);
    43 
    44 class CMySession : public CSession2
    45 	{
    46 public:
    47 	enum TMyRequests { EFinish, EDelay5, EPing };
    48 	CMySession(TInt aId);
    49 	virtual void ServiceL(const RMessage2& aMessage);
    50 private:
    51 	const TInt iD;
    52 	};
    53 
    54 CMySession::CMySession(TInt aId) :
    55 	iD(aId)
    56 	{
    57 	}
    58 
    59 void CMySession::ServiceL(const RMessage2& aMessage)
    60 	{
    61 	TInt err = KErrNotSupported;
    62 
    63 	RDebug::Printf("Session %d: received message %d", iD, aMessage.Function());
    64 	switch (aMessage.Function())
    65 		{
    66 		case EFinish:
    67 			CActiveScheduler::Stop();
    68 			err = KErrNone;
    69 			break;
    70 
    71 		case EDelay5:
    72 			User::After(5000000);
    73 			err = KErrNone;
    74 			break;
    75 
    76 		case EPing:
    77 			User::After(1000000);
    78 			err = KErrNone;
    79 			break;
    80 
    81 		default:
    82 			break;
    83 		}
    84 
    85 	RDebug::Printf("Session %d: completing message %d, err %d", iD, aMessage.Function(), err);
    86 	if (err == KErrNone)
    87 		aMessage.Complete(err);
    88 	else
    89 		aMessage.Panic(KServerName, err);
    90 	}
    91 
    92 
    93 class CMyServer : public CServer2
    94 	{
    95 public:
    96 	CMyServer();
    97 	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
    98 private:
    99 	mutable TInt iCount;
   100 	};
   101 
   102 static CMyServer* TheMaster = NULL;
   103 static CMyServer* TheSlave = NULL;
   104 
   105 CMyServer::CMyServer() :
   106 	CServer2(0),
   107 	iCount(0)
   108 	{
   109 	}
   110 
   111 CSession2* CMyServer::NewSessionL(const TVersion&, const RMessage2&) const
   112 	{
   113 	RDebug::Printf("Server: creating session, slave is $%x", TheSlave);
   114 	iCount += 1;
   115 	CSession2* mySession = new (ELeave) CMySession(iCount);
   116 	if (iCount > 1 && TheSlave != NULL)
   117 		mySession->SetServer(TheSlave);
   118 	RDebug::Printf("Server: created session %d", iCount);
   119 	return mySession;
   120 	}
   121 
   122 TInt RunServerCode(TAny* aFlag)
   123 	{
   124 	TInt mode = (TInt)aFlag;
   125 	TInt r = KErrNoMemory;
   126 	RDebug::Printf("Server: start, mode %d", mode);
   127 
   128 	CTrapCleanup* cleanup = CTrapCleanup::New();
   129 	if (cleanup == NULL)
   130 		return r;
   131 
   132 	CActiveScheduler* pR = new CActiveScheduler;
   133 	if (pR == NULL)
   134 		return r;
   135 
   136 	CActiveScheduler::Install(pR);
   137 	CMyServer* pS = new CMyServer();
   138 	if (pS == NULL)
   139 		return r;
   140 
   141 	switch (mode)
   142 		{
   143 		case 0:
   144 			r = pS->Start(KServerName);
   145 			break;
   146 		case 1:
   147 			TheMaster = pS;
   148 			pS->SetMaster(TheMaster);
   149 			r = pS->Start(KServerName);
   150 			break;
   151 		case 2:
   152 			TheSlave = pS;
   153 			pS->SetMaster(TheMaster);
   154 			r = pS->Start(KNullDesC);
   155 			break;
   156 		}
   157 	if (r != KErrNone)
   158 		return r;
   159 
   160 	RThread::Rendezvous(KErrNone);
   161 	TRAP(r, CActiveScheduler::Start());
   162 	if (r != KErrNone)
   163 		return r;
   164 
   165 	delete pS;
   166 	delete pR;
   167 	delete cleanup;
   168 
   169 	RDebug::Printf("Server: exit");
   170 	return KErrNone;
   171 	}
   172 
   173 
   174 class RSession : public RSessionBase
   175 	{
   176 public:
   177 	TInt Create();
   178 	void Request(TInt aRequest, TRequestStatus& aStatus);
   179 	void Request(TInt aRequest);
   180 	};
   181 
   182 TInt RSession::Create()
   183 	{
   184 	return CreateSession(KServerName, TVersion());
   185 	}
   186 
   187 void RSession::Request(TInt aRequest, TRequestStatus& aStatus)
   188 	{
   189 	SendReceive(aRequest, TIpcArgs(), aStatus);
   190 	}
   191 
   192 void RSession::Request(TInt aRequest)
   193 	{
   194 	SendReceive(aRequest, TIpcArgs());
   195 	}
   196 
   197 TInt RunClientCode(TAny* aFlag)
   198 	{
   199 	TInt mode = (TInt)aFlag;
   200 	RDebug::Printf("Client: open sessions");
   201 	RSession session1, session2;
   202 	session1.Create();
   203 	session2.Create();
   204 
   205 	TBool ooc = EFalse;
   206 	TRequestStatus status1 (KRequestPending), status2 (KRequestPending);
   207 	RDebug::Printf("Client: send request 1");
   208 	session1.Request(CMySession::EDelay5, status1);
   209 	User::After(1000000);
   210 	RDebug::Printf("Client: send request 2");
   211 	session2.Request(CMySession::EPing, status2);
   212 
   213 	User::WaitForRequest(status1, status2);
   214 	if (status1 == KRequestPending)
   215 		{
   216 		// request2 finished first ...
   217 		ooc = ETrue;
   218 		RDebug::Printf("Client: request 2 completed %d", status2.Int());
   219 		User::WaitForRequest(status1);
   220 		}
   221 	else
   222 		{
   223 		RDebug::Printf("Client: request 1 completed %d", status1.Int());
   224 		User::WaitForRequest(status2);
   225 		}
   226 	RDebug::Printf("Client: status1 %d status2 %d OOC %d", status1.Int(), status2.Int(), ooc);
   227 	test_KErrNone(status1.Int());
   228 	test_KErrNone(status2.Int());
   229 	test_Equal(ooc, mode > 0);
   230 
   231 	if (mode)
   232 		session2.Request(CMySession::EFinish);
   233 	session1.Request(CMySession::EFinish);
   234 	RDebug::Printf("Client: exit");
   235 	return KErrNone;
   236 	}
   237 
   238 
   239 void TestSequential()
   240 	{
   241 	TRequestStatus status;
   242 
   243 	RDebug::Printf("Main: start server");
   244 	RThread serverThread;
   245 	test_KErrNone(serverThread.Create(_L("server"), RunServerCode, KHeapSize, NULL, (TAny*)0));
   246 	serverThread.Rendezvous(status);
   247 	serverThread.Resume();
   248 	User::WaitForRequest(status);
   249 	test_KErrNone(status.Int());
   250 
   251 	RDebug::Printf("Main: start client");
   252 	RThread clientThread;
   253 	test_KErrNone(clientThread.Create(_L("client"), RunClientCode, KHeapSize, NULL, (TAny*)0));
   254 	clientThread.Logon(status);
   255 	clientThread.Resume();
   256 	User::WaitForRequest(status);
   257 	test_KErrNone(clientThread.ExitReason());
   258 	test_Equal(EExitKill, clientThread.ExitType());
   259 
   260 	serverThread.Logon(status);
   261 	User::WaitForRequest(status);
   262 	test_KErrNone(serverThread.ExitReason());
   263 	test_Equal(EExitKill, serverThread.ExitType());
   264 
   265 	User::After(1000);
   266 	RDebug::Printf("Main: exit");
   267 	}
   268 
   269 void TestParallel()
   270 	{
   271 	TRequestStatus status;
   272 
   273 	RDebug::Printf("Main: start master server");
   274 	RThread masterThread;
   275 	test_KErrNone(masterThread.Create(_L("master"), RunServerCode, KHeapSize, NULL, (TAny*)1));
   276 	masterThread.Rendezvous(status);
   277 	masterThread.Resume();
   278 	User::WaitForRequest(status);
   279 	test_KErrNone(status.Int());
   280 
   281 	RDebug::Printf("Main: start slave server");
   282 	RThread slaveThread;
   283 	test_KErrNone(slaveThread.Create(_L("slave"), RunServerCode, KHeapSize, NULL, (TAny*)2));
   284 	slaveThread.Rendezvous(status);
   285 	slaveThread.Resume();
   286 	User::WaitForRequest(status);
   287 	test_KErrNone(status.Int());
   288 
   289 	RDebug::Printf("Main: start client");
   290 	RThread clientThread;
   291 	test_KErrNone(clientThread.Create(_L("client2"), RunClientCode, KHeapSize, NULL, (TAny*)3));
   292 	clientThread.Logon(status);
   293 	clientThread.Resume();
   294 	User::WaitForRequest(status);
   295 	test_KErrNone(clientThread.ExitReason());
   296 	test_Equal(EExitKill, clientThread.ExitType());
   297 
   298 	slaveThread.Logon(status);
   299 	User::WaitForRequest(status);
   300 	test_KErrNone(slaveThread.ExitReason());
   301 	test_Equal(EExitKill, slaveThread.ExitType());
   302 
   303 	masterThread.Logon(status);
   304 	User::WaitForRequest(status);
   305 	test_KErrNone(masterThread.ExitReason());
   306 	test_Equal(EExitKill, masterThread.ExitType());
   307 
   308 	User::After(1000);
   309 	RDebug::Printf("Main: exit");
   310 	}
   311 
   312 
   313 GLDEF_C TInt E32Main()
   314 //
   315 // Main
   316 //
   317 	{	
   318 	test.Title();
   319 	__UHEAP_MARK;
   320 
   321 	test.Start(_L("Test threaded server support"));
   322 	test.Next(_L("Test two sessions to the same server (single-threaded)"));
   323 	TestSequential();
   324 	test.Next(_L("Test two sessions to the same server (multi-threaded)"));
   325 	TestParallel();
   326 	test.End();
   327 
   328 	__UHEAP_MARKEND;
   329 	return(KErrNone);
   330 	}