os/kernelhwsrv/kerneltest/e32test/debug/t_perflogger.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 // Kernel Performance Logger test
    15 // Uses helper LDD for performing actual logging from the kernel side.
    16 // See 
    17 // 
    18 //
    19 
    20 /**
    21  @file
    22 */
    23 
    24 
    25 #include <e32std.h>
    26 #include <e32std_private.h>
    27 #include <e32cons.h>
    28 #include <e32test.h>
    29 #include <e32math.h>
    30 
    31 
    32 #include "t_perflogger.h"
    33 #include "t_perflogger_drv.h"
    34 
    35 
    36 //-------------------------------------------------------------------------------------
    37 
    38 //-- logging subcategoty test tags
    39 const TUint8    KLogSubCat_UserThread   = 0x11;
    40 const TUint8    KLogSubCat_KernelThread = 0x12;
    41 const TUint8    KLogSubCat_ISR          = 0x13;
    42 const TUint8    KLogSubCat_IDFC         = 0x14;
    43 
    44 
    45 //-------------------------------------------------------------------------------------
    46 
    47 RTest   test(_L("T_PerfLogger"));
    48 TInt64  rndSeed;
    49 
    50 //-------------------------------------------------------------------------------------
    51 
    52 /**
    53 Print out the logging record.
    54 @param aTraceLayout unrolled trace record structure
    55 */
    56 void  PrintTraceRecord(const TTraceLayout& aTraceLayout)
    57 	{
    58     TBuf<256> printBuf;
    59     
    60     printBuf.Format(_L("Record: Size:%d, Flags:0x%02x, Cat:%d, SubCat:%d "), aTraceLayout.iSize, aTraceLayout.iFlags, aTraceLayout.iCategory, aTraceLayout.iSubCategory);
    61 	
    62     TUint flags = aTraceLayout.iFlags;
    63 	
    64     if(flags&(BTrace::EHeader2Present))
    65         printBuf.AppendFormat(_L("Header2:0x%08x "), aTraceLayout.iHeader2);
    66 	
    67     if(flags & (BTrace::ETimestampPresent))
    68         printBuf.AppendFormat(_L("Timestamp:0x%x "), aTraceLayout.iTimestamp);
    69 	
    70     if(flags & (BTrace::ETimestamp2Present))
    71         printBuf.AppendFormat(_L("Timestamp2:0x%x "), aTraceLayout.iTimestamp2);
    72 	
    73     if(flags & (BTrace::EContextIdPresent))
    74         printBuf.AppendFormat(_L("Context:0x%08x "), aTraceLayout.iContext);
    75 	
    76     if(flags & (BTrace::EPcPresent))
    77         printBuf.AppendFormat(_L("PC: 0x%08x "),  aTraceLayout.iPC);
    78 	
    79     if(flags & (BTrace::EExtraPresent))
    80         printBuf.AppendFormat(_L("Extra: 0x%08x "),  aTraceLayout.iExtra);
    81 	
    82     printBuf.Append(_L("| "));
    83     for(TInt i=0; i< aTraceLayout.iDataWords; ++i)
    84 		{
    85         printBuf.AppendFormat(_L(" 0x%08x"), aTraceLayout.ipData[i]);    
    86 		}
    87     
    88     printBuf.Append(_L("\n"));
    89     test.Printf(printBuf);
    90 	
    91 	}
    92 
    93 //-------------------------------------------------------------------------------------
    94 
    95 /**
    96 	Get logging trace from the kernel trace engine and optionally check if it corresponds to the 
    97 	TTestLogCtrl structure fields. Actually, the logging trace in our case shall be the result of the 
    98 	test helper LDD worr, that in turn, is controlled by the data in TTestLogCtrl structure.
    99 
   100   @param  aTrace          ref. to the kernel trace engine LDD.
   101   @param  apControlStruct if not NULL obtained trace fields checked against fields of this structure.
   102   
   103 */
   104 void GetParseRecordData(RBTrace& aTrace, const TTestLogCtrl* apControlStruct = NULL)
   105 	{
   106     TUint8*         record;
   107     TTraceLayout    traceLayout;
   108 	
   109 	for(TInt i=0; ;++i)
   110 		{
   111         //-- get raw trace record
   112         TInt dataSize = aTrace.GetData(record);
   113 		
   114         if(i != 0 && !dataSize)
   115             break; //-- no more data
   116         
   117         //-- check if we get log data at all at the very beginning
   118         if(i == 0 && !dataSize)
   119 			{
   120 			if(!apControlStruct)
   121 				{//-- it's ok, no check
   122                 break;
   123 				}
   124             else
   125 				{//-- panic if there is no log data, but we are required to get some.
   126                 if(apControlStruct->iLogsNum > 0)
   127 					{
   128                     test.Printf(_L("GetParseRecordData() No trace data found!\n"));
   129                     test(0);
   130 					}
   131 				}
   132 			}
   133         
   134 		
   135         TUint8* end = record+dataSize;
   136         TUint8* currPos = record;
   137         TInt    nRecords = 0;
   138 		TUint nBytes = 0;
   139 		
   140         //-- parser the record, print out fields and optionally check the correspondence to the fields of the control structure.
   141         for(; currPos<end; currPos+=nBytes)
   142 			{
   143             
   144             nBytes = ParseTraceRecord(currPos ,traceLayout);
   145             test(nBytes >0 );
   146             
   147             //-- skip possible loggings that we didn't make
   148             if(traceLayout.iCategory != BTrace::EKernPerfLog)
   149                 continue;
   150             
   151             ++nRecords;
   152 			
   153             //-- print the record out
   154             PrintTraceRecord(traceLayout);
   155 
   156 			//-- check the obtained record structure
   157 			if(apControlStruct)
   158 				{
   159 				test(traceLayout.iCategory    == apControlStruct->iCategory);
   160 				test(traceLayout.iSubCategory == apControlStruct->iSubCategory);
   161 				
   162 				if(traceLayout.iDataWords > 1)  //-- we have at least 1 word of user data (1 is for TickCount)
   163 					test(traceLayout.ipData[0] == apControlStruct->iUserData);
   164 				
   165 				if(traceLayout.iDataWords > 2)  //-- we have 2 words of user data (1 is for TickCount)
   166 					test(traceLayout.ipData[1] == apControlStruct->iUserData2);
   167 				
   168 				}
   169             
   170 			}
   171 		
   172         //-- check number of trace records obtained
   173         if(apControlStruct)
   174 			{
   175             test(nRecords == apControlStruct->iLogsNum);
   176 			}
   177 		
   178         //-- release data buffer.
   179         aTrace.DataUsed();
   180 		}
   181 	}
   182 
   183 
   184 //---------------------------------------------------------------------------------
   185 
   186 /**
   187 	Parse logging record, converting it from the raw representation to the unrolled data 
   188 	structure.
   189 
   190 	@param  apRecord     points to the buffer with the raw trace record
   191 	@param  aTraceLayout here parsed record will bre returned
   192   
   193     @return sise of the record, bytes
   194 */
   195 TUint  ParseTraceRecord(const TUint8* apRecord, TTraceLayout& aTraceLayout)
   196 	{
   197     aTraceLayout.iSize          = apRecord[BTrace::ESizeIndex];    
   198     aTraceLayout.iFlags         = apRecord[BTrace::EFlagsIndex];
   199     aTraceLayout.iCategory      = apRecord[BTrace::ECategoryIndex];
   200     aTraceLayout.iSubCategory   = apRecord[BTrace::ESubCategoryIndex];
   201 	
   202     const TUint flags= aTraceLayout.iFlags;   
   203 	TInt size = aTraceLayout.iSize;
   204     const TUint32* pData = (const TUint32*)(apRecord+4);
   205 	
   206     size -= 4; //-- count header
   207 	
   208     //-- process header flags and appropriate fields of the record
   209     if(flags&(BTrace::EHeader2Present))
   210 		{
   211         aTraceLayout.iHeader2 = *pData++;   
   212         size -= sizeof(TUint32);
   213         test(size >= 0);
   214 		}
   215 	
   216     if(flags & (BTrace::ETimestampPresent))
   217 		{
   218         aTraceLayout.iTimestamp = *pData++;
   219         size -= sizeof(TUint32);
   220         test(size >= 0);
   221 		}
   222 	
   223     if(flags & (BTrace::ETimestamp2Present))
   224 		{
   225         aTraceLayout.iTimestamp2 = *pData++;
   226         size -= sizeof(TUint32);
   227         test(size >= 0);
   228 		}   
   229 	
   230 	if(flags & (BTrace::EContextIdPresent))
   231 		{
   232 		aTraceLayout.iContext = *pData++;
   233 		size -= sizeof(TUint32);
   234         test(size >= 0);
   235 		}
   236 	
   237 	if(flags & (BTrace::EPcPresent))
   238 		{
   239 		aTraceLayout.iPC = *pData++;	
   240 		size -= sizeof(TUint32);
   241         test(size >= 0);
   242 		}
   243 	
   244 	if(flags & (BTrace::EExtraPresent))
   245 		{
   246 		aTraceLayout.iExtra = *pData++;	
   247 		size -= sizeof(TUint32);
   248         test(size >= 0);
   249 		}
   250 	
   251     //-- process user data if present
   252     test(size >= 0);
   253     test(size % sizeof(TUint32) == 0);
   254 	
   255     aTraceLayout.iDataWords = size / sizeof(TUint32);
   256     aTraceLayout.ipData = (aTraceLayout.iDataWords!=0) ? pData : NULL;
   257 	
   258     return aTraceLayout.iSize;
   259 	}
   260 
   261 //---------------------------------------------------------------------------------
   262 //! @SYMTestCaseID          KBASE-T_PERFLOGGER-0055
   263 //! @SYMTestType            UT
   264 //! @SYMPREQ                PREQ1030
   265 //! @SYMTestCaseDesc        Tests logging from different contexts: user thread, ISR, Kernel thread and IDFC. 
   266 //!                         The main functionality is performed by test heller LDD, "d_perflogger_test" that acually calls the logging function from different contexts 
   267 //!                         following the commands from user application.
   268 //!
   269 //! @SYMTestActions         0   setup the data structures that specify the logging parameters.
   270 //!                         1   call RKPLoggerTestHelper::MakeLogFromUserThread() this is a synchronous operation. Performs logging from the user thread context.
   271 //!                         1.1 Parse the log record data and ensure that the logged information matches the data we passed to the helper LDD.
   272 //!
   273 //!                         2   call RKPLoggerTestHelper::MakeLogFromISR() this is asynchronous operation. Performs logging from the ISR context.
   274 //!                         2.1 Wait for operation to complete, validate the completion status.
   275 //!                         2.2 Parse the log record data and ensure that the logged information matches the data we passed to the helper LDD.
   276 //!
   277 //!
   278 //!                         3   call RKPLoggerTestHelper::MakeLogFromDFC() this is asynchronous operation. Performs logging from the Kernel thread context (DFC).
   279 //!                         3.1 Wait for operation to complete, validate the completion status.
   280 //!                         3.2 Parse the log record data and ensure that the logged information matches the data we passed to the helper LDD.
   281 //!
   282 //!                         4   call RKPLoggerTestHelper::MakeLogFromIDFC() this is asynchronous operation. Performs logging from the IDFC.
   283 //!                         4.1 Wait for operation to complete, validate the completion status.
   284 //!                         4.2 Parse the log record data and ensure that the logged information matches the data we passed to the helper LDD.
   285 //!
   286 //!                         5.  Make scattered overlapped logging from ISR, DFC & IDFC simultaneously, ensure that this work.
   287 //!
   288 //! @SYMTestExpectedResults return if the performace logger behaves as expected, panic otherwise
   289 //! @SYMTestPriority        High
   290 //! @SYMTestStatus          Implemented
   291 //---------------------------------------------------------------------------------
   292 void TestPerfLogger(RBTrace &aTrace)
   293 	{
   294     TInt    nRes;
   295     
   296     const TUint32   KLogUserData  = 0xBAAABEEF; //-- just for testing
   297     const TUint32   KLogUserData2 = 0x11FFDDCC; //-- just for testing
   298 	
   299 	
   300     test.Next(_L("testing kernel performance logger functionality\n"));
   301 	
   302     RKPLoggerTestHelper testHelperLDD;  //-- helper test driver
   303     CleanupClosePushL(testHelperLDD);
   304 	
   305     nRes = testHelperLDD.Open(TVersion(1,0,1)); //-- open test helper ldd for a logger
   306     test(nRes == KErrNone);
   307 	
   308     //---
   309     TTestLogCtrl   logCtrl_UserThread;
   310     TTestLogCtrl   logCtrl_ISR;
   311     TTestLogCtrl   logCtrl_DFC;
   312     TTestLogCtrl   logCtrl_IDFC;
   313 	
   314 	
   315     TRequestStatus rqStatLogFromISR;
   316     TRequestStatus rqStatLogFromDFC;
   317     TRequestStatus rqStatLogFromIDFC;
   318 	
   319 	
   320     //-- setup log control structures
   321     logCtrl_UserThread.iLogsNum     = 3;
   322     logCtrl_UserThread.iCategory    = BTrace::EKernPerfLog;
   323     logCtrl_UserThread.iSubCategory = KLogSubCat_UserThread;
   324     logCtrl_UserThread.iUserData    = KLogUserData;
   325     logCtrl_UserThread.iUserData2   = KLogUserData2;
   326 	
   327 	
   328     logCtrl_ISR.iLogsNum        = 3;
   329     logCtrl_ISR.iCategory       = BTrace::EKernPerfLog;
   330     logCtrl_ISR.iSubCategory    = KLogSubCat_ISR;
   331     logCtrl_ISR.iUserData       = KLogUserData;
   332     logCtrl_ISR.iUserData2      = KLogUserData2;
   333 	
   334 	
   335     logCtrl_DFC.iLogsNum        = 3;
   336     logCtrl_DFC.iCategory       = BTrace::EKernPerfLog;
   337     logCtrl_DFC.iSubCategory    = KLogSubCat_KernelThread;
   338     logCtrl_DFC.iUserData       = KLogUserData;
   339     logCtrl_DFC.iUserData2      = KLogUserData2;
   340 	
   341 	
   342     logCtrl_IDFC.iLogsNum       = 3;
   343     logCtrl_IDFC.iCategory      = BTrace::EKernPerfLog;
   344     logCtrl_IDFC.iSubCategory   = KLogSubCat_IDFC;
   345     logCtrl_IDFC.iUserData      = KLogUserData;
   346     logCtrl_IDFC.iUserData2     = KLogUserData2;
   347 	
   348 	
   349 	
   350     test.Printf(_L("Testing logging from user thread\n"));
   351     //============================================================
   352     //-- 1. make logging from user thread, this is a synchronous operation
   353     nRes = testHelperLDD.MakeLogFromUserThread(logCtrl_UserThread);
   354     test(nRes == KErrNone);
   355 	
   356     //-- 1.1 check the results
   357     GetParseRecordData(aTrace, &logCtrl_UserThread);
   358 	
   359 	
   360     test.Printf(_L("Testing logging from ISR\n"));
   361     //============================================================
   362     //-- 2. make logging from ISR, this is asynchronous operation
   363     testHelperLDD.MakeLogFromISR(rqStatLogFromISR, logCtrl_ISR);
   364     User::WaitForRequest(rqStatLogFromISR);
   365     test(rqStatLogFromISR.Int() == KErrNone);
   366 	
   367     //-- 2.1 check the results
   368     GetParseRecordData(aTrace, &logCtrl_ISR);
   369 	
   370     test.Printf(_L("Testing logging from DFC\n"));
   371     //============================================================
   372     //-- 3. make logging from DFC kennel thread, this is asynchronous operation
   373     testHelperLDD.MakeLogFromDFC(rqStatLogFromDFC, logCtrl_DFC);
   374     User::WaitForRequest(rqStatLogFromDFC);
   375     test(rqStatLogFromDFC.Int() == KErrNone);
   376 	
   377     //-- 3.1 check the results
   378     GetParseRecordData(aTrace, &logCtrl_DFC);
   379 	
   380     test.Printf(_L("Testing logging from IDFC\n"));
   381     //============================================================
   382     //-- 4. make logging from IDFC, this is asynchronous operation
   383     testHelperLDD.MakeLogFromIDFC(rqStatLogFromIDFC, logCtrl_IDFC);
   384     User::WaitForRequest(rqStatLogFromIDFC);
   385     test(rqStatLogFromIDFC.Int() == KErrNone);
   386 	
   387     //-- 4.1 check the results
   388     GetParseRecordData(aTrace, &logCtrl_IDFC);
   389 	
   390 	
   391     test.Printf(_L("Testing overlapped logging from ISR, DFC & IDFC\n"));
   392     //============================================================
   393     //-- 5. make logging from ISR, DFC and IDFC simultaneously
   394 	
   395     //-- use random numbers for number and period of loggings  
   396     logCtrl_ISR.iLogsNum        = URnd(16)+1;
   397     logCtrl_ISR.iLogPeriodTick  = URnd(20)+1;
   398 	
   399     logCtrl_DFC.iLogsNum        = URnd(16)+1;
   400     logCtrl_DFC.iLogPeriodTick  = URnd(20)+1;
   401 	
   402     logCtrl_IDFC.iLogsNum       = URnd(16)+1;
   403     logCtrl_IDFC.iLogPeriodTick = URnd(20)+1;
   404 	
   405     //-- start logging
   406     testHelperLDD.MakeLogFromISR(rqStatLogFromISR, logCtrl_ISR);
   407     testHelperLDD.MakeLogFromDFC(rqStatLogFromDFC, logCtrl_DFC);
   408     testHelperLDD.MakeLogFromIDFC(rqStatLogFromIDFC, logCtrl_IDFC);
   409 	
   410     //-- wait for logging to finish
   411     User::WaitForRequest(rqStatLogFromISR);
   412     User::WaitForRequest(rqStatLogFromDFC);
   413     User::WaitForRequest(rqStatLogFromIDFC);
   414 	
   415     GetParseRecordData(aTrace);
   416 	
   417 	
   418     CleanupStack::PopAndDestroy(1); //-- testHelperLDD
   419 	
   420 }
   421 
   422 
   423 //---------------------------------------------------------------------------------
   424 //! @SYMTestCaseID          KBASE-T_PERFLOGGER-0056
   425 //! @SYMTestType            UT
   426 //! @SYMPREQ                PREQ1030
   427 //! @SYMTestCaseDesc        Test of PERF_LOG0, PERF_LOG1, PERF_LOG macros performed by helper LDD
   428 //! @SYMTestActions         Calls helper LDD API that in turn implies using PERF_LOG0, PERF_LOG1, PERF_LOG macros by helper LDD
   429 //! @SYMTestExpectedResults return if the performace logger behaves as expected, panic otherwise
   430 //! @SYMTestPriority        High
   431 //! @SYMTestStatus          Implemented
   432 //---------------------------------------------------------------------------------
   433 void TestMacros(RBTrace &aTrace)
   434 	{
   435     TInt    nRes;
   436     
   437     const TUint32   KLogUserData  = 0xBAAABEEF; //-- just for testing
   438     const TUint32   KLogUserData2 = 0x11FFDDCC; //-- just for testing
   439 	
   440 	
   441     test.Next(_L("Unit test for different macros\n"));
   442 	
   443     RKPLoggerTestHelper testHelperLDD;  //-- helper test driver
   444     CleanupClosePushL(testHelperLDD);
   445 	
   446     nRes = testHelperLDD.Open(TVersion(1,0,1)); //-- open test helper ldd for a logger
   447     test(nRes == KErrNone);
   448 	
   449     //---
   450     TTestLogCtrl   logCtrl;
   451 	
   452     //-- setup log control structures
   453     logCtrl.iLogsNum     = 1;
   454     logCtrl.iCategory    = BTrace::EKernPerfLog;
   455     logCtrl.iSubCategory = KLogSubCat_UserThread;
   456     logCtrl.iUserData    = KLogUserData;
   457     logCtrl.iUserData2   = KLogUserData2;
   458 	
   459     //-- make logging from user thread using different macros, PERF_LOG0, PERF_LOG1, PERF_LOG 
   460     //-- see the helper driver
   461     nRes = testHelperLDD.TestDifferentMacros(logCtrl);
   462     test(nRes == KErrNone);
   463 	
   464     //-- print out the results
   465     GetParseRecordData(aTrace);
   466 	
   467 	
   468     CleanupStack::PopAndDestroy(1); //-- testHelperLDD
   469 	
   470 	}
   471 
   472 //---------------------------------------------------------------------------------
   473 void MainL(void)
   474 	{
   475     test.Start(_L("Kern Perf Logger tests"));
   476     Initialise();
   477 	
   478 	
   479     RBTrace trace;
   480 	TInt error = trace.Open();
   481     test(error == KErrNone);
   482 	
   483 	trace.Empty();
   484 	trace.SetFilter(BTrace::EThreadIdentification,0);
   485 	
   486     
   487     
   488     //-- actually, for hardware platforms, the testing category and trace enabling 
   489     //-- may be set up in appropriate "header.iby" file
   490     trace.SetMode(RBTrace::EEnable);
   491     trace.SetFilter(BTrace::EKernPerfLog, ETrue);
   492     
   493     //-- unit-test for PERF_LOG macros
   494     TestMacros(trace);
   495 	
   496     //-- functionality test
   497     TestPerfLogger(trace); 
   498 	
   499     trace.Close();
   500 	
   501     Finalise();
   502 	test.End();
   503 	}
   504 
   505 
   506 //---------------------------------------------------------------------------------
   507 //! @SYMTestCaseID          KBASE-T_PERFLOGGER-0162
   508 //! @SYMTestType            UT
   509 //! @SYMPREQ                PREQ1030
   510 //! @SYMTestCaseDesc        Load test helper LDD and check the result
   511 //! @SYMTestActions         load specified LDD by calling User::LoadLogicalDevice()
   512 //! @SYMTestExpectedResults return if helper LDD is loaded OK, panic otherwise
   513 //! @SYMTestPriority        High
   514 //! @SYMTestStatus          Implemented
   515 //---------------------------------------------------------------------------------
   516 void Initialise()
   517 	{
   518     rndSeed = Math::Random();
   519     
   520     //-- load device drivers 
   521     TInt nRes;
   522 	
   523     test.Printf(_L("Loading test helper LDD...\n"));
   524     nRes = User::LoadLogicalDevice(KPLoggerHelperTestDrv);
   525     test(nRes == KErrNone || nRes == KErrAlreadyExists);
   526 	}
   527 
   528 /** Finalise environment */
   529 void Finalise(void)
   530 	{
   531 	}
   532 
   533 
   534 
   535 /**
   536     Main 	
   537 */
   538 GLDEF_C TInt E32Main() 
   539 	{
   540 	CTrapCleanup* cleanup=CTrapCleanup::New() ; // get clean-up stack
   541     
   542 	TRAPD(r,MainL());
   543 	
   544     delete cleanup ; // destroy clean-up stack
   545 	
   546     return r;
   547 	
   548 	}
   549 
   550 //-------------------------------------------------------------------------------------
   551 
   552 TUint URnd(TUint aMin, TUint aMax)
   553 	{
   554     test(aMin < aMax);
   555     TUint uRes;
   556 	
   557     do
   558 		{
   559         uRes = Math::Rand(rndSeed) % aMax;
   560 		}while(uRes < aMin);
   561 		
   562 		return uRes;
   563 	}
   564 
   565 TUint URnd(TUint aMax)
   566 	{
   567     return Math::Rand(rndSeed) % aMax;
   568 	}
   569 
   570 
   571 
   572 
   573 
   574 
   575 
   576 
   577 
   578 
   579