os/kernelhwsrv/kerneltest/e32test/emi/t_emi.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2005-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\emi\t_emi.cpp
    15 // 
    16 //
    17 
    18 #include <e32test.h>
    19 #include <e32math.h>
    20 #include <e32def.h>
    21 #include <e32def_private.h>
    22 #include "d_emitest.h"
    23 
    24 //#define VERBOSE
    25 
    26 LOCAL_D RTest test(_L("T_EMI"));
    27 
    28 _LIT(KEMITestLddFileName,"D_EMITEST");
    29 const TInt KHeapSize=0x200;
    30 
    31 REMITest Ldd;
    32 
    33 
    34 /*
    35 	TestEventLogging
    36 	
    37 	Tests initialisation of the logging system, ensuring no memory leaks, and then that user events can
    38 	be added and read correctly.
    39 	
    40 	The test tries filling and emptying the buffer from each possible start position.
    41 	Each time it over fills it (Causing offset to rotate) and each time try and take too many.
    42 	The last record should show the event lost flag. Each field is checked for consistency.
    43 
    44 */
    45 
    46 void TestEventLogging()
    47 	{		
    48 	TInt no;
    49 	TInt i;
    50 	TInt ii;
    51 	TInt iii;
    52 	TUint time;
    53 	TInt wrapcount = 0;
    54 	TInt changecount = 0;
    55  
    56 	TUserTaskEventRecord outrec;
    57 	TUserTaskEventRecord rec[5];
    58 	TUserTaskEventRecord blank;
    59 
    60 	
    61 //! @SYMTestCaseID t_emi_0
    62 //! @SYMTestType CT
    63 //! @SYMTestCaseDesc Set/Get State
    64 //! @SYMPREQ PREQ898
    65 //! @SYMTestActions Sets the EMI user state randomly 100 times, and reads back the state. 
    66 //! @SYMTestExpectedResults The read back state should always be the same as set.
    67 //! @SYMTestPriority High
    68 //! @SYMTestStatus Defined
    69 	
    70 	test.Next(_L("(Set/Get)State"));
    71 	for (i=0; i<100; i++) 
    72 		{
    73 		no = Math::Random();	
    74 		Ldd.SetState(no);
    75 		test(Ldd.GetState()==no);
    76 		}
    77 	
    78 //! @SYMTestCaseID t_emi_1
    79 //! @SYMTestType CT
    80 //! @SYMTestCaseDesc Log Alloc/Free
    81 //! @SYMPREQ PREQ898
    82 //! @SYMTestActions Allocates different sizes of event log.
    83 //! @SYMTestExpectedResults No memory leak.
    84 //! @SYMTestPriority High
    85 //! @SYMTestStatus Defined
    86 	
    87 	test.Next(_L("TaskEventLogging - Log Alloc/Free"));
    88 	
    89 	__KHEAP_MARK;	
    90 	test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone);
    91 	test(Ldd.TaskEventLogging(EFalse,2,ENone)==KErrNone);
    92 	test(Ldd.TaskEventLogging(EFalse,200,ENone)==KErrNone);
    93 	test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone);
    94 	__KHEAP_MARKEND;
    95 
    96 #ifdef _DEBUG
    97 	__KHEAP_MARK;
    98 	__KHEAP_FAILNEXT(1);
    99 	test(Ldd.TaskEventLogging(EFalse,200,ENone)==KErrNoMemory);
   100 	__KHEAP_MARKEND;
   101 #endif
   102 
   103 
   104 //! @SYMTestCaseID t_emi_2
   105 //! @SYMTestType CT
   106 //! @SYMTestCaseDesc AddTaskEvent/GetTaskEvent
   107 //! @SYMPREQ PREQ898
   108 //! @SYMTestActions Tries filling and emptying the buffer from each possible start position. Each time it over fills it (Causing offset to rotate) and each time try and take too many.
   109 //! @SYMTestExpectedResults The last record of each group should show the event lost flag.  Except for the lost record, the contents should be consistant with when the record was added.
   110 //! @SYMTestPriority High
   111 //! @SYMTestStatus Defined
   112 
   113 	test.Next(_L("AddTaskEvent/GetTaskEvent"));
   114 	
   115 	test(!Ldd.GetTaskEvent(outrec));
   116 
   117 	test(Ldd.TaskEventLogging(EFalse,5,ENone)==KErrNone);
   118 	
   119 	test(Ldd.AddTaskEvent(blank));
   120 	test(Ldd.GetTaskEvent(outrec));
   121 
   122 	time=outrec.iTime;
   123 
   124 	test(!Ldd.GetTaskEvent(outrec));
   125 		
   126 	// This next test tries filling and emptying the buffer from each possible start position.
   127 	// Each time it over fills it (Causeing offset to rotate) and each time try and take too many.
   128 	// The last record should show the event lost flag.
   129 		
   130 	// To ensure the time field is samething like you'd expect, let it tick over by 50.
   131 	iii=0;
   132 	do 	
   133 		{
   134 		for (ii=0; ii<5; ii++) 
   135 			{
   136 			test(Ldd.AddTaskEvent(blank)); //will be lost
   137 			for (i=0; i<5; i++)
   138 				{
   139 				rec[i].iType=(TUint8) ((Math::Random() & 255) | 128);
   140 				rec[i].iFlags=0;
   141 				rec[i].iExtra=(TUint16) (Math::Random() & 65535);
   142 				rec[i].iPrevious=&rec[i];
   143 				rec[i].iNext=&rec[ii];
   144 				no = Math::Random();
   145 				Ldd.SetState(no);
   146 				test(Ldd.AddTaskEvent(rec[i]));
   147 				rec[i].iUserState=no;
   148 				}
   149 			
   150 			for (i=0; i<5; i++)
   151 				{			
   152 				test(Ldd.GetTaskEvent(outrec));
   153 #ifdef VERBOSE
   154 				test.Printf(_L("%x : Type %x(%x), Time %x, flag %x, ThdA %x ThdB %x\n"),i,outrec.iType,rec[i].iType,outrec.iTime, outrec.iFlags, outrec.iPrevious,outrec.iNext);
   155 #endif
   156 				if (i==0)
   157 					test((outrec.iFlags & KEMI_EventLost)==KEMI_EventLost);
   158 				else 
   159 					test((outrec.iFlags & KEMI_EventLost)!=KEMI_EventLost);
   160 				
   161 				test(outrec.iType==rec[i].iType);
   162 				test(outrec.iExtra==rec[i].iExtra);
   163 				test(outrec.iPrevious==rec[i].iPrevious);
   164 				test(outrec.iNext==rec[i].iNext);
   165 				test(outrec.iUserState==rec[i].iUserState);
   166 				if (outrec.iTime!=time)
   167 					{
   168 					if (outrec.iTime<time)
   169 						wrapcount++;
   170 					time=outrec.iTime;
   171 					changecount++;
   172 					}
   173 				}
   174 			test(!Ldd.GetTaskEvent(outrec));
   175 			}
   176 #ifdef VERBOSE
   177 		test.Printf(_L("Time = %i\n"),time);
   178 #endif
   179 		iii++;		
   180 		if (changecount<50)
   181 			User::After(1);
   182 		} while ((changecount<50) && (iii<50));
   183 	test(changecount>=50);
   184 	test(wrapcount<2);
   185 	}
   186 
   187 
   188 
   189 /* Used by 	TestStartStopMonitors() and	TestScheduleEventLogging() */
   190 
   191 TBool ShortLivedThreadDone;
   192 
   193 LOCAL_C TInt ShortLivedThread(TAny*)
   194 	{
   195 	int i;
   196 	for (i=0; i<50; i++)
   197 		User::After(1);
   198 	ShortLivedThreadDone=ETrue;
   199 	return(KErrNone);
   200 	}
   201 
   202 
   203 /*
   204   TestStartStopMonitors
   205   
   206   Checks Start monitor was iterated with current thread list on startup.
   207   It then creates and destroys a thread, and see if it triggered the
   208   monitor callbacks in the test driver.  The test driver will add
   209   events to the event log, which are read and checked.
   210 
   211 */
   212 
   213 void TestStartStopMonitors()
   214 	{	
   215 	TInt i;
   216 	TInt no;
   217 	TUserTaskEventRecord outrec;
   218 	RThread thread;
   219 	TRequestStatus stat;		
   220 	TAny* myNThread;
   221 	TInt seenIdle;
   222 	TInt seenSigma;
   223 
   224 	TAny* idleThread;
   225 	TAny* sigmaThread;
   226 
   227 //! @SYMTestCaseID t_emi_5
   228 //! @SYMTestType CT
   229 //! @SYMTestCaseDesc Null/Sigma
   230 //! @SYMPREQ PREQ898
   231 //! @SYMTestActions Get the null and sigma thread pointers.
   232 //! @SYMTestExpectedResults Non-null pointers, which are usable in the following tests.
   233 //! @SYMTestPriority High
   234 //! @SYMTestStatus Defined
   235 
   236 
   237 	test.Next(_L("Check Null/Sigma"));
   238 	sigmaThread=Ldd.GetSigmaThread();
   239 	test(sigmaThread!=NULL);			
   240 	
   241 	idleThread=Ldd.GetIdleThread();
   242 	test(idleThread!=NULL);	
   243 
   244 	sigmaThread=((TInt*) sigmaThread)+1;
   245 	idleThread=((TInt*) idleThread)+1;
   246 
   247 //! @SYMTestCaseID t_emi_3
   248 //! @SYMTestType CT
   249 //! @SYMTestCaseDesc Thread start/stop Monitors
   250 //! @SYMPREQ PREQ898
   251 //! @SYMTestActions The start stop monitors are enabled.  The start/stop monitors have been made to add event log entries, to allow there execution to be visible. After all existing threads have be iterated by the start monitor, the log is first filled with random entries for the thread, and then the log is watched as a thread is started and stopped.
   252 //! @SYMTestExpectedResults At least 15 threads should be iterated on activation, and then both monitors should be called for the new thread. The random entries should have changed to refer to the sigma thread.
   253 //! @SYMTestPriority High
   254 //! @SYMTestStatus Defined
   255 
   256 	test.Next(_L("Thread start/stop Monitors"));
   257 	for (i=0; i<3; i++)
   258 		{
   259 		test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone);
   260 		test(Ldd.TaskEventLogging(EFalse,50,ENormal)==KErrNone);
   261 	
   262 
   263 		// Check Start monitor was iterated with current thread list.
   264 		test.Printf(_L("Check start monitor called for theads. (try %d)\n"),i);
   265 		
   266 		seenIdle=0;
   267 		seenSigma=0;	
   268 
   269 		no=0;
   270 		while (Ldd.GetTaskEvent(outrec))
   271 			{
   272 			test(outrec.iType==128);
   273 			if (outrec.iPrevious==sigmaThread)
   274 				{
   275 				test.Printf(_L("Seen Sigma Thread\n"));	
   276 				seenSigma++;
   277 				}
   278 			if (outrec.iPrevious==idleThread)
   279 				{
   280 				test.Printf(_L("Seen Idle Thread\n"));	
   281 				seenIdle++;
   282 				}
   283 
   284 			no++;
   285 			}
   286 		test.Printf(_L("Records = %d\n"),no);	
   287 		test(no>=15);
   288 		test(seenSigma==1);
   289 		test(seenIdle==1);
   290 		}
   291 		
   292 		
   293 		
   294 	test.Next(_L("Check monitor behaviour on thead creation/deletion"));
   295 
   296 	// To test monitors, we need to create and destroy a thread, and see if it 
   297 	// triggered the callbacks in the test driver.  The test driver will add
   298 	// events to the event log.
   299 	
   300 
   301 	// First Check for background noise
   302 	for (i=0; i<50; i++)
   303 		{		
   304 		test(!Ldd.GetTaskEvent(outrec));
   305 		User::After(1);
   306 		}
   307 		
   308 	test.Printf(_L("Create Thread..\n"));
   309 	// Start thread, and let it die
   310 	
   311 	test(thread.Create(_L("ShortLivedThread"),ShortLivedThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
   312 	thread.Logon(stat);
   313 	test(stat==KRequestPending);
   314 	
   315 	myNThread = Ldd.GetNThread(thread);
   316 
   317 	// Fill with records - should not survive cleanup
   318 	for (i=0; i<50; i++)
   319 		{
   320 		outrec.iType=(TUint8) (((Math::Random() & 63) + 10) | 128);
   321 		
   322 		outrec.iPrevious= i<5?myNThread:(TAny*) Math::Random();
   323 		outrec.iNext= i>10?myNThread:(TAny*) Math::Random();
   324 	
   325 		test(Ldd.AddTaskEvent(outrec));
   326 		}	
   327 		
   328 	// Let thead run
   329 	thread.Resume();
   330 	User::WaitForRequest(stat);
   331 	thread.Close();
   332 	test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone);
   333 	
   334 	// Did it leave log as expected?
   335 	test.Printf(_L("Check for logging/Clearing\n"));
   336 	i = 0;
   337 	no=0;
   338 	while (Ldd.GetTaskEvent(outrec)) 
   339 		{
   340 		i++;
   341 #ifdef VERBOSE
   342 		test.Printf(_L("%x : Type %x, Time %x,ThdA %x ThdB %x\n"),i,outrec.iType,outrec.iTime, outrec.iPrevious,outrec.iNext);
   343 #endif
   344 		if (outrec.iType==128) 
   345 			{
   346 			test((TInt)outrec.iPrevious==((TInt) myNThread)+4);
   347 			no++;
   348 			}
   349 		if (outrec.iType==129)
   350 			{				
   351 			test(outrec.iPrevious==myNThread);
   352 			no++;
   353 			}
   354 		else
   355 			{
   356 			test(outrec.iPrevious!=myNThread);
   357 			test(outrec.iNext!=myNThread);				
   358 			}
   359 		}
   360 	test (no==2);
   361 	}
   362 
   363 
   364 
   365 /* 
   366 
   367 Thread Tracking functions, 
   368 used in	TestScheduleEventLogging() and TestTagMaskDFC()
   369 
   370 */
   371 
   372 struct TThreadList
   373 	{
   374 	TAny* iThread;
   375 	TUint iRan;
   376 	};
   377 
   378 TThreadList ThreadList[51];
   379 TInt NoThreads=0;
   380 
   381 inline TUint LookupThread(TAny* aThread)
   382 	{
   383 	for (TInt i=0; i<NoThreads;i++)
   384 		if (aThread==ThreadList[i].iThread)
   385 			return i;
   386 	if (NoThreads<49)
   387 		{
   388 			ThreadList[NoThreads].iThread=aThread;
   389 			ThreadList[NoThreads].iRan=0;
   390 			NoThreads++;
   391 		
   392 		}
   393 	return NoThreads-1;	
   394 	}
   395 	
   396 void AddThread(TAny* aThread) 
   397 	{
   398 	test(NoThreads<49);
   399 	ThreadList[NoThreads].iThread=aThread;
   400 	ThreadList[NoThreads].iRan=0;
   401 	NoThreads++;
   402 	}
   403 
   404 
   405 /*
   406   TestScheduleEventLogging
   407   
   408   Checks AfterIdle, Null/Sigma thread lookup, Set/Get Loggable, as well as
   409   Schedule Event logging.  Select threads are marked as loggable, and starts a
   410   new thread (that repeatadly sleeps for short times, to generate events).
   411   The events are then collected and all of the fields checked.  The test
   412   
   413 */
   414 
   415 void TestScheduleEventLogging()
   416 	{	
   417 	RThread thread;
   418 	TRequestStatus stat;		
   419 	TAny* myNThread;
   420 	TInt i;
   421 	TInt ii;
   422 	TUint time=0;
   423 	TInt wrapcount = 0;
   424 	TInt changecount = 0;
   425 	TUserTaskEventRecord outrec;
   426 
   427 
   428 //! @SYMTestCaseID t_emi_4
   429 //! @SYMTestType CT
   430 //! @SYMTestCaseDesc AfterIdle
   431 //! @SYMPREQ PREQ898
   432 //! @SYMTestActions Uses AfterIdle.
   433 //! @SYMTestExpectedResults No panic.
   434 //! @SYMTestPriority High
   435 //! @SYMTestStatus Defined
   436 
   437 
   438 	test.Next(_L("Check AfterIdle"));
   439 	Ldd.AfterIdle(100);
   440 		
   441 	
   442 //! @SYMTestCaseID t_emi_6
   443 //! @SYMTestType CT
   444 //! @SYMTestCaseDesc Set/Get Loggable
   445 //! @SYMPREQ PREQ898
   446 //! @SYMTestActions Get/Set ThreadLoggable are used on multiple threads.
   447 //! @SYMTestExpectedResults The Get function should confirm that the Set function changed the loggable state.
   448 //! @SYMTestPriority High
   449 //! @SYMTestStatus Defined
   450 
   451 	test.Next(_L("Check Set/Get Loggable"));
   452 	myNThread=Ldd.GetSigmaThread();
   453 	test(myNThread!=NULL);		
   454 	AddThread(myNThread);
   455 		
   456 	myNThread=Ldd.GetIdleThread();
   457 	test(myNThread!=NULL);		
   458 	AddThread(myNThread);
   459 
   460 	
   461 	Ldd.SetThreadLoggable(myNThread,ETrue);
   462 	test(Ldd.GetThreadLoggable(myNThread)!=EFalse);
   463 
   464 	Ldd.SetThreadLoggable(myNThread,EFalse);
   465 	test(Ldd.GetThreadLoggable(myNThread)==EFalse);
   466 
   467 	Ldd.SetThreadLoggable(myNThread,ETrue);
   468 	test(Ldd.GetThreadLoggable(myNThread)!=EFalse);
   469 		
   470 	
   471 //! @SYMTestCaseID t_emi_7
   472 //! @SYMTestType CT
   473 //! @SYMTestCaseDesc Set/Get VEMSData
   474 //! @SYMPREQ PREQ898
   475 //! @SYMTestActions Get/Set VEMSData are used on a thread 100 times.
   476 //! @SYMTestExpectedResults The Get function should confirm that the Set function set the value correctly.
   477 //! @SYMTestPriority High
   478 //! @SYMTestStatus Defined
   479 
   480 	
   481 	test.Next(_L("(Set/Get) VEMSData"));
   482 	
   483 	test.Printf(_L("Spawn Thread\n"));
   484 	ShortLivedThreadDone=EFalse;
   485 	test(thread.Create(_L("ShortLivedThread"),ShortLivedThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
   486 	thread.Logon(stat);
   487 	test(stat==KRequestPending);	
   488 	myNThread = Ldd.GetNThread(thread);
   489 	Ldd.SetThreadLoggable(myNThread,ETrue);
   490 	AddThread(myNThread);
   491 	test(Ldd.GetThreadLoggable(myNThread)!=EFalse);
   492 
   493 	for (i=0; i<100; i++) 
   494 		{
   495 		ii = Math::Random();
   496 		Ldd.SetVEMSData(myNThread,(TAny*)ii);
   497 		test((TInt)Ldd.GetVEMSData(myNThread)==ii);
   498 		}
   499 
   500 //! @SYMTestCaseID t_emi_8
   501 //! @SYMTestType CT
   502 //! @SYMTestCaseDesc Task Event Logging
   503 //! @SYMPREQ PREQ898
   504 //! @SYMTestActions Task event logging is turned on, with a thread running in the background. Some threads set as loggable. Each event record is inspected, and a count for the seen thread in incremented. User state is incremented on each iteration.
   505 //! @SYMTestExpectedResults Each thread ran at lest 10 times.  Time changed over 45 times, but wrapped no more then once. User state changed over 15, some events where seen to be waiting, thread order is consistent, record type is correct, and at lest 100 records where read before the test finished.
   506 //! @SYMTestPriority High
   507 //! @SYMTestStatus Defined
   508 
   509 
   510 		
   511 	test.Next(_L("Task Event Logging"));	
   512 	
   513 	Ldd.SetState(0);
   514 	thread.Resume();
   515 	User::After(1);
   516 	test(Ldd.TaskEventLogging(ETrue,50,ENone)==KErrNone);
   517 	i=0;
   518 	ii=0;
   519 	TInt prevNextThread=-1;
   520 	TInt lastThread;
   521 	TInt nextThread;
   522 	TBool seenWaiting=EFalse;
   523 	wrapcount=0;
   524 	changecount=0;
   525 	TUint lastUserState=0;
   526 	TInt userStateChange=0;
   527 	FOREVER
   528 		{
   529 		
   530 		if (!Ldd.GetTaskEvent(outrec))
   531 			{			
   532 			if ((i>100) && ShortLivedThreadDone)
   533 				break;
   534 			Ldd.AfterIdle(5);
   535 			test((ii++)<500); //timeout!
   536 			}
   537 		else
   538 			{
   539 			lastThread=LookupThread(outrec.iPrevious);
   540 			nextThread=LookupThread(outrec.iNext);
   541 #ifdef VERBOSE
   542 			test.Printf(_L("%x: Ty %x Tm %x ThdA %x ThdB %x F %x U %x\n"),
   543 				i,outrec.iType,outrec.iTime, lastThread,nextThread, outrec.iFlags, outrec.iUserState);
   544 #endif
   545 			test(outrec.iType==0);
   546 			
   547 			
   548 			if (outrec.iTime!=time)
   549 				{
   550 				if ((outrec.iTime<time) && (time!=0))
   551 					wrapcount++;
   552 				time=outrec.iTime;
   553 				changecount++;
   554 				}			
   555 			
   556 			if ((outrec.iFlags & KEMI_PrevWaiting)!=0)
   557 				seenWaiting=ETrue;
   558 			
   559 			if (((outrec.iFlags & KEMI_EventLost)==0) && (prevNextThread!=-1))
   560 				test (prevNextThread==lastThread);
   561 			prevNextThread=nextThread;
   562 			ThreadList[nextThread].iRan++;
   563 
   564 			test(outrec.iUserState>=lastUserState);
   565 			if (outrec.iUserState!=lastUserState)
   566 				{
   567 				userStateChange++;
   568 				lastUserState=outrec.iUserState;
   569 				}
   570 
   571 			i++;
   572 			Ldd.SetState(i);
   573 			}
   574 		if ((i>100) && ShortLivedThreadDone)
   575 			test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone);			
   576 		}
   577 
   578 	test.Printf(_L("DTime %x DState %x Wrap %x\n"),changecount,userStateChange, wrapcount);
   579 
   580 	test(changecount>=45);
   581 	test(userStateChange>15);
   582 	test(wrapcount<2);
   583 		
   584 	test(seenWaiting);
   585 	
   586 	User::WaitForRequest(stat);
   587 	thread.Close();
   588 	
   589 	for (i=0; i<NoThreads;i++)
   590 		{		
   591 		test.Printf(_L("Thread %x ran %d times.\n"),i,ThreadList[i].iRan);
   592 		test(ThreadList[i].iRan>10);
   593 		}
   594 	}
   595 
   596 
   597 
   598 
   599 /* TagMaskTestThread() - used by TestTagMaskDFC */
   600 LOCAL_C TInt TagMaskTestThread(TAny*)
   601 	{
   602 	TInt i;
   603 	TInt mask=1;
   604 	for (i=0; i<31; i++)
   605 		{		
   606 		User::After(1);
   607 		mask = mask << 1;
   608 		Ldd.SetMask(mask);
   609 		}
   610 	ShortLivedThreadDone=ETrue;
   611 	return(KErrNone);
   612 	}
   613 
   614 /*
   615   TestTagMaskDFC()
   616 
   617   Checks Mask and Tag setting.
   618   Checks a that a DFC (found in driver) is triggered my an apropriate tag and mask.
   619 */
   620 
   621 void TestTagMaskDFC()
   622 	{	
   623 	RThread thread;
   624 	TRequestStatus stat;		
   625 	TAny* myNThread;
   626 	TUserTaskEventRecord outrec;
   627 	TInt i=0;
   628 	TInt ii=0;
   629 	TInt seen9=0;
   630 	TInt seen18=0;
   631 	TInt seen27=0;	
   632 	TUint no;
   633 	
   634 #ifdef VERBOSE	
   635 	TInt lastThread;
   636 #endif	
   637 	TInt nextThread;
   638 
   639 
   640 //! @SYMTestCaseID t_emi_9
   641 //! @SYMTestType CT
   642 //! @SYMTestCaseDesc Set/Get Mask
   643 //! @SYMPREQ PREQ898
   644 //! @SYMTestActions Get/Set the mask 100 times.
   645 //! @SYMTestExpectedResults The Get function should confirm that the Set function changed the mask state.
   646 //! @SYMTestPriority High
   647 //! @SYMTestStatus Defined
   648 
   649 
   650 	test.Next(_L("(Set/Get)Mask"));
   651 	for (i=0; i<100; i++) 
   652 		{
   653 		no = Math::Random();
   654 		Ldd.SetMask(no);
   655 		test(Ldd.GetMask()==no);
   656 		}
   657 
   658 //! @SYMTestCaseID t_emi_10
   659 //! @SYMTestType CT
   660 //! @SYMTestCaseDesc Tag/Mask DFC
   661 //! @SYMPREQ PREQ898
   662 //! @SYMTestActions A DFC is set than will change the user state to the results of GetDFCTriggerTag.  The event log is monitored, with a background thread, which has had a tag set.  This thread repeatedly changes the mask.
   663 //! @SYMTestExpectedResults The state should be seen to change once to the correct tag for the thread.  Other factors also checked in t_emi_7 should show the test running correctly.
   664 //! @SYMTestPriority High
   665 //! @SYMTestStatus Defined
   666 
   667 
   668 	test.Next(_L("Tag/Mask DFC."));
   669 	
   670 	NoThreads=0; // Reset Thread Tracking
   671 	
   672 	myNThread=Ldd.GetSigmaThread();
   673 	test(myNThread!=NULL);		
   674 	AddThread(myNThread);
   675 	
   676 	myNThread=Ldd.GetIdleThread();
   677 	test(myNThread!=NULL);		
   678 	AddThread(myNThread);
   679 	
   680 	Ldd.SetThreadLoggable(myNThread,ETrue);
   681 	test(Ldd.GetThreadLoggable(myNThread)!=EFalse);
   682 		
   683 	Ldd.SetDfc();
   684 	test(Ldd.GetMask()==0);
   685 	
   686 	test.Printf(_L("Spawn Thread\n"));
   687 	ShortLivedThreadDone=EFalse;
   688 	test(thread.Create(_L("TagMaskTestThread"),TagMaskTestThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
   689 	thread.Logon(stat);
   690 	test(stat==KRequestPending);	
   691 	myNThread = Ldd.GetNThread(thread);
   692 	test(Ldd.GetThreadLoggable(myNThread)==EFalse);
   693 	Ldd.SetThreadLoggable(myNThread,ETrue);
   694 	test(Ldd.GetThreadLoggable(myNThread)!=EFalse);
   695 	AddThread(myNThread);
   696 	Ldd.SetThreadTag(myNThread,(1<<9)+(1<<18)+(1<<27));
   697 	test(Ldd.GetThreadTag(myNThread)==(1<<9)+(1<<18)+(1<<27));
   698 	
   699 	Ldd.SetState(0);
   700 	
   701 	test.Printf(_L("Start Event Logging\n"));
   702 	test(Ldd.TaskEventLogging(ETrue,50,ENone)==KErrNone);
   703 
   704 	thread.Resume();
   705 	
   706 	FOREVER
   707 		{		
   708 		if (!Ldd.GetTaskEvent(outrec))
   709 			{			
   710 			if ((i>100) && ShortLivedThreadDone)
   711 				break;
   712 			Ldd.AfterIdle(5);
   713 			test((ii++)<500); //timeout!
   714 			}
   715 		else
   716 			{
   717 
   718 #ifdef VERBOSE
   719 			lastThread=LookupThread(outrec.iPrevious);
   720 #else
   721 			LookupThread(outrec.iPrevious);
   722 #endif
   723 			nextThread=LookupThread(outrec.iNext);
   724 			
   725 #ifdef VERBOSE
   726 			test.Printf(_L("%x: Ty %x Tm %x ThdA %x ThdB %x F %x U %x\n"),
   727 				i,outrec.iType,outrec.iTime, lastThread,nextThread, outrec.iFlags, outrec.iUserState);
   728 #endif
   729 
   730 			ThreadList[nextThread].iRan++;
   731 				
   732 			switch(outrec.iUserState)
   733 				{
   734 				case 0      : break;
   735 				case (1<<9) : ++seen9; break;
   736 				case (1<<18): ++seen18; break;
   737 				case (1<<27): ++seen27; break;
   738 				default: test(0); // bad state
   739 				}
   740 			}
   741 		i++;		
   742 		if ((i>100) && ShortLivedThreadDone)
   743 			test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone);
   744 		
   745 		}
   746 	Ldd.SetMask(0);
   747 
   748 	test(seen9);
   749 	test(seen18);
   750 	test(seen27);
   751 	User::WaitForRequest(stat);
   752 	thread.Close();
   753 		
   754 	for (i=0; i<NoThreads;i++)
   755 		{		
   756 		test.Printf(_L("Thread %x ran %d times.\n"),i,ThreadList[i].iRan);
   757 		test(ThreadList[i].iRan>10);
   758 		}
   759 	test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone);	
   760 	}
   761 
   762 
   763 /*
   764 void SoakTest()
   765 
   766 Repeatedly changes the start/exit monitors, while repeatedly starting and stopping threads.
   767 As threads exit, they are checked for consistency.
   768 
   769 */
   770 
   771 TBool FinishedSoak=EFalse;
   772 TBool Going=EFalse;
   773 LOCAL_C TInt SoakTest_Thread(TAny*)
   774 	{
   775 	int i;
   776 	Going=ETrue;
   777 	for (i=(Math::Random() & 1); i<2; i++)
   778 			User::AfterHighRes(1000+(Math::Random() & 31));
   779 	return(KErrNone);
   780 	}
   781 
   782 TInt MainCount=0;
   783 TInt ThreadGenCount=0;
   784 TInt Maxloops=4100;
   785 TBool Forever=EFalse;
   786 TInt State=1;
   787 TInt GoodCount=0;
   788 
   789 LOCAL_C TInt SoakTest_ThreadGenerator(TAny*)
   790 	{
   791 	const TInt NOTHREADS=100;
   792 
   793 	RThread threadlist[NOTHREADS];
   794 	TRequestStatus threadlist_stat[NOTHREADS];
   795 	TInt head=0;
   796 	TInt tail=0;
   797 	TBool done=EFalse;
   798 	TInt newHead;
   799 	RThread thisThread = RThread();
   800 	FOREVER
   801 		{
   802 		
   803 		switch (Math::Random() & 63) 
   804 			{
   805 			case 1: thisThread.SetPriority(EPriorityLess);
   806 			break;
   807 			case 2: thisThread.SetPriority(EPriorityNormal);
   808 			break;
   809 			case 3: thisThread.SetPriority(EPriorityMore);
   810 			break;
   811 			}
   812 			
   813 		newHead = head+1;
   814 		if (newHead==NOTHREADS)
   815 			newHead=0;
   816 		if ((newHead!=tail) &&  !done) //not full & not finished
   817 			{
   818 			test(threadlist[head].Create(_L(""),SoakTest_Thread,KDefaultStackSize,NULL,NULL)==KErrNone);
   819 			threadlist[head].Logon(threadlist_stat[head]);
   820 			switch (Math::Random() & 3) 
   821 				{
   822 				case 1: threadlist[head].SetPriority(EPriorityLess);
   823 				break;
   824 				case 2: threadlist[head].SetPriority(EPriorityNormal);
   825 				break;
   826 				case 3: threadlist[head].SetPriority(EPriorityMore);
   827 				break;
   828 				}
   829 
   830 			threadlist[head].Resume();
   831 			head=newHead;
   832 			}
   833 		else
   834 			{
   835 			if (head==tail)//empty
   836 				{
   837 				
   838 				if (done)
   839 					break;			
   840 				}
   841 
   842 			else
   843 				{				
   844 				User::WaitForRequest(threadlist_stat[tail] );
   845 	
   846 				if (State==1)
   847 					{
   848 					State=(TInt) Ldd.GetVEMSData(Ldd.GetNThread(threadlist[tail]));
   849 					if (State!=1)
   850 						done=ETrue;
   851 					else
   852 						GoodCount++;
   853 					}
   854 				threadlist[tail].Close();
   855 				tail++;
   856 				if (tail==NOTHREADS)
   857 					tail=0;
   858 				}					
   859 			}
   860 		if ((Math::Random() & 63)==1)
   861 				User::AfterHighRes((Math::Random() & 32));
   862 		ThreadGenCount=MainCount;
   863 		if ((ThreadGenCount>=Maxloops) && !Forever)
   864 			done=ETrue;
   865 		}
   866 	FinishedSoak=ETrue;
   867 	return(KErrNone);
   868 	}
   869 
   870 
   871 void SoakTest()
   872 	{
   873 	RThread threadGenerator;
   874 	TRequestStatus stat;
   875 	TInt count=0;
   876 	TInt oldcount=0;
   877 	RThread thisThread = RThread();
   878 	TInt ret;
   879 	TMonitors monitor=EStressSecond;
   880 
   881 	test.Next(_L("Repeated monitor switching Test"));
   882 	test(Ldd.TaskEventLogging(EFalse,0,EStressSecond)==KErrNone);
   883 
   884 	for (count=1; count<100; count++) 
   885 		{
   886 		
   887 		Going=EFalse;
   888 		test(threadGenerator.Create(_L(""),SoakTest_Thread,KDefaultStackSize,NULL,NULL)==KErrNone);
   889 		threadGenerator.Logon(stat);
   890 		test(stat==KRequestPending);	
   891 		threadGenerator.Resume();
   892 		while (!Going)	User::AfterHighRes(Math::Random() & 15);
   893 
   894 		monitor= (monitor==EStressFirst)?EStressSecond:EStressFirst;
   895 		test(Ldd.TaskEventLogging(EFalse,0,monitor)==KErrNone);
   896 		
   897 		if (count & 1)
   898 			{
   899 			monitor= (monitor==EStressFirst)?EStressSecond:EStressFirst;
   900 			test(Ldd.TaskEventLogging(EFalse,0,monitor)==KErrNone);
   901 			}
   902 		User::WaitForRequest(stat);
   903 		ret=(TInt) Ldd.GetVEMSData(Ldd.GetNThread(threadGenerator));
   904 		if (ret!=1)
   905 			test.Printf(_L("Thread %x had VEMs value was %x \n"),count,ret);
   906 		threadGenerator.Close();
   907 		test(ret==1);
   908 		}
   909 
   910 
   911 	// Full soak test
   912 	
   913 	count=1;
   914 	test.Next(_L("Soak test"));
   915 	test(Ldd.TaskEventLogging(EFalse,0,EStressSecond)==KErrNone);
   916 
   917 	// Start threadGenerator
   918 	test(threadGenerator.Create(_L("threadGenerator"),SoakTest_ThreadGenerator,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
   919 	threadGenerator.Logon(stat);
   920 	test(stat==KRequestPending);	
   921 	threadGenerator.Resume();
   922 	
   923 	for (;!FinishedSoak; MainCount=ThreadGenCount+1) 
   924 		{
   925 			switch (Math::Random() & 63) 
   926 			{
   927 			case 1: thisThread.SetPriority(EPriorityLess);
   928 			break;
   929 			case 2: thisThread.SetPriority(EPriorityNormal);
   930 			break;
   931 			case 3: thisThread.SetPriority(EPriorityMore);
   932 			break;
   933 			}
   934 
   935 		// Now repeatadly start and stop the start/exit monitors.
   936 		test(Ldd.TaskEventLogging(EFalse,0,EStressFirst)==KErrNone);
   937 		if ((Math::Random() & 63)==1)
   938 				User::AfterHighRes((Math::Random() & 31));
   939 		test(Ldd.TaskEventLogging(EFalse,0,EStressSecond)==KErrNone);
   940 		if (MainCount>>7 != oldcount)
   941 			{	
   942 			oldcount=MainCount>>7;
   943 			if ((count & 15)==1)
   944 				test.Printf(_L("\nCount: "));			
   945 			test.Printf(_L("%x "),count);
   946 	
   947 			count++;
   948 			}
   949 		if ((Math::Random() & 63)==1)
   950 			User::AfterHighRes((Math::Random() & 31));
   951 		}
   952 		
   953 	test.Printf(_L("\nDone.\n: "));	
   954 	User::WaitForRequest(stat);
   955 	threadGenerator.Close();
   956 	if (State!=1)
   957 		{
   958 		test.Printf(_L("Thread %x VEMs value was %x \n"),GoodCount,State);
   959 		test(0);
   960 		}
   961 
   962 	test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone);
   963 	}
   964 
   965 void ParseCommandLine()
   966 	{
   967 	TBuf<32> args;
   968 	User::CommandLine(args);
   969 	
   970 	if (args == KNullDesC)
   971 		{
   972 		test.Printf(_L("No soaklength specified, using default.\n"));
   973 		return;
   974 		}
   975 	else if (args == _L("-"))
   976 		{
   977 		test.Printf(_L("Infinate soaklength specified.\n"));
   978 
   979 		Forever=ETrue;
   980 		}
   981 	else 
   982 		{
   983 		TLex l(args);
   984 		TInt r = l.Val(Maxloops);
   985 		if (r != KErrNone)
   986 			{
   987 			test.Printf(_L("Bad parameter!\nUsage: t_emi <soaklength>\n       '-' indicates infinity.\n\n"));
   988 			User::After(4000000);
   989 			test(0);
   990 			}
   991 		else
   992 			{
   993 			test.Printf(_L("Soaklength set to 0x%x\n"),Maxloops);
   994 			Maxloops = Maxloops << 7;
   995 			}
   996 
   997 		}
   998 	}
   999 
  1000 /* 
  1001  E32Main - Where it all begins.
  1002 */
  1003 
  1004 GLDEF_C TInt E32Main()
  1005 	{
  1006 	TInt r;
  1007 
  1008 	test.Title();
  1009 	ParseCommandLine();
  1010 
  1011 	test.Start(_L("Loading Device"));
  1012 
  1013 	r=User::LoadLogicalDevice(KEMITestLddFileName);
  1014 	test(r==KErrNone || r==KErrAlreadyExists);
  1015 
  1016 	test.Next(_L("Open Logical Channel"));
  1017 	r=Ldd.Open();
  1018 	test(r==KErrNone);
  1019 	
  1020 	
  1021 	test.Next(_L("Calling LDD"));
  1022 
  1023 	if(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNotSupported)
  1024 		{
  1025 		test.Printf(_L("********************\n"));
  1026 		test.Printf(_L("*  NO EMI SUPPORT  *\n"));
  1027 		test.Printf(_L("********************\n"));
  1028 		test.Printf(_L("*  Testing SKIPPED *\n"));
  1029 		test.Printf(_L("********************\n"));
  1030 		User::After(2000000);  //Time to read it!
  1031 		test.Next(_L("Close Logical Channel"));
  1032 		Ldd.Close();
  1033 		test.End();
  1034 		return(0);
  1035 		}
  1036 
  1037 	// Start Testing!
  1038 	
  1039 	TestEventLogging();
  1040 	TestStartStopMonitors();
  1041 	TestScheduleEventLogging();		
  1042 	TestTagMaskDFC();
  1043 	SoakTest();
  1044 
  1045 	test.Next(_L("Close Logical Channel"));
  1046 	Ldd.Close();
  1047 	test.End();
  1048 
  1049 	return(0);
  1050 	}