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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Kernel Performance Logger test
15 // Uses helper LDD for performing actual logging from the kernel side.
26 #include <e32std_private.h>
32 #include "t_perflogger.h"
33 #include "t_perflogger_drv.h"
36 //-------------------------------------------------------------------------------------
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;
45 //-------------------------------------------------------------------------------------
47 RTest test(_L("T_PerfLogger"));
50 //-------------------------------------------------------------------------------------
53 Print out the logging record.
54 @param aTraceLayout unrolled trace record structure
56 void PrintTraceRecord(const TTraceLayout& aTraceLayout)
60 printBuf.Format(_L("Record: Size:%d, Flags:0x%02x, Cat:%d, SubCat:%d "), aTraceLayout.iSize, aTraceLayout.iFlags, aTraceLayout.iCategory, aTraceLayout.iSubCategory);
62 TUint flags = aTraceLayout.iFlags;
64 if(flags&(BTrace::EHeader2Present))
65 printBuf.AppendFormat(_L("Header2:0x%08x "), aTraceLayout.iHeader2);
67 if(flags & (BTrace::ETimestampPresent))
68 printBuf.AppendFormat(_L("Timestamp:0x%x "), aTraceLayout.iTimestamp);
70 if(flags & (BTrace::ETimestamp2Present))
71 printBuf.AppendFormat(_L("Timestamp2:0x%x "), aTraceLayout.iTimestamp2);
73 if(flags & (BTrace::EContextIdPresent))
74 printBuf.AppendFormat(_L("Context:0x%08x "), aTraceLayout.iContext);
76 if(flags & (BTrace::EPcPresent))
77 printBuf.AppendFormat(_L("PC: 0x%08x "), aTraceLayout.iPC);
79 if(flags & (BTrace::EExtraPresent))
80 printBuf.AppendFormat(_L("Extra: 0x%08x "), aTraceLayout.iExtra);
82 printBuf.Append(_L("| "));
83 for(TInt i=0; i< aTraceLayout.iDataWords; ++i)
85 printBuf.AppendFormat(_L(" 0x%08x"), aTraceLayout.ipData[i]);
88 printBuf.Append(_L("\n"));
89 test.Printf(printBuf);
93 //-------------------------------------------------------------------------------------
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.
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.
104 void GetParseRecordData(RBTrace& aTrace, const TTestLogCtrl* apControlStruct = NULL)
107 TTraceLayout traceLayout;
111 //-- get raw trace record
112 TInt dataSize = aTrace.GetData(record);
114 if(i != 0 && !dataSize)
115 break; //-- no more data
117 //-- check if we get log data at all at the very beginning
118 if(i == 0 && !dataSize)
121 {//-- it's ok, no check
125 {//-- panic if there is no log data, but we are required to get some.
126 if(apControlStruct->iLogsNum > 0)
128 test.Printf(_L("GetParseRecordData() No trace data found!\n"));
135 TUint8* end = record+dataSize;
136 TUint8* currPos = record;
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)
144 nBytes = ParseTraceRecord(currPos ,traceLayout);
147 //-- skip possible loggings that we didn't make
148 if(traceLayout.iCategory != BTrace::EKernPerfLog)
153 //-- print the record out
154 PrintTraceRecord(traceLayout);
156 //-- check the obtained record structure
159 test(traceLayout.iCategory == apControlStruct->iCategory);
160 test(traceLayout.iSubCategory == apControlStruct->iSubCategory);
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);
165 if(traceLayout.iDataWords > 2) //-- we have 2 words of user data (1 is for TickCount)
166 test(traceLayout.ipData[1] == apControlStruct->iUserData2);
172 //-- check number of trace records obtained
175 test(nRecords == apControlStruct->iLogsNum);
178 //-- release data buffer.
184 //---------------------------------------------------------------------------------
187 Parse logging record, converting it from the raw representation to the unrolled data
190 @param apRecord points to the buffer with the raw trace record
191 @param aTraceLayout here parsed record will bre returned
193 @return sise of the record, bytes
195 TUint ParseTraceRecord(const TUint8* apRecord, TTraceLayout& aTraceLayout)
197 aTraceLayout.iSize = apRecord[BTrace::ESizeIndex];
198 aTraceLayout.iFlags = apRecord[BTrace::EFlagsIndex];
199 aTraceLayout.iCategory = apRecord[BTrace::ECategoryIndex];
200 aTraceLayout.iSubCategory = apRecord[BTrace::ESubCategoryIndex];
202 const TUint flags= aTraceLayout.iFlags;
203 TInt size = aTraceLayout.iSize;
204 const TUint32* pData = (const TUint32*)(apRecord+4);
206 size -= 4; //-- count header
208 //-- process header flags and appropriate fields of the record
209 if(flags&(BTrace::EHeader2Present))
211 aTraceLayout.iHeader2 = *pData++;
212 size -= sizeof(TUint32);
216 if(flags & (BTrace::ETimestampPresent))
218 aTraceLayout.iTimestamp = *pData++;
219 size -= sizeof(TUint32);
223 if(flags & (BTrace::ETimestamp2Present))
225 aTraceLayout.iTimestamp2 = *pData++;
226 size -= sizeof(TUint32);
230 if(flags & (BTrace::EContextIdPresent))
232 aTraceLayout.iContext = *pData++;
233 size -= sizeof(TUint32);
237 if(flags & (BTrace::EPcPresent))
239 aTraceLayout.iPC = *pData++;
240 size -= sizeof(TUint32);
244 if(flags & (BTrace::EExtraPresent))
246 aTraceLayout.iExtra = *pData++;
247 size -= sizeof(TUint32);
251 //-- process user data if present
253 test(size % sizeof(TUint32) == 0);
255 aTraceLayout.iDataWords = size / sizeof(TUint32);
256 aTraceLayout.ipData = (aTraceLayout.iDataWords!=0) ? pData : NULL;
258 return aTraceLayout.iSize;
261 //---------------------------------------------------------------------------------
262 //! @SYMTestCaseID KBASE-T_PERFLOGGER-0055
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.
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.
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.
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.
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.
286 //! 5. Make scattered overlapped logging from ISR, DFC & IDFC simultaneously, ensure that this work.
288 //! @SYMTestExpectedResults return if the performace logger behaves as expected, panic otherwise
289 //! @SYMTestPriority High
290 //! @SYMTestStatus Implemented
291 //---------------------------------------------------------------------------------
292 void TestPerfLogger(RBTrace &aTrace)
296 const TUint32 KLogUserData = 0xBAAABEEF; //-- just for testing
297 const TUint32 KLogUserData2 = 0x11FFDDCC; //-- just for testing
300 test.Next(_L("testing kernel performance logger functionality\n"));
302 RKPLoggerTestHelper testHelperLDD; //-- helper test driver
303 CleanupClosePushL(testHelperLDD);
305 nRes = testHelperLDD.Open(TVersion(1,0,1)); //-- open test helper ldd for a logger
306 test(nRes == KErrNone);
309 TTestLogCtrl logCtrl_UserThread;
310 TTestLogCtrl logCtrl_ISR;
311 TTestLogCtrl logCtrl_DFC;
312 TTestLogCtrl logCtrl_IDFC;
315 TRequestStatus rqStatLogFromISR;
316 TRequestStatus rqStatLogFromDFC;
317 TRequestStatus rqStatLogFromIDFC;
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;
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;
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;
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;
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);
356 //-- 1.1 check the results
357 GetParseRecordData(aTrace, &logCtrl_UserThread);
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);
367 //-- 2.1 check the results
368 GetParseRecordData(aTrace, &logCtrl_ISR);
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);
377 //-- 3.1 check the results
378 GetParseRecordData(aTrace, &logCtrl_DFC);
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);
387 //-- 4.1 check the results
388 GetParseRecordData(aTrace, &logCtrl_IDFC);
391 test.Printf(_L("Testing overlapped logging from ISR, DFC & IDFC\n"));
392 //============================================================
393 //-- 5. make logging from ISR, DFC and IDFC simultaneously
395 //-- use random numbers for number and period of loggings
396 logCtrl_ISR.iLogsNum = URnd(16)+1;
397 logCtrl_ISR.iLogPeriodTick = URnd(20)+1;
399 logCtrl_DFC.iLogsNum = URnd(16)+1;
400 logCtrl_DFC.iLogPeriodTick = URnd(20)+1;
402 logCtrl_IDFC.iLogsNum = URnd(16)+1;
403 logCtrl_IDFC.iLogPeriodTick = URnd(20)+1;
406 testHelperLDD.MakeLogFromISR(rqStatLogFromISR, logCtrl_ISR);
407 testHelperLDD.MakeLogFromDFC(rqStatLogFromDFC, logCtrl_DFC);
408 testHelperLDD.MakeLogFromIDFC(rqStatLogFromIDFC, logCtrl_IDFC);
410 //-- wait for logging to finish
411 User::WaitForRequest(rqStatLogFromISR);
412 User::WaitForRequest(rqStatLogFromDFC);
413 User::WaitForRequest(rqStatLogFromIDFC);
415 GetParseRecordData(aTrace);
418 CleanupStack::PopAndDestroy(1); //-- testHelperLDD
423 //---------------------------------------------------------------------------------
424 //! @SYMTestCaseID KBASE-T_PERFLOGGER-0056
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)
437 const TUint32 KLogUserData = 0xBAAABEEF; //-- just for testing
438 const TUint32 KLogUserData2 = 0x11FFDDCC; //-- just for testing
441 test.Next(_L("Unit test for different macros\n"));
443 RKPLoggerTestHelper testHelperLDD; //-- helper test driver
444 CleanupClosePushL(testHelperLDD);
446 nRes = testHelperLDD.Open(TVersion(1,0,1)); //-- open test helper ldd for a logger
447 test(nRes == KErrNone);
450 TTestLogCtrl logCtrl;
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;
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);
464 //-- print out the results
465 GetParseRecordData(aTrace);
468 CleanupStack::PopAndDestroy(1); //-- testHelperLDD
472 //---------------------------------------------------------------------------------
475 test.Start(_L("Kern Perf Logger tests"));
480 TInt error = trace.Open();
481 test(error == KErrNone);
484 trace.SetFilter(BTrace::EThreadIdentification,0);
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);
493 //-- unit-test for PERF_LOG macros
496 //-- functionality test
497 TestPerfLogger(trace);
506 //---------------------------------------------------------------------------------
507 //! @SYMTestCaseID KBASE-T_PERFLOGGER-0162
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 //---------------------------------------------------------------------------------
518 rndSeed = Math::Random();
520 //-- load device drivers
523 test.Printf(_L("Loading test helper LDD...\n"));
524 nRes = User::LoadLogicalDevice(KPLoggerHelperTestDrv);
525 test(nRes == KErrNone || nRes == KErrAlreadyExists);
528 /** Finalise environment */
538 GLDEF_C TInt E32Main()
540 CTrapCleanup* cleanup=CTrapCleanup::New() ; // get clean-up stack
544 delete cleanup ; // destroy clean-up stack
550 //-------------------------------------------------------------------------------------
552 TUint URnd(TUint aMin, TUint aMax)
559 uRes = Math::Rand(rndSeed) % aMax;
565 TUint URnd(TUint aMax)
567 return Math::Rand(rndSeed) % aMax;