kerneltest/e32test/dll/t_dllwsd.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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