kerneltest/e32test/emi/t_emi.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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 	}