os/kernelhwsrv/kerneltest/e32test/dll/t_dllwsd.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description:
    15 *
    16 */
    17 
    18 
    19 /**
    20 Overview:
    21 	Test DLL Writeable Static Data support
    22 
    23 API Information:
    24 
    25 
    26 Details:
    27 	- Each process has independent DLL WSD
    28 	- Whether DLL linked directly or indirectly
    29 	- Whether DLL loaded dynamically or statically
    30 	- DLL WSD is consistent under heavy usage by multiple processes
    31 	- IPC works to/from DLL WSD descriptors & TRequestStatus
    32 	This source file builds in 4 configurations, with each of
    33 	direct and indirect linking either used or not used.
    34 	These configurations are set by 4 MM files, t_dllwsd[d][i].mmp
    35 	Any of the exe created from the MMP files can be started 
    36 	to run the tests, it does not matter which is used. 
    37 	All exe configurations will be used during the tests.
    38 
    39 Platforms/Drives/Compatibility:
    40 	All.
    41 
    42 Assumptions/Requirement/Pre-requisites:
    43 	
    44 
    45 Failures and causes:
    46 	
    47 
    48 Base Port information:
    49 
    50 */
    51 
    52 #define __E32TEST_EXTENSION__
    53 
    54 #include <e32test.h>
    55 #include <e32svr.h>
    56 #include <f32dbg.h>
    57 #include <u32std.h>
    58 #include "t_dllwsd_dll.h"
    59 #include "t_dllwsd_dlli.h"
    60 
    61 
    62 LOCAL_D RTest test(_L("T_DLLWSD"));
    63 
    64 enum TTestFunc
    65 	{
    66 	ETestFuncTestCons=1,
    67 	ETestFuncThrash1,
    68 	ETestFuncIpcTest,
    69 	ETestFuncIpcGet,
    70 	ETestFuncIpcReverse,
    71 	ETestFuncIpcSet,
    72 	ETestFuncPanic,
    73 	};
    74 
    75 // Test session for IPC use of WSD, talks to the same server as RDllWsd
    76 class RIpcTestSession : public RSessionBase
    77 	{
    78 	public:
    79 	TInt Connect()
    80 		{
    81 		return CreateSession(_L("IpcTestServer"), TVersion());
    82 		}
    83 	void Get(TBuf<60000>& buf, TRequestStatus& req)
    84 		{
    85 		SendReceive(ETestFuncIpcGet, TIpcArgs(&buf), req);
    86 		}
    87 	void Reverse(TRequestStatus& req)
    88 		{
    89 		SendReceive(ETestFuncIpcReverse, req);
    90 		}
    91 	void Set(const TBuf<60000>& buf, TRequestStatus& req)
    92 		{
    93 		SendReceive(ETestFuncIpcSet, TIpcArgs(&buf), req);
    94 		}
    95 	};
    96 
    97 #ifdef T_DLLWSD_DIRECT
    98 void FillBuf(TInt start, TInt inc)
    99 	{
   100 	for (int ii=0; ii<WsdBuf().Length(); ii++)
   101 		{
   102 		WsdBuf()[ii] = (unsigned short)start;
   103 		start += inc;
   104 		}
   105 	}
   106 
   107 TInt CheckBuf(TInt start, TInt inc)
   108 	{
   109 	for (int ii=0; ii<WsdBuf().Length(); ii++)
   110 		{
   111 		if (WsdBuf()[ii] != start)
   112 			return KErrGeneral;
   113 		start += inc;
   114 		}
   115 	return KErrNone;
   116 	}
   117 #endif
   118 
   119 class CDllWsdServer : public CServer2
   120 	{
   121 public:
   122 	CDllWsdServer() : CServer2(EPriorityStandard)
   123 		{
   124 		}
   125 	CSession2* NewSessionL(const TVersion& /*aVersion*/,const RMessage2& /*aMessage*/) const;
   126 	mutable TInt iCount;
   127 	};
   128 
   129 class CDllWsdSession : public CSession2
   130 	{
   131 public:
   132 	CDllWsdSession()
   133 		{
   134 		ResetConsistencyCheck();
   135 		}
   136 		
   137 	~CDllWsdSession()
   138 		{
   139 		// transient server immediate shutdown when last client disconnects
   140 		if (--((CDllWsdServer*)Server())->iCount == 0)
   141 			CActiveScheduler::Stop();
   142 		}
   143 		
   144 	void ResetConsistencyCheck()
   145 		{
   146 		iX=42;
   147 		iY=0;
   148 		}
   149 
   150 	void OptResetConsistencyCheck()
   151 		{
   152 #if !defined(T_DLLWSD_DIRECT) && !defined(T_DLLWSD_INDIRECT)
   153 		// if DLL has been unloaded (dynamic library closed, no static link)
   154 		// WSD will be reset
   155 		ResetConsistencyCheck();
   156 #endif
   157 		}
   158 		
   159 	TInt TestConsistency()
   160 		{
   161 #ifdef T_DLLWSD_DIRECT
   162 		// static direct
   163 		if (WsdFuncX() != iX++)
   164 			return KErrGeneral;
   165 		if (WsdFuncY() != iY++)
   166 			return KErrGeneral;
   167 #endif
   168 
   169 #ifdef T_DLLWSD_INDIRECT
   170 		// static indirect
   171 		if (IndWsdFuncX() != iX++)
   172 			return KErrGeneral;
   173 		if (IndWsdFuncY() != iY++)
   174 			return KErrGeneral;
   175 #endif
   176 
   177 		// dynamic direct
   178 		OptResetConsistencyCheck();
   179 		RLibrary lib;
   180 		TInt err = lib.Load(_L("t_dllwsd_dll"));
   181 		if (err) return err;
   182 		if ((*lib.Lookup(1))/*WsdFuncX*/() != iX++)
   183 			return KErrGeneral;
   184 		if ((*lib.Lookup(2))/*WsdFuncX*/() != iY++)
   185 			return KErrGeneral;
   186 		lib.Close();
   187 
   188 		// dynamic indirect
   189 		OptResetConsistencyCheck();
   190 		err = lib.Load(_L("t_dllwsd_dlli"));
   191 		if (err) return err;
   192 		if ((*lib.Lookup(1))/*IndWsdFuncX*/() != iX++)
   193 			return KErrGeneral;
   194 		if ((*lib.Lookup(2))/*IndWsdFuncX*/() != iY++)
   195 			return KErrGeneral;
   196 		lib.Close();
   197 		
   198 		return KErrNone;
   199 		}
   200 		
   201 	TInt Thrash1()
   202 		{
   203 		TTime start;
   204 		start.HomeTime();
   205 		TInt count = 0;
   206 		const TTimeIntervalMicroSeconds limit(10000000); // 10 seconds
   207 		for (;; count++)
   208 			{
   209 			TInt err = TestConsistency();
   210 			if (err) return err;
   211 			TTime now;
   212 			now.HomeTime();
   213 			if (now.MicroSecondsFrom(start) > limit)
   214 				break;
   215 			}
   216 		return count > 0 ? count : -count;
   217 		}
   218 		
   219 	TInt IpcTest()
   220 		{
   221 #ifdef T_DLLWSD_DIRECT
   222     	RIpcTestSession s;
   223     	TInt err = s.Connect();
   224     	if (!err) return err;
   225         WsdBuf().SetLength(WsdBuf().MaxLength());
   226     	for (int i=0; i<10; i++)
   227     		{
   228     		// 0..n -> buf
   229 	        FillBuf(0,1);
   230 	        err = CheckBuf(0,1);
   231 	    	if (!err) return err;
   232 	        
   233 	        // buf -> server
   234 	        s.Set(WsdBuf(), WsdReq());
   235 	        err = CheckBuf(0,1);
   236 	    	if (!err) return err;
   237 	    	
   238 	    	// use TReqestStatus in WSD
   239 	        User::WaitForRequest(WsdReq());
   240 	        if (!WsdReq().Int()) return WsdReq().Int();
   241 	        
   242 	        // 0..0 -> buf
   243 	        FillBuf(0,0);
   244 	        err = CheckBuf(0,0);
   245 	    	if (!err) return err;
   246 	        WsdReq() = KRequestPending;
   247 
   248 			// reverse buf on server
   249 	        s.Reverse(WsdReq());
   250 	        
   251 			// local buf is still 0..0
   252 	        err = CheckBuf(0,0);
   253 	    	if (!err) return err;
   254 
   255 	    	// use TReqestStatus in WSD
   256 	        User::WaitForRequest(WsdReq());
   257 	        if (!WsdReq().Int()) return WsdReq().Int();
   258 
   259 			// local buf is still 0..0
   260 	        err = CheckBuf(0,0);
   261 	    	if (!err) return err;
   262 
   263 	        // get buf from server
   264 	        s.Get(WsdBuf(), WsdReq());
   265 	        User::WaitForRequest(WsdReq());
   266 	        
   267 	        // buf is n..0
   268 	        err = CheckBuf(59999,-1);
   269 	    	if (!err) return err;
   270     		}
   271     	s.Close();
   272 		return KErrNone;
   273 #else
   274 		return KErrNotSupported;
   275 #endif
   276 		}
   277 	
   278 	void ServiceL(const RMessage2& aMessage)
   279 		{
   280 #ifdef T_DLLWSD_DIRECT
   281 		TInt ii=0;
   282 #endif
   283 		switch (aMessage.Function())
   284 			{
   285 			case ETestFuncTestCons:
   286 				aMessage.Complete(TestConsistency());
   287 				break;
   288 			case ETestFuncThrash1:
   289 				aMessage.Complete(Thrash1());
   290 				break;
   291 			case ETestFuncIpcTest:
   292 				aMessage.Complete(IpcTest());
   293 				break;
   294 			case ETestFuncIpcGet:
   295 #ifdef T_DLLWSD_DIRECT
   296 				aMessage.WriteL(0, WsdBuf());
   297 				aMessage.Complete(KErrNone);
   298 #else
   299 				aMessage.Complete(KErrNotSupported);
   300 #endif
   301 				break;
   302 			case ETestFuncIpcReverse:
   303 #ifdef T_DLLWSD_DIRECT
   304 				for (ii=0; ii<WsdBuf().Length()/2; ii++)
   305 					{
   306 					TInt o = WsdBuf().Length() - 1 - ii;
   307 					TInt t = WsdBuf()[ii];
   308 					WsdBuf()[ii] = WsdBuf()[o];
   309 					WsdBuf()[o] = (unsigned short)t;
   310 					}
   311 				aMessage.Complete(KErrNone);
   312 #else
   313 				aMessage.Complete(KErrNotSupported);
   314 #endif
   315 				break;
   316 			case ETestFuncIpcSet:
   317 #ifdef T_DLLWSD_DIRECT
   318 				aMessage.ReadL(0, WsdBuf());
   319 				aMessage.Complete(KErrNone);
   320 #else
   321 				aMessage.Complete(KErrNotSupported);
   322 #endif
   323 				break;
   324 			case ETestFuncPanic:
   325 				User::Panic(_L("As requested..."), 0);
   326 				break;
   327 			default:
   328 				aMessage.Panic(_L("Unrecognised"), aMessage.Function());
   329 				break;
   330 			}
   331 		}
   332 	
   333 	int iX;
   334 	int iY;
   335 	};
   336 	
   337 CSession2* CDllWsdServer::NewSessionL(const TVersion& /*aVersion*/,const RMessage2& /*aMessage*/) const
   338 	{
   339 	iCount++;
   340 	return new(ELeave) CDllWsdSession;
   341 	}
   342 	
   343 TInt SlaveMain()
   344 	{
   345 	TName name;
   346 	User::CommandLine(name);
   347 	
   348 	CTrapCleanup* cleanup = CTrapCleanup::New();
   349 	if (!cleanup)
   350 		return KErrNoMemory;
   351 	
   352 	TRAPD(err, 
   353 		{
   354 		CActiveScheduler* sched=new(ELeave) CActiveScheduler;
   355 		CActiveScheduler::Install(sched);
   356 
   357 		CDllWsdServer* server = new(ELeave) CDllWsdServer;
   358 		server->StartL(name);
   359 
   360 		RProcess::Rendezvous(KErrNone);
   361 		CActiveScheduler::Start();
   362 		
   363 		delete server;
   364 		delete sched;
   365 		});
   366 	delete cleanup;
   367 
   368 	return err;
   369 	}
   370 
   371 //
   372 // Master test controller
   373 //
   374 
   375 class RDllWsd : public RSessionBase
   376 	{
   377 public:
   378 	RDllWsd(const TDesC& aServerName, const TDesC& aExeName = _L("t_dllwsddi"))
   379 		{
   380 		test.Start(_L("RDllWsd create"));
   381 		RProcess proc;
   382 		test_KErrNone(proc.Create(aExeName, aServerName));
   383 		TRequestStatus req;
   384 		proc.Rendezvous(req);
   385 		proc.Resume();
   386 		User::WaitForRequest(req);
   387 		test_KErrNone(req.Int());
   388 		test_KErrNone(CreateSession(aServerName, TVersion()));
   389 		proc.Close();
   390 		test.End();
   391 		}
   392 	TInt ConsistencyTest()
   393 		{
   394 		return SendReceive(ETestFuncTestCons);
   395 		}
   396 	void ThrashTest1(TRequestStatus& aStatus)
   397 		{
   398 		SendReceive(ETestFuncThrash1, aStatus);
   399 		}
   400 	TInt IpcTest()
   401 		{
   402 		return SendReceive(ETestFuncIpcTest);
   403 		}
   404 	TInt Panic()
   405 		{
   406 		return SendReceive(ETestFuncPanic);
   407 		}
   408 	};
   409 
   410 void BasicTest()
   411 	{
   412 	test.Start(_L("BasicConsistency"));
   413 
   414 	// create a test server/process for each link variant
   415 	RDllWsd slaves[] =
   416 		{
   417 		RDllWsd(_L("slave1"), _L("t_dllwsd")),
   418 		RDllWsd(_L("slave2"), _L("t_dllwsdd")),
   419 		RDllWsd(_L("slave3"), _L("t_dllwsdi")),
   420 		RDllWsd(_L("slave4"), _L("t_dllwsddi")),
   421 		RDllWsd(_L("slave5"), _L("t_dllwsd")),
   422 		RDllWsd(_L("slave6"), _L("t_dllwsdd")),
   423 		RDllWsd(_L("slave7"), _L("t_dllwsdi")),
   424 		RDllWsd(_L("slave8"), _L("t_dllwsddi"))
   425 		};
   426 	TInt nSlaves = sizeof(slaves)/sizeof(slaves[0]);
   427 	TInt ii;
   428 	// do this a few times
   429 	for (TInt jj=0; jj<10; jj++)
   430 		{
   431 		// all four test variants
   432 		for (ii=0; ii<nSlaves; ii++)
   433 			{
   434 			// repeat the test different numbers of times, to ensure WSD values diverge
   435 			for (TInt kk=0; kk<ii+2; kk++)
   436 				{
   437 				// change order in which processes run the tests
   438 				int idx = (ii + jj) % nSlaves;
   439 				test_KErrNone(slaves[idx].ConsistencyTest());
   440 				}
   441 			}
   442 		// start and stop an extra process
   443 		RDllWsd extra(_L("slave9"), _L("t_dllwsddi"));
   444 		test_KErrNone(extra.ConsistencyTest());
   445 		extra.Close();
   446 		}
   447 
   448 	for (ii=nSlaves-1; ii>=0; ii--)
   449 		slaves[ii].Close();
   450 
   451 	test.End();
   452 	}
   453 
   454 void ThrashTest1()
   455 	{
   456 	test.Start(_L("ThrashTest1"));
   457 
   458 	// create a test server/process for each link variant
   459 	RDllWsd slaves[4] =
   460 		{
   461 		RDllWsd(_L("slaveA"), _L("t_dllwsd")),
   462 		RDllWsd(_L("slaveB"), _L("t_dllwsdd")),
   463 		RDllWsd(_L("slaveC"), _L("t_dllwsdi")),
   464 		RDllWsd(_L("slaveD"), _L("t_dllwsddi"))
   465 		};
   466 	
   467 	TRequestStatus req[4];
   468 	TInt ii;
   469 	// start the thrash tests
   470 	for (ii=0; ii<4; ii++)
   471 		{
   472 		slaves[ii].ThrashTest1(req[ii]);
   473 		test.Printf(_L("slave %d thrash started\n"), ii);
   474 		}
   475 
   476 	// show some progress to indicate that things are running		
   477 	for (ii=0; ii<8; ii++)
   478 		{
   479 		test.Printf(_L("Waiting %d\n"), ii);
   480 		User::After(1000000);
   481 		}
   482 	// demonstrate that test processes are still doing their stuff
   483 	test.Printf(_L("Still a couple of seconds to wait...\n"));
   484 
   485 	// wait till the test process are done
   486 	for (ii=0; ii<4; ii++)
   487 		{
   488 		User::WaitForRequest(req[ii]);
   489 		// show how much each process did
   490 		test.Printf(_L("Slave %d count = %d\n"), ii, req[ii].Int());
   491 		test_NotNegative(req[ii].Int());
   492 		}
   493 		
   494 	for (ii=3; ii>=0; ii--)
   495 		slaves[ii].Close();
   496 
   497 	test.End();
   498 	}
   499 
   500 void PanicTest()
   501 	{
   502 	test.Start(_L("PanicTest1"));
   503 
   504 	// create a test server/process for each link variant
   505 	RDllWsd slaves[4] =
   506 		{
   507 		RDllWsd(_L("slaveP1"), _L("t_dllwsd")),
   508 		RDllWsd(_L("slaveP2"), _L("t_dllwsdd")),
   509 		RDllWsd(_L("slaveP3"), _L("t_dllwsdi")),
   510 		RDllWsd(_L("slaveP4"), _L("t_dllwsddi"))
   511 		};
   512 	TInt ii;
   513 	for (ii=0; ii<4; ii++)
   514 		slaves[ii].Panic();
   515 		
   516 	for (ii=0; ii<4; ii++)
   517 		slaves[ii].Close();
   518 	}
   519 
   520 void IpcTest()
   521 	{
   522 	test.Start(_L("IPC test"));
   523 	// these two processes will use t_dllwsddi, static link variant
   524 	RDllWsd server(_L("IpcTestServer"));
   525 	RDllWsd client(_L("IpcTestClient"));
   526 	// client will talk to IpcTestServer, ie the server
   527 	test_KErrNone(client.IpcTest());
   528 	client.Close();
   529 	server.Close();
   530 	test.End();
   531 	}
   532 	
   533 TInt MasterMain()
   534 	{
   535 	test.Title();
   536 	test.Start(_L("Test"));
   537 
   538 	BasicTest();
   539 	ThrashTest1();
   540 	IpcTest();
   541 //	PanicTest();
   542 
   543 	test.End();
   544 	return KErrNone;
   545 	}
   546 
   547 TInt E32Main()
   548 	{
   549 	if (User::CommandLineLength() > 0)	// command line contains server name
   550 		return SlaveMain();
   551 	else
   552 		return MasterMain();
   553 	}
   554