diff -r 000000000000 -r a41df078684a kerneltest/e32test/debug/t_btrace.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/debug/t_btrace.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,3425 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\debug\t_btrace.cpp +// Overview: +// Tests generation of traces using the BTrace APIs +// and captuirng of these by BTRACE.LDD and BTRACEC.DLL. +// API Information: +// class BTrace +// class RBTrace +// BTrace0 +// BTrace4 +// BTrace8 +// BTrace12 +// BTraceN +// BTraceBig +// BTracePc0 +// BTracePc4 +// BTracePc8 +// BTracePc12 +// BTracePcN +// BTracePcBig +// BTraceContext0 +// BTraceContext4 +// BTraceContext8 +// BTraceContext12 +// BTraceContextN +// BTraceContextBig +// BTraceContextPc0 +// BTraceContextPc4 +// BTraceContextPc8 +// BTraceContextPc12 +// BTraceContextPcN +// BTraceContextPcBig +// +// + +#define __E32TEST_EXTENSION__ +#include +#include +#include +#include + +#include "../../../kernel/eka/include/d32btrace.h" +#include "../../../kernel/eka/include/e32btrace.h" +#include "d_btrace.h" + +#define __TRACE_LINE__() test.Printf(_L("%d\n"),__LINE__) + +RTest test(_L("T_BTRACE")); + +TUint BaseSize; // Size of a standard test trace with no data + +RBTrace Trace; +RBTraceTest TraceTest; + +TInt ContextOffset(const TUint8* aData) + { + TInt size = 4; // header size + if(aData[BTrace::EFlagsIndex]&BTrace::EHeader2Present) + size += 4; + if(aData[BTrace::EFlagsIndex]&BTrace::ETimestampPresent) + size += 4; + if(aData[BTrace::EFlagsIndex]&BTrace::ETimestamp2Present) + size += 4; + return size; + } + + +TInt ExtraSize(const TUint8* aData) + { + TInt size = ContextOffset(aData); + if(aData[BTrace::EFlagsIndex]&BTrace::EContextIdPresent) + size += 4; + if(aData[BTrace::EFlagsIndex]&BTrace::EPcPresent) + size += 4; + if(aData[BTrace::EFlagsIndex]&BTrace::EExtraPresent) + size += 4; + return size; + } + + +TUint32* Body(const TUint8* aData) + { + return (TUint32*)(aData+ExtraSize(aData)); + } + + +TPtrC8 Text(const TUint8* aData) + { + TInt size = aData[BTrace::ESizeIndex]; + TInt extra = ExtraSize(aData); + extra += 8; // skip past first 2 32bit args + size -= extra; + return TPtrC8(aData+extra,size); + } + + +const TUint KTest1SubCategory = 0x81; +const TUint KTest2SubCategory = 0xc3; + +TUint8 KTestTrace1[KMaxBTraceRecordSize*2] = { BTrace::ETest1, KTest1SubCategory }; +TUint8 KTestTrace2[KMaxBTraceRecordSize*2] = { BTrace::ETest2, KTest2SubCategory }; +TUint32 BigFilter2[KNumBTraceFilterTestUids]; + +void Trace1(TInt aSize, TInt aDelay=0) + { + test_KErrNone(TraceTest.Trace(0,KTestTrace1,aSize,aDelay)); + } + +void Trace2(TInt aSize, TInt aDelay=0) + { + test_KErrNone(TraceTest.Trace(0,KTestTrace2,aSize,aDelay)); + } + +TBool CheckTrace1(TUint8* aData, TInt aSize, TInt aSubCategory=KTest1SubCategory) + { + if(((aData[BTrace::ESizeIndex]+3)&~3)!=aSize) + return EFalse; + if(aData[BTrace::ECategoryIndex]!=BTrace::ETest1) + return EFalse; + if(aData[BTrace::ESubCategoryIndex]!=aSubCategory) + return EFalse; + TInt extra = ExtraSize(aData); + aSize = aData[BTrace::ESizeIndex]-extra; + aData += extra; + while(--aSize>=0) + { + if(((TUint8*)KTestTrace1)[4+aSize]!=aData[aSize]) + return EFalse; + } + return ETrue; + } + +TBool CheckTrace2(TUint8* aData, TInt aSize, TInt aSubCategory=KTest2SubCategory) + { + if(((aData[BTrace::ESizeIndex]+3)&~3)!=aSize) + return EFalse; + if(aData[BTrace::ECategoryIndex]!=BTrace::ETest2) + return EFalse; + if(aData[BTrace::ESubCategoryIndex]!=aSubCategory) + return EFalse; + TInt extra = ExtraSize(aData); + aSize = aData[BTrace::ESizeIndex]-extra; + aData += extra; + while(--aSize>=0) + { + if(((TUint8*)KTestTrace2)[4+aSize]!=aData[aSize]) + return EFalse; + } + return ETrue; + } + + +TBool CheckSize(const TUint8* aData, TInt aSize, TInt aExpected) + { + TInt extra = ExtraSize(aData); + if(aSize==((extra+aExpected+3)&~3)) + return 1; + else + { + TInt actual_size = aData[0]; + if (aSize > actual_size) + actual_size = aSize; + test.Printf(_L("Trace data:\n")); + TInt i; + for (i=0; iend) + test(BadTrace(aData)); + TUint subCategory = aData[BTrace::ESubCategoryIndex]; + if(aData[BTrace::EFlagsIndex]&(BTrace::EMissingRecord)) + { + Trace1Sequence = -1; + Trace2Sequence = -1; + } + if(aData[BTrace::ECategoryIndex]==BTrace::ETest1) + { + if(subCategory!=(TUint)Trace1Sequence && Trace1Sequence!=-1) + { + test.Printf(_L("Sequence wrong %02x!=%02x\n"),subCategory,Trace1Sequence); + test(BadTrace(aData)); + } + if(!CheckTrace1(aData,size,subCategory)) + test(BadTrace(aData)); + Trace1Sequence = subCategory+1; + Trace1Sequence &= 0xff; + } + else + { + if(aData[BTrace::ECategoryIndex]!=BTrace::ETest2) + test(BadTrace(aData)); + if(subCategory!=(TUint)Trace2Sequence && Trace2Sequence!=-1) + { + test.Printf(_L("Sequence wrong %02x!=%02x\n"),subCategory,Trace2Sequence); + test(BadTrace(aData)); + } + if(!CheckTrace2(aData,size,subCategory)) + test(BadTrace(aData)); + Trace2Sequence = subCategory+1; + Trace2Sequence &= 0xff; + } + aData = BTrace::NextRecord(aData); + } + } + + +void DumpTrace() + { + TBuf8<(80+KMaxBTraceDataArray*9/4)*2> buf; + for(;;) + { + TUint8* record; + TInt dataSize = Trace.GetData(record); + if(!dataSize) + break; + TUint8* end = record+dataSize; + while(record0) ? *(TUint32*)(data) : 0; + TUint32 data1 = (size>4) ? *(TUint32*)(data+4) : 0; + TUint32 data2 = (size>8) ? *(TUint32*)(data+8) : 0; + TPtrC8 des(0,0); + if(size>=8) + des.Set(data+8,size-8); + switch(category) + { + case BTrace::EKernPrintf: + case BTrace::ERDebugPrintf: + case BTrace::EPlatsecPrintf: + { + if(category==BTrace::EKernPrintf) + buf.Append(_L8("Kern::Printf ")); + else if(category==BTrace::ERDebugPrintf) + buf.Append(_L8("RDebug::Printf ")); + else + buf.Append(_L8("PlatSecPrintf ")); + switch(header2&BTrace::EMultipartFlagMask) + { + case BTrace::EMultipartFirst: + buf.AppendFormat(_L8("seq:%d size:%d thread-id:%d \"%S\""),extra,data0,data1,&des); + break; + case BTrace::EMultipartMiddle: + case BTrace::EMultipartLast: + buf.AppendFormat(_L8("seq:%d size:%d offset:%d \"%S\""),extra,data0,data1,&des); + break; + default: + des.Set(data+4,size-4); + buf.AppendFormat(_L8("thread-id:%d \"%S\""),data0,&des); + break; + } + } + break; + + case BTrace::EThreadIdentification: + { + switch(subCategory) + { + case BTrace::ENanoThreadCreate: + buf.AppendFormat(_L8("NanoThreadCreate thrd:%08x"),data0); + break; + case BTrace::ENanoThreadDestroy: + buf.AppendFormat(_L8("NanoThreadDestroy thrd:%08x"),data0); + break; + case BTrace::EThreadCreate: + buf.AppendFormat(_L8("ThreadCreate thrd:%08x proc:%08x name:%S"),data0,data1,&des); + break; + case BTrace::EThreadDestroy: + buf.AppendFormat(_L8("ThreadDestroy thrd:%08x proc:%08x id:%d"),data0,data1,data2); + break; + case BTrace::EThreadName: + buf.AppendFormat(_L8("ThreadName thrd:%08x proc:%08x name:%S"),data0,data1,&des); + break; + case BTrace::EThreadId: + buf.AppendFormat(_L8("ThreadId thrd:%08x proc:%08x id:%d"),data0,data1,data2); + break; + case BTrace::EProcessName: + buf.AppendFormat(_L8("ProcessName thrd:%08x proc:%08x name:%S"),data0,data1,&des); + break; + } + } + break; + + case BTrace::ECpuUsage: + { + switch(subCategory) + { + case BTrace::EIrqStart: + buf.AppendFormat(_L8("IrqStart")); + break; + case BTrace::EIrqEnd: + buf.AppendFormat(_L8("IrqEnd")); + break; + case BTrace::EFiqStart: + buf.AppendFormat(_L8("FiqStart")); + break; + case BTrace::EFiqEnd: + buf.AppendFormat(_L8("FiqEnd")); + break; + case BTrace::EIDFCStart: + buf.AppendFormat(_L8("IDFCStart")); + break; + case BTrace::EIDFCEnd: + buf.AppendFormat(_L8("IDFCEnd")); + break; + case BTrace::ENewThreadContext: + buf.AppendFormat(_L8("NewThreadContext")); + break; + } + break; + } + + case BTrace::EClientServer: + { + switch(subCategory) + { + case BTrace::EServerCreate: + buf.AppendFormat(_L8("EServerCreate serv:%08x name:%S"),data0,&des); + break; + case BTrace::EServerDestroy: + buf.AppendFormat(_L8("EServerDestroy serv:%08x"),data0); + break; + case BTrace::ESessionAttach: + buf.AppendFormat(_L8("ESessionAttach sess:%08x serv:%08x"),data0,data1); + break; + case BTrace::ESessionDetach: + buf.AppendFormat(_L8("ESessionDetach sess:%08x"),data0); + break; + case BTrace::EMessageSend: + buf.AppendFormat(_L8("EMessageSend mess:%08x func:%08x sess:%08x"),data0,data1,data2); + break; + case BTrace::EMessageReceive: + buf.AppendFormat(_L8("EMessageReceive mess:%08x"),data0); + break; + case BTrace::EMessageComplete: + buf.AppendFormat(_L8("EMessageComplete mess:%08x reas:%08x"),data0,data1); + break; + } + break; + } + + case BTrace::ERequests: + { + switch(subCategory) + { + case BTrace::ERequestComplete: + buf.AppendFormat(_L8("ERequestComplete thrd:%08x stat:%08x resn:%08x"),data0,data1,data2); + break; + } + break; + } + + default: + { + buf.AppendFormat(_L8("size:%d flags:%02x cat:%d,%d data: "),size,flags,category,subCategory); + for(TUint i=0; in ... + Trace.RequestData(s1,BaseSize+8); + test_Equal(KRequestPending,s1.Int()); + timer.After(s2,5*1000000); + Trace1(20); + User::WaitForRequest(s1,s2); + test_KErrNone(s1.Int()); + timer.Cancel(); + User::WaitForRequest(s2); + + size = Trace.GetData(data); + test_Compare(size, >= , BaseSize+8); + Trace.DataUsed(); + size = Trace.GetData(data); + test_Equal(0,size); + + // delayed notification... + Trace.RequestData(s1,0); + timer.After(s2,5*1000000); + Trace1(4,500000); + test_Equal(KRequestPending,s1.Int()); + User::WaitForRequest(s1,s2); + test_KErrNone(s1.Int()); + timer.Cancel(); + User::WaitForRequest(s2); + size = Trace.GetData(data); + test(CheckSize(data,size,4)); + Trace.DataUsed(); + + // delayed notification with size>n... + Trace.RequestData(s1,BaseSize+8); + Trace1(4,500000); + test_Equal(KRequestPending,s1.Int()); + timer.After(s2,1000000); + User::WaitForRequest(s1,s2); + test_KErrNone(s2.Int()); + timer.After(s2,5*1000000); + Trace1(20,500000); + test_Equal(KRequestPending,s1.Int()); + User::WaitForRequest(s1,s2); + test_KErrNone(s1.Int()); + timer.Cancel(); + User::WaitForRequest(s2); + + size = Trace.GetData(data); + test_Compare(size, >=, BaseSize+8); + Trace.DataUsed(); + size = Trace.GetData(data); + test_Equal(0,size); + + test.Next(_L("Test RequestData() when data is already available")); + Trace1(4); + Trace.RequestData(s1,0); + test_KErrNone(s1.Int()); + User::WaitForRequest(s1); + size = Trace.GetData(data); + test(CheckSize(data,size,4)); + Trace.DataUsed(); + size = Trace.GetData(data); + test_Equal(0,size); + + Trace1(4); + Trace.RequestData(s1,1); + test_KErrNone(s1.Int()); + User::WaitForRequest(s1); + size = Trace.GetData(data); + test(CheckSize(data,size,4)); + Trace.DataUsed(); + size = Trace.GetData(data); + test_Equal(0,size); + + test.Next(_L("Test RequestData() for ISR disabled traces")); + Trace.RequestData(s1,0); + test_Equal(KRequestPending,s1.Int()); + timer.After(s2,5*1000000); + TraceTest.Trace(RBTraceTest::EContextIntsOff,KTestTrace1,4); + User::WaitForRequest(s1,s2); + test_KErrNone(s1.Int()); + timer.Cancel(); + User::WaitForRequest(s2); + size = Trace.GetData(data); + test(CheckSize(data,size,4)); + Trace.DataUsed(); + size = Trace.GetData(data); + test_Equal(0,size); + + test.Next(_L("Test CancelRequestData()")); + Trace.RequestData(s1,0); + test_Equal(KRequestPending,s1.Int()); + Trace.CancelRequestData(); + User::WaitForRequest(s1); + test_Equal(KErrCancel,s1.Int()); + + test.Next(_L("Test trace data contents")); + Trace1(0); + size = Trace.GetData(data); + test(CheckSize(data,size,0)); + test(CheckTrace1(data,size)); + if(data[BTrace::EFlagsIndex]&BTrace::ETimestampPresent) + test.Printf(_L("Timestamps are present\n")); + else + test.Printf(_L("Timestamps are NOT present\n")); + Trace.DataUsed(); + + Trace1(4); + size = Trace.GetData(data); + test(CheckSize(data,size,4)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + + TInt i; + for(i=0; i<=8+(TInt)KMaxBTraceDataArray; i++) + { + Trace1(i); + size = Trace.GetData(data); + test(CheckSize(data,size,i)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + } + Trace1(i); + size = Trace.GetData(data); + test(data[BTrace::EFlagsIndex]&BTrace::ERecordTruncated); + test(CheckSize(data,size,i-1)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + + test.Next(_L("Test BufferSize() and ResizeBuffer()")); + TInt oldSize = Trace.BufferSize(); + Trace1(50); + size = Trace.GetData(data); + test(CheckSize(data,size,50)); + r = Trace.ResizeBuffer(oldSize+0x1000); + test_KErrNone(r); + size = Trace.BufferSize(); + test_Equal(oldSize+0x1000,size); + Trace.SetMode(aMode); + size = Trace.GetData(data); + test_Equal(0,size); + Trace1(40); + size = Trace.GetData(data); + test(CheckSize(data,size,40)); + Trace.DataUsed(); + r = Trace.ResizeBuffer(oldSize); + test_KErrNone(r); + size = Trace.BufferSize(); + test_Equal(oldSize,size); + + test.End(); + } + + + + +//--------------------------------------------- +//! @SYMTestCaseID KBASE-T_BTRACE-0060 +//! @SYMTestType UT +//! @SYMPREQ PREQ1030 +//! @SYMTestCaseDesc Test traces generated from user code. +//! @SYMTestActions Generate traces using BTrace0, BTrace4, BTrace8, BTrace12, +//! and BTraceN macros. +//! @SYMTestExpectedResults All trace contents captured by RBTrace match those specified +//! at point of trace generation. +//! @SYMTestPriority High +//! @SYMTestStatus Implemented +//--------------------------------------------- +void TestUserTrace(TUint aMode) + { + aMode |= RBTrace::EEnable; + + TUint8* data; + TInt size; + + test.Start(_L("Reset trace buffer")); + Trace.SetMode(0); + Trace.Empty(); + Trace.SetMode(RBTrace::EEnable); + Trace.SetFilter(BTrace::ETest1,1); + Trace.SetFilter(BTrace::ETest2,0); + + test.Next(_L("BTrace0")); + BTrace0(BTrace::ETest1,KTest1SubCategory); + size = Trace.GetData(data); + test(CheckSize(data,size,0)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + + test.Next(_L("BTrace4")); + BTrace4(BTrace::ETest1,KTest1SubCategory,*(TUint32*)(KTestTrace1+4)); + size = Trace.GetData(data); + test(CheckSize(data,size,4)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + + test.Next(_L("BTrace8")); + BTrace8(BTrace::ETest1,KTest1SubCategory,*(TUint32*)(KTestTrace1+4),*(TUint32*)(KTestTrace1+8)); + size = Trace.GetData(data); + test(CheckSize(data,size,8)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + + test.Next(_L("BTrace12")); + BTrace12(BTrace::ETest1,KTest1SubCategory,*(TUint32*)(KTestTrace1+4),*(TUint32*)(KTestTrace1+8),*(TUint32*)(KTestTrace1+12)); + size = Trace.GetData(data); + test(CheckSize(data,size,12)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + + test.Next(_L("BTraceN")); + TInt i; + for(i=8; i<=8+(TInt)KMaxBTraceDataArray; i++) + { + BTraceN(BTrace::ETest1,KTest1SubCategory,*(TUint32*)(KTestTrace1+4),*(TUint32*)(KTestTrace1+8),KTestTrace1+12,i-8); + size = Trace.GetData(data); + test(CheckSize(data,size,i)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + } + BTraceN(BTrace::ETest1,KTest1SubCategory,*(TUint32*)(KTestTrace1+4),*(TUint32*)(KTestTrace1+8),KTestTrace1+12,i-8); + size = Trace.GetData(data); + test(data[BTrace::EFlagsIndex]&BTrace::ERecordTruncated); + test(CheckSize(data,size,i-1)); + test(CheckTrace1(data,size)); + Trace.DataUsed(); + + test.End(); + } + + +TBool CompareFilter2(const TUint32* aUids, TInt aNumUids, TInt aGlobalFilter) + { + TUint32* filter2Buffer = (TUint32*)-1; // initialise to invalid value + TInt filter2Global = 0x80000000; // initialise to invalid value + TInt filter2Size = Trace.Filter2(filter2Buffer,filter2Global); + + TBool pass = ETrue; + if(filter2Size!=aNumUids) + pass = EFalse; + else if(filter2Global!=aGlobalFilter) + pass = EFalse; + else if(0!=Mem::Compare((TUint8*)filter2Buffer,filter2Size,(TUint8*)aUids,aNumUids)) + pass = EFalse; + + delete filter2Buffer; + return pass; + } + + +void TestFilter2() + { + test.Start(_L("Get filter2")); + TUint32* filter2Buffer = (TUint32*)-1; // initialise to invalid value + TInt filter2Global = 0x80000000; // initialise to invalid value + TInt filter2Size = Trace.Filter2(filter2Buffer,filter2Global); + test_NotNegative(filter2Size); + test_Compare(filter2Buffer, != , (TUint32*)-1); + test_Compare(filter2Global, != , -1); + test(CompareFilter2(filter2Buffer,filter2Size,filter2Global)); + Trace.SetFilter(BTrace::ETest1,1); + TInt r; + + test.Next(_L("Clear filter2")); + r = Trace.SetFilter2((TUint32*)0,0); + test_KErrNone(r); + Trace.SetFilter2(0); + test(CompareFilter2(0,0,0)); + +#ifdef _DEBUG + test.Next(_L("Check SetFilter2's 'New' fails gracefully")); + __KHEAP_FAILNEXT(1); + + r = Trace.SetFilter2(KBTraceFilterTestUid1,1); + test_Equal(KErrNoMemory, r); + + __KHEAP_RESET; +#endif + + test.Next(_L("Test set and clear single uid")); + r = Trace.SetFilter2(KBTraceFilterTestUid1,0); + test_KErrNone(r); + test(CompareFilter2(0,0,0)); + r = Trace.SetFilter2(KBTraceFilterTestUid1,1); + test_KErrNone(r); + test(CompareFilter2(&KBTraceFilterTestUid1,1,-1)); + r = Trace.SetFilter2(KBTraceFilterTestUid1,0); + test_Equal(1,r); + test(CompareFilter2(0,0,0)); + + test.Next(_L("Test set multiple uid API")); + r = Trace.SetFilter2(&KBTraceFilterTestUid1,1); + test_KErrNone(r); + test(CompareFilter2(&KBTraceFilterTestUid1,1,-1)); + r = Trace.SetFilter2(KBTraceFilterTestUid1,0); + test_Equal(1,r); + test(CompareFilter2(0,0,0)); + + test.Next(_L("Test set and clear uids with lots of permutations")); + TInt itterations = 0; + const TInt maxUids = 5; + TInt permute[maxUids] = {0}; + TInt numUids; + RArray sortedArray(maxUids); + RArray array(maxUids); + for(numUids=1; numUids<=maxUids; ++numUids) + { + TInt p=0; + do + { + ++itterations; + if(itterations==-1) + __BREAKPOINT(); // debuging breakpoint for a specific itteration + + // make arrays of uids + sortedArray.Reset(); + array.Reset(); + TInt i; + for(i=0; i=0) + { + test(BTrace::CheckFilter2(BTrace::ETest1,removedUid)); + sortedArray.Remove(r); + removed = ETrue; + } + r = Trace.SetFilter2(removedUid,0); + test_NotNegative(r); + if(removed) + { + test(!BTrace::CheckFilter2(BTrace::ETest1,removedUid)); + } + r = sortedArray.Count(); + if(r) + test(CompareFilter2(&sortedArray[0],r,-1)); + else + { + test(CompareFilter2(0,0,0)); + break; + } + } + + // make next permutation + p=0; + while(paOutSize) + return EFalse; + + while(--size>=0) + if(*data++!=*out++) + return EFalse; + aData = data; + + return ETrue; + } + + + +TBool CheckBigTrace1(TUint8* aData, TInt aSize, TInt aOutSize, TInt aSubCategory=KTest1SubCategory, TUint32 aExtraIds = 0) + { + if(aOutSize<=(TInt)KMaxBTraceDataArray+8) + { + if(!CheckSize(aData,aSize,aOutSize)) + return EFalse; + if(!CheckTrace1(aData,aSize,aSubCategory)) + return EFalse; + } + else + { + TUint8* end = aData+aSize; + aOutSize -= 4 + aExtraIds; // first 4 bytes of trace are always present, and don't count towards 'size' of multipart trace + TUint32 aOffset = 0; + while(aOffset threadName = RThread().Name().Collapse(); + TUint threadId = RThread().Id(); + TBuf8 processName = RProcess().Name().Collapse(); + + TUint32 threadTraceId = 0; + TUint32 processTraceId = 0; + TUint8* data; + TInt size; + + test.Start(_L("Reset trace buffer")); + Trace.SetMode(0); + TInt oldSize = Trace.BufferSize(); + TInt r = Trace.ResizeBuffer(0x100000); + test_KErrNone(r); + Trace.SetFilter(BTrace::EThreadIdentification,0); + Trace.SetMode(RBTrace::EEnable); + + test.Next(_L("Test category is primed correct when it is enabled")); + Trace.SetFilter(BTrace::EThreadIdentification,1); + // search for current thread in trace... + TUint8* trace; + size=Trace.GetData(trace); + test_NotNull(size); + TUint8* end = trace+size; + for(data=trace; data>24u); + + if(size<4) + BTrace0(category,subCategory); + else if(size<=8) + BTrace4(category,subCategory,((TUint32*)aData)[1]); + else if(size<12) + BTrace8(category,subCategory,((TUint32*)aData)[1],((TUint32*)aData)[2]); + else + BTraceN(category,subCategory,((TUint32*)aData)[1],((TUint32*)aData)[2],&((TUint32*)aData)[3],size-12); + ++subCategory; + } + return 0; + } + + +TInt SoakThreadFunction2(TAny* aData) + { + TUint32 random = 0; + BTrace::TCategory category = (BTrace::TCategory)*(TUint8*)aData; + TUint subCategory = 0; + while(!SoakDone) + { + random = random*69069+1; + TUint size = (random>>24u); + + TInt outOk; + if(size<=8) + outOk = BTraceFiltered4(category,subCategory,((TUint32*)aData)[1]); + else if(size<12) + outOk = BTraceFiltered8(category,subCategory,((TUint32*)aData)[1],((TUint32*)aData)[2]); + else + outOk = BTraceFilteredN(category,subCategory,((TUint32*)aData)[1],((TUint32*)aData)[2],&((TUint32*)aData)[3],size-12); + if(outOk) + ++subCategory; + } + return 0; + } + + +TInt SoakControlThreadFunction(TAny*) + { + // randomly mess with thread priorities of soak test threads so + // we get lots of preemption going on + const TThreadPriority priorities[] = + { + EPriorityMuchLess, + EPriorityLess, + EPriorityNormal, + EPriorityMore + }; + + TUint32 random = 0; + while(!SoakDone) + { + User::AfterHighRes(1); + random = random*69069+1; + SoakThread[(random>>16)%3].SetPriority(priorities[(random>>14)&3]); + } + return 0; + } + + +void ChangeSecondaryFilter() + { + // mess with secondary filter... + static TUint32 random = 0; + random = random*69069+1; + switch(random>>29) + { + case 0: + Trace.SetFilter2(KBTraceFilterTestUid1,0); + break; + case 1: + Trace.SetFilter2(KBTraceFilterTestUid1,1); + break; + case 2: + Trace.SetFilter2(KBTraceFilterTestUid2,0); + break; + case 3: + Trace.SetFilter2(KBTraceFilterTestUid2,1); + break; + case 4: + Trace.SetFilter2(0); + break; + case 5: + Trace.SetFilter2(1); + break; + case 6: + Trace.SetFilter2(&KBTraceFilterTestUid1,1); + break; + case 7: + Trace.SetFilter2(&KBTraceFilterTestUid2,1); + break; + } + } + +//--------------------------------------------- +//! @SYMTestCaseID KBASE-T_BTRACE-0066 +//! @SYMTestType UT +//! @SYMPREQ PREQ1030 +//! @SYMTestCaseDesc Soak tests +//! @SYMTestActions Generate ordered traces of random size using two worker threads and +//! read the generated trace in the main test program thread. All threads are scheduled +//! in a random manner. +//! @SYMTestExpectedResults Captured traces must contain the correct data and any +//! missing traces must be indicated by the EMissingRecord flag in the next trace. +//! @SYMTestPriority High +//! @SYMTestStatus Implemented +//--------------------------------------------- +void TestSoak(TUint aMode,TUint aTimeInSeconds) + { + aMode |= RBTrace::EEnable; + + test.Start(_L("Reset trace buffer")); + TInt oldSize = Trace.BufferSize(); + TInt r = Trace.ResizeBuffer(0x10000); + test_KErrNone(r); + Trace.SetMode(aMode); + Trace.SetFilter(BTrace::ETest1,1); + Trace.SetFilter(BTrace::ETest2,1); + Trace.SetFilter2(KBTraceFilterTestUid2,1); + + TUint32* buffer = (TUint32*)Trace.DataChunk().Base(); + test.Printf(_L("Buffer=%x %x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n"),buffer, + buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],buffer[8],buffer[9]); + + test.Next(_L("Random traces...")); + Trace1Sequence = 0; + Trace2Sequence = 0; + RTimer timer; + test_KErrNone(timer.CreateLocal()); + SoakThread[0].Duplicate(RThread(),EOwnerProcess); + test_KErrNone(SoakThread[1].Create(KNullDesC,SoakThreadFunction,0x1000,&User::Allocator(),KTestTrace1)); + test_KErrNone(SoakThread[2].Create(KNullDesC,SoakThreadFunction2,0x1000,&User::Allocator(),KTestTrace2)); + test_KErrNone(SoakThread[3].Create(KNullDesC,SoakControlThreadFunction,0x1000,&User::Allocator(),KTestTrace2)); + // The control thread must be resumed first otherwise time slicing perculiarities + // can cause the soak threads to take all of the CPU time... + SoakThread[3].SetPriority(EPriorityMuchMore); + SoakThread[3].Resume(); + + TRequestStatus s; + TTimeIntervalMicroSeconds32 tickPeriod; + UserHal::TickPeriod(tickPeriod); + TInt64 ticks = aTimeInSeconds; + ticks *= 1000000; + ticks /= tickPeriod.Int(); + timer.AfterTicks(s,(TInt)ticks); + + // resume threads producing trace output... + SoakThread[1].Resume(); + SoakThread[2].Resume(); + + TInt64 totalSize = 0; + for(;;) + { + ChangeSecondaryFilter(); + const TInt KTraceDataBlockSize = 0x1000; + TUint8* data; + TInt size; + while(s==KRequestPending && (size=Trace.GetData(data))!=0) + { +// RDebug::Printf("READ: data=%08x size=%08x\n",data,size); + if(s!=KRequestPending) + break; + CheckTraceData(data,size); + totalSize += size; + Trace.DataUsed(); + } + if(s!=KRequestPending) + break; + TRequestStatus waitStatus; + Trace.RequestData(waitStatus,KTraceDataBlockSize); + User::WaitForRequest(waitStatus); + test_KErrNone(waitStatus.Int()); + } + User::WaitForRequest(s); + test_Equal(EExitPending, SoakThread[1].ExitType() ); + test_Equal(EExitPending, SoakThread[2].ExitType() ); + test_Equal(EExitPending, SoakThread[3].ExitType() ); + SoakThread[1].Kill(0); + SoakThread[2].Kill(0); + SoakThread[3].Kill(0); + SoakThread[1].Close(); + SoakThread[2].Close(); + SoakThread[3].Close(); + + test.Printf(_L("total trace data processed = %ld k\n"),totalSize>>10); + + test.Next(_L("Restore buffer")); + r = Trace.ResizeBuffer(oldSize); + test_KErrNone(r); + + test.End(); + } + + +void KernelBenchmark(TUint& aTime1,TUint& aTime2,TUint& aTime3,TBool aTraceEnabled,TBool aFilter2) + { + TInt oldSize = Trace.BufferSize(); + + TInt r = Trace.ResizeBuffer(0x1000); + test_KErrNone(r); + Trace.SetMode(RBTrace::EFreeRunning|RBTrace::EEnable); + + if(aFilter2) + r = 1+TraceTest.TestBenchmark2(0,1000000); + else + r = 1+TraceTest.TestBenchmark(0,1000000); + TUint8* data; + TInt size = Trace.GetData(data); + test(aTraceEnabled ? size!=0 : size==0); + Trace.DataUsed(); + aTime1 = 1000000000/r; + + r = Trace.ResizeBuffer(0x1000); + test_KErrNone(r); + Trace.SetMode(RBTrace::EFreeRunning|RBTrace::EEnable); + + if(aFilter2) + r = 1+TraceTest.TestBenchmark2(KMaxBTraceDataArray,1000000); + else + r = 1+TraceTest.TestBenchmark(KMaxBTraceDataArray,1000000); + size = Trace.GetData(data); + test(aTraceEnabled ? size!=0 : size==0); + Trace.DataUsed(); + aTime2 = 1000000000/r; + + r = 1+TraceTest.TestBenchmarkCheckFilter(aFilter2,1000000); + aTime3 = 1000000000/r; + + r = Trace.ResizeBuffer(oldSize); + test_KErrNone(r); + } + + +void UserBenchmark(TUint& aTime1,TUint& aTime2,TUint& aTime3,TBool aTraceEnabled,TBool aFilter2) + { + TInt oldSize = Trace.BufferSize(); + + RTimer timer; + TRequestStatus status; + test_KErrNone(timer.CreateLocal()); + + TInt r = Trace.ResizeBuffer(0x1000); + test_KErrNone(r); + Trace.SetMode(RBTrace::EFreeRunning|RBTrace::EEnable); + + timer.After(status,1); + User::WaitForRequest(status); + timer.After(status,1000000); + r = 0; + if(aFilter2) + do + { + BTraceFiltered4(BTrace::ETest1,0,KBTraceFilterTestUid1); + ++r; + } + while(status==KRequestPending); + else + do + { + BTrace0(BTrace::ETest1,0); + ++r; + } + while(status==KRequestPending); + User::WaitForRequest(status); + TUint8* data; + TInt size = Trace.GetData(data); + test(aTraceEnabled ? size!=0 : size==0); + Trace.DataUsed(); + aTime1 = 1000000000/r; + + r = Trace.ResizeBuffer(0x1000); + test_KErrNone(r); + Trace.SetMode(RBTrace::EFreeRunning|RBTrace::EEnable); + + timer.After(status,1); + User::WaitForRequest(status); + timer.After(status,1000000); + r = 0; + if(aFilter2) + do + { + BTraceFilteredContextN(BTrace::ETest1,0,KBTraceFilterTestUid1,0,KTestTrace1,KMaxBTraceDataArray); + ++r; + } + while(status==KRequestPending); + else + do + { + BTraceContextN(BTrace::ETest1,0,0,0,KTestTrace1,KMaxBTraceDataArray); + ++r; + } + while(status==KRequestPending); + User::WaitForRequest(status); + size = Trace.GetData(data); + test(aTraceEnabled ? size!=0 : size==0); + Trace.DataUsed(); + aTime2 = 1000000000/r; + + timer.After(status,1); + User::WaitForRequest(status); + timer.After(status,1000000); + r = 0; + TBool check = -1; + if(aFilter2) + do + { + check = BTrace::CheckFilter2(BTrace::ETest1,KBTraceFilterTestUid1); + ++r; + } + while(status==KRequestPending); + else + do + { + check = BTrace::CheckFilter(BTrace::ETest1); + ++r; + } + while(status==KRequestPending); + test(check == aTraceEnabled); + aTime3 = 1000000000/r; + + r = Trace.ResizeBuffer(oldSize); + test_KErrNone(r); + } + + +//--------------------------------------------- +//! @SYMTestCaseID KBASE-T_BTRACE-0066-0067 +//! @SYMTestType UT +//! @SYMPREQ PREQ1030 +//! @SYMTestCaseDesc Benchmark tracing. +//! @SYMTestActions Time the generation of minimum and maximum sized traces both with +//! and without the trace filter enabled for the trace category. +//! @SYMTestExpectedResults Trace time with filter enabled should not excede 2000 nano-seconds, +//! and time with filter disabled should not excede 500 nano-seconds. (These limits are not +//! asserted). If time significantly excedes this then detailed investigation is required. +//! @SYMTestPriority Medium +//! @SYMTestStatus Implemented +//--------------------------------------------- +void TestBenchmark(TBool aUserTrace) + { + TUint t1 = 0; + TUint t2 = 0; + TUint t3 = 0; + +#define BENCH(a1,a2) aUserTrace ? UserBenchmark(t1,t2,t3,a1,a2) : KernelBenchmark(t1,t2,t3,a1,a2) + + test.Printf(_L(" Min Trace Max Trace Filter\n")); + + Trace.SetFilter(BTrace::ETest1,0); + BENCH(0,0); + test.Printf(_L("filter1 off %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter(BTrace::ETest1,1); + BENCH(1,0); + test.Printf(_L("filter1 on %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter(BTrace::ETest1,0); + Trace.SetFilter2(0); + BENCH(0,1); + test.Printf(_L("filter1 off filter2 off %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter(BTrace::ETest1,1); + Trace.SetFilter2(0); + BENCH(0,1); + test.Printf(_L("filter1 on global filter2 off %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter2(1); + BENCH(1,1); + test.Printf(_L("filter1 on global filter2 on %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter2(&KBTraceFilterTestUid2,1); + BENCH(0,1); + test.Printf(_L("filter1 on 1 UID filter2 off %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter2(&KBTraceFilterTestUid1,1); + BENCH(1,1); + test.Printf(_L("filter1 on 1 UID filter2 on %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter2(BigFilter2,sizeof(BigFilter2)/sizeof(TUint32)); + Trace.SetFilter2(KBTraceFilterTestUid1,0); + BENCH(0,1); + test.Printf(_L("filter1 on 100 UID filter2 off %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter2(BigFilter2,sizeof(BigFilter2)/sizeof(TUint32)); + BENCH(1,1); + test.Printf(_L("filter1 on 100 UID filter2 on %6d ns %6d ns %6d ns\n"),t1,t2,t3); + + Trace.SetFilter(BTrace::ETest1,0); + Trace.SetFilter2(0); + } + +struct THREADTRACETESTSTRUCT { + TInt* alloc_addr; + void* chunk_addr; +}; + +LOCAL_D TInt threadtraceTestThread(TAny* param) + { + THREADTRACETESTSTRUCT* p = (THREADTRACETESTSTRUCT*)param; + p->alloc_addr = new TInt; + delete p->alloc_addr; + return 0; + } + +void TestHeapAndChunkTrace() + { + if(KErrNotSupported==Trace.Filter(BTrace::EHeap)) + { + test.Start(_L("Trace category EHeap not supported by this build of kernel.")); + test.End(); + return; + } + + test.Start(_L("Reset trace buffer")); + Trace.SetMode(0); + TInt oldSize = Trace.BufferSize(); + TInt r = Trace.ResizeBuffer(0x100000); + test_KErrNone(r); + Trace.SetFilter(BTrace::EHeap,0); + Trace.SetFilter(BTrace::EChunks,0); + Trace.SetMode(RBTrace::EEnable); + + test.Next(_L("Test heap-alloc works as expected")); + Trace.SetFilter(BTrace::EHeap,1); + TBool chunkTraceEnabled = Trace.SetFilter(BTrace::EChunks,1)!=KErrNotSupported; + + // Create a test thread + THREADTRACETESTSTRUCT threadtest; + RThread thread; + TRequestStatus stat; + test.Next(_L("Test thread creation heap trace")); + r=thread.Create(_L("t_tbrace_2"),threadtraceTestThread,KDefaultStackSize,0x2000,0x2000,&threadtest); + test_KErrNone(r); + thread.Logon(stat); + thread.Resume(); + User::WaitForRequest(stat); + + + // search for heap records in trace... + TUint8* data; + TUint8* trace; + TInt size=Trace.GetData(trace); + test_NotNull(size); + TUint8* end = trace+size; + TUint chunk_ptr = 0, heap_chunk_ptr = 0; + int found_chunk_create = 0; + int found_heap_chunk_create = 0; + int found_heap_create=0; + int found_heap_alloc=0; + int found_heap_free=0; + for(data=trace; data= ,4); + } + } + if(data[BTrace::ESubCategoryIndex]==BTrace::EHeapFree) + { + if(Body(data)[1]==(TUint)threadtest.alloc_addr) + found_heap_free=1; + } + } + } + test(found_heap_create); + test(found_heap_chunk_create); + test(found_heap_alloc); + test(found_heap_free); + if(!chunkTraceEnabled) + { + test.Next(_L("Trace category EChunk not supported by this build of kernel.")); + test.End(); + return; + } + test(chunk_ptr && heap_chunk_ptr); + test(chunk_ptr == heap_chunk_ptr); + //Trace.DataUsed(); + + // Turn on chunk trace and empty btrace buffer + test.Next(_L("Chunk testing")); + Trace.SetFilter(BTrace::EChunks,1); + Trace.Empty(); + + // Create a chunk and test the expected traces + RChunk chunk; + test_KErrNone(chunk.CreateLocal(4096, 4*1024*1024)); + trace = NULL; + size=Trace.GetData(trace); + test_NotNull(size); + end = trace+size; + found_chunk_create=0; + for(data=trace; data>= 1; + if(Trace.SetFilter(category,newBits&1)) + oldBits |= 0x80000000u; + newBits >>= 1; + ++category; + } + while(category&31); + if(aOld) + *aOld++ = oldBits; + } + while(category<256); + } + + +TUint32 OldTraceFilter[8] = {0}; + + +//thread function to generate BTrace::EHeap::EHeapAllocFail event +LOCAL_D TInt ThreadtraceAllocFailTestThread(TAny* /*param*/) + { + RPointerArray array(1000); + TInt i = 1; + for(;;) + { + TInt32* p = new TInt32[(++i)*2]; + if(!p) + break; + else + if(array.Append(p) == KErrNoMemory) + break; + } + array.ResetAndDestroy(); + array.Close(); + return 0; + } + +//thread function to generate BTrace::EHeap::EHeapReAllocFail event +LOCAL_D TInt ThreadtraceReAllocFailTestThread(TAny* /*param*/) + { + TInt s = 4; + TUint8 *p = (TUint8*)User::Alloc(s); + for(;;) + { + s *= 2; + TUint8* np = (TUint8*)User::ReAlloc(p, s); + if(!np) + { + delete [] p; + break; + } + else + p=np; + } + return 0; + } + + + +//--------------------------------------------------------------------------------------------------------------------- +//! @SYMTestCaseID KBASE-T_BTRACE-0733 +//! @SYMTestCaseDesc Test BTrace - EHeapAllocFail and EHeapReAllocFail subcategories. +//! @SYMTestType UT +//! @SYMPREQ PREQ1340 +//! @SYMTestPriority Medium +//! @SYMTestActions +//! 1. Configure BTrace to use EHeap and EThreadIdentification as main filter +//! categories. +//! 2. Create and start a thread which will eventually exhaust +//! all memory resources (this should result with sending a trace +//! from allocator class - sent trace should have +//! category - EHeap and subcategory - EHeapAllocFail). +//! 3. After thread (from previous point) crashes, get trace data from BTrace +//! and search for trace with category EHeap and subcategory EHeapAllocFail +//! 4. Validate trace data payload - it should have exactly 8 bytes (2x4 bytes values). +//! +//! @SYMTestExpectedResults +//! 1. Trace data should contain at least one trace with category +//! EHeap and subcategory EHeapAllocFail. +//! 2. Trace data payload (where category is EHeap and subcategory is EHeapAllocFail) should +//! be 8 bytes long (2 x 4 bytes values). +//--------------------------------------------------------------------------------------------------------------------- +void TestHeapAllocFailEvent(TInt aTestCategory) + { + //configurnig trace + if(aTestCategory == BTrace::EHeapAllocFail) + test.Next(_L("Test to check BTrace::EHeap::EHeapAllocFail trace event")); + else if(aTestCategory == BTrace::EHeapReAllocFail) + test.Next(_L("Test to check BTrace::EHeap::EHeapReAllocFail trace event")); + //configure BTrace + Trace.Open(); + Trace.SetMode(0); + TInt r = Trace.ResizeBuffer(0x100000); + + test_KErrNone(r); + Trace.SetFilter(BTrace::EHeap,0); + Trace.SetFilter(BTrace::EChunks,0); + Trace.SetMode(RBTrace::EEnable); + Trace.SetFilter(BTrace::EHeap,1); + Trace.SetFilter(BTrace::EThreadIdentification,1); + + //start thread to cause EHeapAllocFail event + RThread thread; + TRequestStatus stat; + + //starting test thread + if(aTestCategory == BTrace::EHeapAllocFail) + r = thread.Create(_L("t_btrace_allocfail_thread"), ThreadtraceAllocFailTestThread, KDefaultStackSize, 0x2000, 0x2000, NULL); + else if(aTestCategory == BTrace::EHeapReAllocFail) + r = thread.Create(_L("t_btrace_reallocfail_thread"), ThreadtraceReAllocFailTestThread, KDefaultStackSize, 0x2000, 0x2000, NULL); + + test_KErrNone(r); + thread.Logon(stat); + thread.Resume(); + User::WaitForRequest(stat); + thread.Close(); + + //getting trace data + TUint8* data; + TUint8* trace; + TInt size=Trace.GetData(trace); + + test_NotNull(size); + TUint8* end = trace+size; + TInt8 found_heap_allocfail = 0; + + TInt subCat = BTrace::EHeapAllocFail; + TInt expectedDataSize = 8; + if(aTestCategory == BTrace::EHeapReAllocFail) + { + subCat = BTrace::EHeapReAllocFail; + expectedDataSize = 12; + } + + for(data=trace; data 8 + { + UTRACE_SECONDARY_ANY(BTrace::ETest1, KBTraceFilterTestUid1, aContextPresent, aPcPresent, KUtracePcValues[1], formatId, data+3, aSizeOfData); + UTRACE_SECONDARY_ANY(BTrace::ETest1, KBTraceFilterTestUid1, aContextPresent, aPcPresent, KUtracePcValues[2], formatId, data+3, aSizeOfData); + //BTraceFilteredContextPcBig(BTrace::ETest1,KTest1SubCategory,KBTraceFilterTestUid1,data+2,aSizeOfData-4); + //BTraceFilteredContextPcBig(BTrace::ETest1,KTest1SubCategory,KBTraceFilterTestUid1,data+2,aSizeOfData-4); + } + } + + +void CheckUtraceFlags(TUint8* aData, TUint8* aData2, TBool aContextPresent, TBool aPcPresent) + { + TUint offset = ContextOffset(aData); + if(aContextPresent) + { + aContextPresent = BTrace::EContextIdPresent; + test((aContextPresent == (aData[BTrace::EFlagsIndex]&BTrace::EContextIdPresent))); + test_Equal(ThisTraceContextId, ((TUint32*)(aData+offset))[0] ); + test_Equal(ThisTraceContextId, ((TUint32*)(aData2+offset))[0] ); + } + if(aPcPresent) + { + aPcPresent = BTrace::EPcPresent; + test((aPcPresent == (aData[BTrace::EFlagsIndex]&BTrace::EPcPresent))); + if(aContextPresent) + { + test_Compare(((TUint32*)(aData+offset))[1], ==, KUtracePcValues[1]); //(offset plus 1 because context id is before pc) + test_Compare(((TUint32*)(aData2+offset))[1], ==, KUtracePcValues[2]); + } + else + { + test_Compare(((TUint32*)(aData+offset))[0], ==, KUtracePcValues[1]); + test_Compare(((TUint32*)(aData2+offset))[0], ==, KUtracePcValues[2]); + } + } + } + +void SetupTestDataForUtrace(TBool aChangeData = ETrue) + { + if(aChangeData)//change to accomodate iFormatId only being 16 bit + { + KTestTrace1[10] = (TUint8) 0; + KTestTrace1[11] = (TUint8) 0; + } + else //restore to original data + { + KTestTrace1[10] = (TUint8) 10; + KTestTrace1[11] = (TUint8) 11; + } + } + +//--------------------------------------------- +//! @SYMTestCaseID KBASE-T_BTRACE-2441 +//! @SYMTestType UT +//! @SYMPREQ CR1623 +//! @SYMTestCaseDesc Test UTraces, including multiparted utraces, only testing user side for now, kernel side will be added later +//! @SYMTestActions Generate traces from kernel code using the UTrace macros as defined above, +//! @SYMTestExpectedResults Traces where broken down into multiple parts and +//! all trace contents captured by RBTrace matched those specified +//! at point of trace generation. Also, where appropriate, PC and/or +//! Context ID values are present and correct. +//! @SYMTestPriority High +//! @SYMTestStatus Prototype +//--------------------------------------------- +void TestUtrace(TBool aUserTrace, TBool aFilter2) + { + test.Next(_L("Testing utrace\n")); + TInt oldSize = Trace.BufferSize(); + TInt r = Trace.ResizeBuffer(0x100000); + test_KErrNone(r); + Trace.SetMode(RBTrace::EEnable); + + //set up the test data for UTrace + SetupTestDataForUtrace(); + + // dummy trace do get current thread context id + Trace.SetFilter(BTrace::ETest1,0); + ThisTraceContextId = TraceTest.Trace(BTrace::EContextIdPresent,KTestTrace1,0); + + // create a test filter... + TInt extraFlags = 0; + if(aUserTrace) + extraFlags |= RBTraceTest::EUserTrace; + TInt minSize = 4; + if(aFilter2) + { + extraFlags |= RBTraceTest::EFilter2Trace; + minSize += 4; + } + + //Test that filtering works... + TInt filterMode; + for(filterMode=0; filterMode<(aFilter2?6:2); ++filterMode) + { + + // setup filters... + Trace.SetFilter(BTrace::ETest1,1); + Trace.SetFilter2(BigFilter2,KNumBTraceFilterTestUids); + if(filterMode==0 || filterMode==2) + Trace.SetFilter(BTrace::ETest1,0); // disable in primary filter + if(filterMode==0 || filterMode==1) + Trace.SetFilter2(KBTraceFilterTestUid1,0); // disable in secondary filter + if(filterMode==4) + Trace.SetFilter2(0); // disable entire secondary filter + if(filterMode==5) + Trace.SetFilter2(1); // enable entire secondary filter + + // expectTrace is true if we expect trace to be output... + TBool expectTrace = aFilter2 ? (filterMode==3 || filterMode==5) : filterMode&1; + + switch(filterMode) + { + case 0: test.Next(_L("Test with primary filter OFF, secondary filter OFF")); break; + case 1: test.Next(_L("Test with primary filter ON, secondary filter OFF")); break; + case 2: test.Next(_L("Test with primary filter OFF, secondary filter ON")); break; + case 3: test.Next(_L("Test with primary filter ON, secondary filter ON")); break; + case 4: test.Next(_L("Test with primary filter ON, global secondary filter OFF")); break; + case 5: test.Next(_L("Test with primary filter ON, global secondary filter ON")); break; + } + + TBool contextPresent = EFalse; + TBool pcPresent = EFalse; + for(TInt flags = 0; flags < 4; flags++) + { + switch(flags) + { + case 0: test.Printf(_L("ContextId OFF, Pc OFF\n")); break; + case 1: contextPresent = ETrue; extraFlags = BTrace::EContextIdPresent|BTrace::EPcPresent|extraFlags; test.Printf(_L("ContextId ON, Pc OFF\n"));break; + case 2: pcPresent = ETrue; extraFlags = BTrace::EContextIdPresent|BTrace::EPcPresent|extraFlags; test.Printf(_L("ContextId OFF, Pc ON\n"));break; + case 3: contextPresent = ETrue; pcPresent = ETrue; extraFlags = BTrace::EContextIdPresent|BTrace::EPcPresent|extraFlags; test.Printf(_L("ContextId ON, Pc ON\n"));break; + } + + // multiparted traces... + BigTraceBeginTest(); + for(TInt i=0; i<=(TInt)sizeof(KTestTrace1)-4; i++) + { + //CallUtrace(typeOfCall, contextPresent, pcPresent, i); + CallUtrace(extraFlags, contextPresent, pcPresent, i); + + TUint8* data; + TUint8* data2; + TInt size = Trace.GetData(data); + if(!expectTrace) + { + test(!size); + continue; + } + size /= 2; + data2 = data+size; + + TInt sizePlusFormatId = i + 8; + test(CheckBigTrace1(data, size, sizePlusFormatId, KTest1SubCategory, 4)); + test(CheckBigTrace1(data2, size, sizePlusFormatId, KTest1SubCategory, 4)); + + CheckUtraceFlags(data, data2, contextPresent, pcPresent); + Trace.DataUsed(); + } + test_Equal(expectTrace,BigTraceEndTest()); // check we actually got multipart traces + } + } + + //Restore trace data + SetupTestDataForUtrace(EFalse); + + test.Next(_L("Restore buffer\n")); + r = Trace.ResizeBuffer(oldSize); + test_KErrNone(r); + Trace.SetFilter2(0); + } + + + +GLDEF_C TInt E32Main() + { + // initialise test trace data... + KTestTrace1[0] = BTrace::ETest1; + TUint i; + for(i=8; i>0)&0xff; + KTestTrace1[5] = (KBTraceFilterTestUid1>>8)&0xff; + KTestTrace1[6] = (KBTraceFilterTestUid1>>16)&0xff; + KTestTrace1[7] = (KBTraceFilterTestUid1>>24)&0xff; + + KTestTrace2[4] = (KBTraceFilterTestUid2>>0)&0xff; + KTestTrace2[5] = (KBTraceFilterTestUid2>>8)&0xff; + KTestTrace2[6] = (KBTraceFilterTestUid2>>16)&0xff; + KTestTrace2[7] = (KBTraceFilterTestUid2>>24)&0xff; + + for(i=0; i commandLine; + User::CommandLine(commandLine); + if(commandLine==_L("dump")) + { + test.Next(_L("Dumping trace buffer...")); + DumpTrace(); + goto done; + } + else if(commandLine==_L("soak")) + { + test.Next(_L("Running endless soak test...")); + for(;;) + { + test.Next(_L("Soak test in free-running mode")); + TestSoak(RBTrace::EFreeRunning,60); + test.Next(_L("Soak test in sample mode")); + TestSoak(0,60); + } + } + + test.Next(_L("Basic tests in sample mode")); + TestBasics(0); + test.Next(_L("Basic tests in free-running mode")); + TestBasics(RBTrace::EFreeRunning); + test.Next(_L("User BTrace test in sample mode")); + TestUserTrace(0); + test.Next(_L("Check secondary filter")); + TestFilter2(); + + test.Next(_L("Test user traces")); + TestTrace(ETrue,EFalse); + test.Next(_L("Test kernel traces")); + TestTrace(EFalse,EFalse); + test.Next(_L("Test user traces using secondary filter")); + TestTrace(ETrue,ETrue); + test.Next(_L("Test kernel traces using secondary filter")); + TestTrace(EFalse,ETrue); + + test.Next(_L("Big user traces")); + TestBig(ETrue,EFalse); + test.Next(_L("Big kernel traces")); + TestBig(EFalse,EFalse); + test.Next(_L("Big user traces using secondary filter")); + TestBig(ETrue,ETrue); + test.Next(_L("Big kernel traces using secondary filter")); + TestBig(EFalse,ETrue); + + test.Next(_L("Test category EThreadIdentification")); + TestThreadIdentification(); + test.Next(_L("Test category ECpuUsage")); + TestCpuUsage(); + + test.Next(_L("Soak test in sample mode")); + TestSoak(0,10); + test.Next(_L("Soak test in free-running mode")); + TestSoak(RBTrace::EFreeRunning,10); + + test.Next(_L("Benchmark kernel tracing")); + TestBenchmark(0); + test.Next(_L("Benchmark user tracing")); + TestBenchmark(1); + + test.Next(_L("Test category EHeap")); + TestHeapAndChunkTrace(); + + test.Next(_L("Test user side utraces")); + TestUtrace(ETrue, ETrue); + //Kernel side is currently not implemented + //test.Next(_L("Test kernel side utraces")); + //TestUtrace(EFalse, ETrue); + test.Next(_L("Benchmark user side UTraces")); + TestUtraceBenchmark(ETrue); + +done: + // restore trace settin gs... + Trace.SetMode(0); + SetBTraceFilter(OldTraceFilter,OldTraceFilter); + Trace.SetMode(savedMode); + + test.Next(_L("Close LDD")); + Trace.Close(); + TraceTest.Close(); + User::FreeLogicalDevice(RBTraceTest::Name()); + + //test RHeap instrumentation: + //with BTrace:EHeap:EHeapAllocFail trace points + TestHeapAllocFailEvent(BTrace::EHeapAllocFail); + //with BTrace:EHeap:EHeapReAllocFail trace points + TestHeapAllocFailEvent(BTrace::EHeapReAllocFail); + //with BTrace:EHeap:EHeapCorruption trace points + TestHeapCorruptionEvents(); + + test.End(); + return(0); + } +