kerneltest/e32test/debug/t_btrace.cpp
changeset 0 a41df078684a
child 43 c1f20ce4abcf
--- /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 <e32test.h>
+#include <e32svr.h>
+#include <e32def.h>
+#include <e32def_private.h>
+
+#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; i<actual_size; ++i)
+			{
+			test.Printf(_L(" %02x"), aData[i]);
+			if ((i&15)==15 || i==actual_size-1)
+				test.Printf(_L("\n"));
+			}
+		test.Printf(_L("extra=%d aExp=%d aSize=%d\n"), extra, aExpected, aSize);
+		return 0;
+		}
+	}
+
+
+TInt Trace1Sequence = 0;
+TInt Trace2Sequence = 0;
+
+TUint8* TraceData;
+TInt TraceDataSize;
+
+TInt BadTrace(TUint8* aData)
+	{
+	Trace.SetMode(0);
+	TUint8* buffer = Trace.DataChunk().Base();
+	test.Printf(_L("BAD TRACE: data=%x buffer=%x (dataRead=%x,%x)\n"),aData,buffer,TraceData,TraceDataSize);
+	TUint8* bufferEnd =  buffer+((TUint32*)buffer)[1]; // TBTraceBuffer.iEnd
+	while(buffer<bufferEnd)
+		{
+		RDebug::Printf("%08x  %02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x",
+			buffer,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],
+			buffer[8],buffer[9],buffer[10],buffer[11],buffer[12],buffer[13],buffer[14],buffer[15]);
+		buffer += 16;
+		}
+	buffer = Trace.DataChunk().Base();
+	TInt size = ((TUint32*)buffer)[9];
+	buffer += ((TUint32*)buffer)[8];
+	bufferEnd = buffer+size;
+	test.Printf(_L("copyBuffer=%x\n"),buffer,0);
+	while(buffer<bufferEnd)
+		{
+		RDebug::Printf("%08x  %02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x",
+			buffer,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],
+			buffer[8],buffer[9],buffer[10],buffer[11],buffer[12],buffer[13],buffer[14],buffer[15]);
+		buffer += 16;
+		}
+	return 0;
+	}
+
+void CheckTraceData(TUint8* aData, TUint aSize)
+	{
+	TraceData = aData;
+	TraceDataSize = aSize;
+	TUint8* end = aData+aSize;
+	while(aData<end)
+		{
+		TUint size = (aData[BTrace::ESizeIndex]+3)&~3;
+		if(aData+size>end)
+			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(record<end)
+			{
+			TUint size = record[BTrace::ESizeIndex];
+			TUint flags = record[BTrace::EFlagsIndex];
+			TUint category = record[BTrace::ECategoryIndex];
+			TUint subCategory = record[BTrace::ESubCategoryIndex];
+			TUint8* data = record+4;
+			size -= 4;
+
+			buf.Zero();
+			TUint32 header2 = 0;
+			if(flags&(BTrace::EHeader2Present))
+				{
+				header2 = *(TUint32*)data;
+				data += 4;
+				size -= 4;
+				}
+
+			if((flags&(BTrace::ETimestampPresent|BTrace::ETimestamp2Present))==(BTrace::ETimestampPresent|BTrace::ETimestamp2Present))
+				{
+				buf.AppendFormat(_L8("time:%08x:%08x "),((TUint32*)data)[1],*(TUint32*)data);
+				data += 8;
+				size -= 8;
+				}
+			else if(flags&(BTrace::ETimestampPresent|BTrace::ETimestamp2Present))
+				{
+				buf.AppendFormat(_L8("time:%08x "),*(TUint32*)data);
+				data += 4;
+				size -= 4;
+				}
+
+			if(flags&(BTrace::EContextIdPresent))
+				{
+				buf.AppendFormat(_L8("context:%08x "),*(TUint32*)data);
+				data += 4;
+				size -= 4;
+				}
+			else
+				{
+				buf.AppendFormat(_L8("                 "));
+				}
+
+			if(flags&(BTrace::EPcPresent))
+				{
+				buf.AppendFormat(_L8("pc:%08x "),*(TUint32*)data);
+				data += 4;
+				size -= 4;
+				}
+
+			TUint32 extra = 0;
+			if(flags&(BTrace::EExtraPresent))
+				{
+				extra = *(TUint32*)data;
+				data += 4;
+				size -= 4;
+				}
+
+			TUint32 data0 = (size>0) ? *(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; i<size; i+=4)
+					buf.AppendFormat(_L8("%08x "),*(TUint32*)(data+i));
+				}
+				break;
+				}
+			buf.Append('\r');
+			buf.Append('\n');
+			RDebug::RawPrint(buf.Expand());
+
+			record = BTrace::NextRecord(record);
+			}
+		Trace.DataUsed();
+		}
+	}
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBASE-T_BTRACE-0058-0059
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1030
+//! @SYMTestCaseDesc Basic functionality tests which run in both 'sample' and 'free-running' modes.
+//! @SYMTestActions Test basic functionality provided by the functions:
+//!		RBTrace::SetFilter(), RBTrace::Empty(),
+//!		RBTrace::GetData(), RBTrace::DataUsed(),
+//!		RBTrace::RequestData(), RBTrace::CancelRequestData(),
+//!		RBTrace::BufferSize(), and RBTrace::ResizeBuffer()
+//! @SYMTestExpectedResults Function produce expected results.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void TestBasics(TUint aMode)
+	{
+	aMode |= RBTrace::EEnable;
+
+	TUint8* data;
+	TInt size;
+
+	test.Start(_L("Check a second Open() fails"));
+	RBTrace dummy;
+	TInt r = dummy.Open();
+	test_Equal(KErrInUse,r);
+	r = dummy.Open();
+	test_Equal(KErrInUse,r);
+
+	test.Next(_L("Reset trace buffer"));
+	Trace.SetMode(0);
+	Trace.Empty();
+	Trace.SetMode(aMode);
+
+	TUint8* buffer_base = Trace.DataChunk().Base();
+	test.Printf(_L("Buffer base %08x\n"), buffer_base);
+
+	test.Next(_L("Test SetFilter() and GetData()"));
+	Trace.SetFilter(BTrace::ETest1,0);
+	Trace.SetFilter(BTrace::ETest2,0);
+	size = Trace.GetData(data);
+	test_Equal(0,size);
+	Trace1(4);
+	size = Trace.GetData(data);
+	test_Equal(0,size);
+	Trace2(4);
+	size = Trace.GetData(data);
+	test_Equal(0,size);
+	Trace.SetFilter(BTrace::ETest1,1);
+	Trace2(4);
+	size = Trace.GetData(data);
+	test_Equal(0,size);
+	Trace1(4);
+	size = Trace.GetData(data);
+	test(CheckSize(data,size,4));
+	BaseSize = size - 4;
+	test.Printf(_L("BaseSize=%d\n"), BaseSize);
+
+	test.Next(_L("Test Empty()"));
+	Trace.Empty();
+	size = Trace.GetData(data);
+	test_Equal(0,size);
+
+	test.Next(_L("Test DataUsed()"));
+	Trace1(0);
+	size = Trace.GetData(data);
+	test(CheckSize(data,size,0));
+	Trace.DataUsed();
+	size = Trace.GetData(data);
+	test_Equal(0,size);
+
+	test.Next(_L("Test RequestData()"));
+	TRequestStatus s1;
+	TRequestStatus s2;
+	RTimer timer;
+	test_KErrNone(timer.CreateLocal());
+
+	// immediate notification...
+	Trace.RequestData(s1,0);
+	test_Equal(KRequestPending, s1.Int());
+	timer.After(s2,5*1000000);
+	Trace1(4);
+	User::WaitForRequest(s1,s2);
+	test_KErrNone(s1.Int());
+	timer.Cancel();
+	User::WaitForRequest(s2);
+
+	// immediate notification with size>n ...
+	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<TUint32> sortedArray(maxUids);
+	RArray<TUint32> 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<numUids; ++i)
+				{
+				sortedArray.InsertInUnsignedKeyOrder(KBTraceFilterTestUid+permute[i]);
+				array.Append(KBTraceFilterTestUid+permute[i]);
+				}
+
+			// set filter using single uid api...
+			Trace.SetFilter2(0);
+			for(i=0; i<numUids; ++i)
+				{
+				r = Trace.SetFilter2(KBTraceFilterTestUid+permute[i],1);
+				test_NotNegative(r);
+				}
+			test(CompareFilter2(&sortedArray[0],sortedArray.Count(),-1));
+
+			// set filter using multiple uid api...
+			Trace.SetFilter2(0);
+			r = Trace.SetFilter2(&array[0],array.Count());
+			test_NotNegative(r);
+			test(CompareFilter2(&sortedArray[0],sortedArray.Count(),-1));
+
+			// remove uids...
+			for(i=0; i<numUids; ++i)
+				{
+				TUint32 removedUid = KBTraceFilterTestUid+permute[i];
+				TBool removed = EFalse;
+				r = sortedArray.FindInUnsignedKeyOrder(removedUid);
+				if(r>=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(p<numUids && ++permute[p] == numUids)
+				permute[p++] = 0;
+			}
+		while(p<numUids);
+		}
+
+	test.Next(_L("Test global filter"));
+	Trace.SetFilter2(0);
+	test(CompareFilter2(0,0,0));
+	Trace.SetFilter2(1);
+	test(CompareFilter2(0,0,1));
+	r = Trace.SetFilter2(KBTraceFilterTestUid1,1);
+	test_Equal(1,r);
+	test(CompareFilter2(0,0,1));
+	r = Trace.SetFilter2(KBTraceFilterTestUid1,0);
+	test_Equal(KErrNotSupported,r);
+	test(CompareFilter2(0,0,1));
+	r = Trace.SetFilter2(&KBTraceFilterTestUid1,1);
+	test_KErrNone(r);
+	test(CompareFilter2(&KBTraceFilterTestUid1,1,-1));
+
+	test.Next(_L("Restore filter2"));
+	r = Trace.SetFilter2(filter2Buffer,filter2Size);
+	test_KErrNone(r);
+	Trace.SetFilter2(filter2Global);
+	Trace.SetFilter(BTrace::ETest1,0);
+	delete filter2Buffer;
+
+	test.End();
+	}
+
+TUint32 ThisTraceContextId;
+
+void TestTrace1(TUint aType,TInt aSize)
+	{
+	if(!(aType&RBTraceTest::EUserTrace))
+		{
+		// use driver to create a kernel trace...
+		TraceTest.Trace(aType,KTestTrace1,aSize);
+		return;
+		}
+
+	TInt size = aSize;
+	TUint32* data = (TUint32*)KTestTrace1;
+	BTrace::TCategory category = BTrace::ETest1;
+	TUint subCategory = KTest1SubCategory;
+	TUint type = aType&0xff;
+	TBool bigTrace = aType&RBTraceTest::EBigTrace;
+	TBool filter2Trace = aType&RBTraceTest::EFilter2Trace;
+
+	if(!filter2Trace)
+		{
+		if(type==BTrace::EPcPresent)
+			{
+			if(bigTrace)
+				{
+				BTracePcBig(category,subCategory,data[1],data+2,size-4);
+				BTracePcBig(category,subCategory,data[1],data+2,size-4);
+				}
+			else if(size==0)
+				{
+				BTracePc0(category,subCategory);
+				BTracePc0(category,subCategory);
+				}
+			else if(size<=4)
+				{
+				BTracePc4(category,subCategory,data[1]);
+				BTracePc4(category,subCategory,data[1]);
+				}
+			else if(size<=8)
+				{
+				BTracePc8(category,subCategory,data[1],data[2]);
+				BTracePc8(category,subCategory,data[1],data[2]);
+				}
+			else
+				{
+				BTracePcN(category,subCategory,data[1],data[2],data+3,size-8);
+				BTracePcN(category,subCategory,data[1],data[2],data+3,size-8);
+				}
+			}
+		else if(type==BTrace::EContextIdPresent)
+			{
+			if(bigTrace)
+				{
+				BTraceContextBig(category,subCategory,data[1],data+2,size-4);
+				BTraceContextBig(category,subCategory,data[1],data+2,size-4);
+				}
+			else if(size==0)
+				{
+				BTraceContext0(category,subCategory);
+				BTraceContext0(category,subCategory);
+				}
+			else if(size<=4)
+				{
+				BTraceContext4(category,subCategory,data[1]);
+				BTraceContext4(category,subCategory,data[1]);
+				}
+			else if(size<=8)
+				{
+				BTraceContext8(category,subCategory,data[1],data[2]);
+				BTraceContext8(category,subCategory,data[1],data[2]);
+				}
+			else
+				{
+				BTraceContextN(category,subCategory,data[1],data[2],data+3,size-8);
+				BTraceContextN(category,subCategory,data[1],data[2],data+3,size-8);
+				}
+			}
+		else if(type==BTrace::EContextIdPresent+BTrace::EPcPresent)
+			{
+			if(bigTrace)
+				{
+				BTraceContextPcBig(category,subCategory,data[1],data+2,size-4);
+				BTraceContextPcBig(category,subCategory,data[1],data+2,size-4);
+				}
+			else if(size==0)
+				{
+				BTraceContextPc0(category,subCategory);
+				BTraceContextPc0(category,subCategory);
+				}
+			else if(size<=4)
+				{
+				BTraceContextPc4(category,subCategory,data[1]);
+				BTraceContextPc4(category,subCategory,data[1]);
+				}
+			else if(size<=8)
+				{
+				BTraceContextPc8(category,subCategory,data[1],data[2]);
+				BTraceContextPc8(category,subCategory,data[1],data[2]);
+				}
+			else
+				{
+				BTraceContextPcN(category,subCategory,data[1],data[2],data+3,size-8);
+				BTraceContextPcN(category,subCategory,data[1],data[2],data+3,size-8);
+				}
+			}
+		else
+			{
+			if(bigTrace)
+				BTraceBig(category,subCategory,data[1],data+2,size-4);
+			else if(size==0)
+				BTrace0(category,subCategory);
+			else if(size<=4)
+				BTrace4(category,subCategory,data[1]);
+			else if(size<8)
+				BTrace8(category,subCategory,data[1],data[2]);
+			else
+				BTraceN(category,subCategory,data[1],data[2],data+3,size-8);
+			}
+		}
+	else
+		{
+		if(type==BTrace::EPcPresent)
+			{
+			if(bigTrace)
+				{
+				BTraceFilteredPcBig(category,subCategory,data[1],data+2,size-4);
+				BTraceFilteredPcBig(category,subCategory,data[1],data+2,size-4);
+				}
+			else if(size<4)
+				{
+				// invalid
+				}
+			else if(size==4)
+				{
+				BTraceFilteredPc4(category,subCategory,data[1]);
+				BTraceFilteredPc4(category,subCategory,data[1]);
+				}
+			else if(size<=8)
+				{
+				BTraceFilteredPc8(category,subCategory,data[1],data[2]);
+				BTraceFilteredPc8(category,subCategory,data[1],data[2]);
+				}
+			else
+				{
+				BTraceFilteredPcN(category,subCategory,data[1],data[2],data+3,size-8);
+				BTraceFilteredPcN(category,subCategory,data[1],data[2],data+3,size-8);
+				}
+			}
+		else if(type==BTrace::EContextIdPresent)
+			{
+			if(bigTrace)
+				{
+				BTraceFilteredContextBig(category,subCategory,data[1],data+2,size-4);
+				BTraceFilteredContextBig(category,subCategory,data[1],data+2,size-4);
+				}
+			else if(size<4)
+				{
+				// invalid
+				}
+			else if(size==4)
+				{
+				BTraceFilteredContext4(category,subCategory,data[1]);
+				BTraceFilteredContext4(category,subCategory,data[1]);
+				}
+			else if(size<=8)
+				{
+				BTraceFilteredContext8(category,subCategory,data[1],data[2]);
+				BTraceFilteredContext8(category,subCategory,data[1],data[2]);
+				}
+			else
+				{
+				BTraceFilteredContextN(category,subCategory,data[1],data[2],data+3,size-8);
+				BTraceFilteredContextN(category,subCategory,data[1],data[2],data+3,size-8);
+				}
+			}
+		else if(type==BTrace::EContextIdPresent+BTrace::EPcPresent)
+			{
+			if(bigTrace)
+				{
+				BTraceFilteredContextPcBig(category,subCategory,data[1],data+2,size-4);
+				BTraceFilteredContextPcBig(category,subCategory,data[1],data+2,size-4);
+				}
+			else if(size<4)
+				{
+				// invalid
+				}
+			else if(size==4)
+				{
+				BTraceFilteredContextPc4(category,subCategory,data[1]);
+				BTraceFilteredContextPc4(category,subCategory,data[1]);
+				}
+			else if(size<=8)
+				{
+				BTraceFilteredContextPc8(category,subCategory,data[1],data[2]);
+				BTraceFilteredContextPc8(category,subCategory,data[1],data[2]);
+				}
+			else
+				{
+				BTraceFilteredContextPcN(category,subCategory,data[1],data[2],data+3,size-8);
+				BTraceFilteredContextPcN(category,subCategory,data[1],data[2],data+3,size-8);
+				}
+			}
+		else
+			{
+			if(bigTrace)
+				BTraceFilteredBig(category,subCategory,data[1],data+2,size-4);
+			else if(size<4)
+				{
+				// invalid
+				}
+			else if(size==4)
+				BTraceFiltered4(category,subCategory,data[1]);
+			else if(size<8)
+				BTraceFiltered8(category,subCategory,data[1],data[2]);
+			else
+				BTraceFilteredN(category,subCategory,data[1],data[2],data+3,size-8);
+			}
+		}
+	}
+
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBASE-T_BTRACE-0062-0063
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1030
+//! @SYMTestCaseDesc Test traces which specify thread context and/or program counter values.
+//! @SYMTestActions Generate traces from user and kernel code using the BTracePcX,
+//!		BTraceContextX and BTraceContextPcX macros. Kernel traces are additionaly
+//!		generated in ISR and IDFC context.
+//! @SYMTestExpectedResults All trace contents captured by RBTrace match those specified
+//!		at point of trace generation. Also, where appropriate, PC and/or Context ID values
+//!		are present and correct.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void TestTrace(TBool aUserTrace, TBool aFilter2)
+	{
+	test.Start(_L("Reset trace buffer"));
+	TInt oldSize = Trace.BufferSize();
+	TInt r = Trace.ResizeBuffer(0x100000);
+	test_KErrNone(r);
+	Trace.SetMode(RBTrace::EEnable);
+
+	// 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 = 0;
+	if(aFilter2)
+		{
+		extraFlags |= RBTraceTest::EFilter2Trace;
+		minSize += 4;
+		}
+
+	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;
+			}
+
+		test.Start(_L("Traces without special context"));
+		TInt i;
+		for(i=minSize; i<=8+(TInt)KMaxBTraceDataArray; i++)
+			{
+			TestTrace1(extraFlags,i);
+
+			TUint8* data;
+			TInt size;
+			size = Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+
+			test(CheckSize(data,size,i));
+			test(CheckTrace1(data,size,KTest1SubCategory));
+
+			test(!(data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+			test(!(data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+			Trace.DataUsed();
+			}
+
+		test.Next(_L("Traces with PC"));
+		for(i=minSize; i<=8+(TInt)KMaxBTraceDataArray; i++)
+			{
+			TestTrace1(BTrace::EPcPresent|extraFlags,i);
+
+			TUint8* data;
+			TUint8* data2;
+			TInt size;
+			size=Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+			size /= 2;
+			data2 = data+size;
+
+			test(CheckSize(data,size,i));
+			test(CheckTrace1(data,size,KTest1SubCategory));
+
+			test(CheckSize(data2,size,i));
+			test(CheckTrace1(data2,size,KTest1SubCategory));
+
+			test(!(data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+			test((data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+			TInt offset = ContextOffset(data);
+			test_Compare( ((TUint32*)(data+offset))[0], != ,((TUint32*)(data2+offset))[0]);
+
+			Trace.DataUsed();
+			}
+
+		test.Next(_L("Traces with Context ID"));
+		for(i=minSize; i<=8+(TInt)KMaxBTraceDataArray; i++)
+			{
+			TestTrace1(BTrace::EContextIdPresent|extraFlags,i);
+
+			TUint8* data;
+			TUint8* data2;
+			TInt size;
+			size=Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+			size /= 2;
+			data2 = data+size;
+
+			test(CheckSize(data,size,i));
+			test(CheckTrace1(data,size,KTest1SubCategory));
+
+			test(CheckSize(data2,size,i));
+			test(CheckTrace1(data2,size,KTest1SubCategory));
+
+			test((data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+			test(!(data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+			TUint offset = ContextOffset(data);
+			test_Equal(ThisTraceContextId, ((TUint32*)(data+offset))[0]);
+			test_Equal(ThisTraceContextId, ((TUint32*)(data2+offset))[0]);
+			Trace.DataUsed();
+			}
+
+		test.Next(_L("Traces with Context ID and PC"));
+		for(i=minSize; i<=8+(TInt)KMaxBTraceDataArray; i++)
+			{
+			TestTrace1(BTrace::EContextIdPresent|BTrace::EPcPresent|extraFlags,i);
+
+			TUint8* data;
+			TUint8* data2;
+			TInt size;
+			size=Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+			size /= 2;
+			data2 = data+size;
+
+			test(CheckSize(data,size,i));
+			test(CheckTrace1(data,size,KTest1SubCategory));
+
+			test(CheckSize(data2,size,i));
+			test(CheckTrace1(data2,size,KTest1SubCategory));
+
+			test((data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+			test((data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+			TUint offset = ContextOffset(data);
+
+			test_Equal(ThisTraceContextId, ((TUint32*)(data+offset))[0]);
+			test_Equal(ThisTraceContextId, ((TUint32*)(data2+offset))[0]);
+			test_Compare( ((TUint32*)(data+offset))[1], != ,((TUint32*)(data2+offset))[1]);
+
+			Trace.DataUsed();
+			}
+
+		if(!aUserTrace)
+			{
+			test.Next(_L("Traces with Context ID in ISR mode"));
+			for(i=minSize; i<=8+(TInt)KMaxBTraceDataArray; i++)
+				{
+				TraceTest.Trace(BTrace::EContextIdPresent|RBTraceTest::EContextIsr|extraFlags,KTestTrace1,i);
+
+				TUint8* data;
+				TUint8* data2;
+				TInt size;
+				size=Trace.GetData(data);
+				if(!expectTrace)
+					{
+					test(!size);
+					continue;
+					}
+				size /= 2;
+				data2 = data+size;
+
+				test(CheckSize(data,size,i));
+				test(CheckTrace1(data,size,KTest1SubCategory));
+
+				test(CheckSize(data2,size,i));
+				test(CheckTrace1(data2,size,KTest1SubCategory));
+
+				test((data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+				test(!(data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+				TUint offset = ContextOffset(data);
+				test( ((TUint32*)(data+offset))[0] == 2 );
+				test( ((TUint32*)(data2+offset))[0] == 2 );
+
+				Trace.DataUsed();
+				}
+
+			test.Next(_L("Traces with Context ID in IDFC mode"));
+			for(i=minSize; i<=8+(TInt)KMaxBTraceDataArray; i++)
+				{
+				TraceTest.Trace(BTrace::EContextIdPresent|RBTraceTest::EContextIDFC|extraFlags,KTestTrace1,i);
+
+				TUint8* data;
+				TUint8* data2;
+				TInt size;
+				size=Trace.GetData(data);
+				if(!expectTrace)
+					{
+					test(!size);
+					continue;
+					}
+				size /= 2;
+				data2 = data+size;
+
+				test(CheckSize(data,size,i));
+				test(CheckTrace1(data,size,KTest1SubCategory));
+
+				test(CheckSize(data2,size,i));
+				test(CheckTrace1(data2,size,KTest1SubCategory));
+
+				test((data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+				test(!(data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+				TUint offset = ContextOffset(data);
+				test( ((TUint32*)(data+offset))[0] == 3 );
+				test( ((TUint32*)(data2+offset))[0] == 3 );
+
+				Trace.DataUsed();
+				}
+			}
+		test.End();
+		r = Trace.ResizeBuffer(0x100000);	// avoid buffer wrap problems
+		test_KErrNone(r);
+		Trace.SetMode(RBTrace::EEnable);
+		}
+
+	test.Next(_L("Restore buffer"));
+	r = Trace.ResizeBuffer(oldSize);
+	test_KErrNone(r);
+	Trace.SetFilter2(0);
+
+	test.End();
+	}
+
+
+TUint32 BigTraceId = 0;
+
+TBool BigTraceFirst = 0;
+TBool BigTraceMiddle = 0;
+TBool BigTraceEnd = 0;
+
+void BigTraceBeginTest()
+	{
+	BigTraceFirst = 0;
+	BigTraceMiddle = 0;
+	BigTraceEnd = 0;
+	}
+
+TBool BigTraceEndTest()
+	{
+	return BigTraceFirst&&BigTraceMiddle&&BigTraceEnd;
+	}
+
+TBool DoCheckBigTrace1(TUint8*& aData, TUint32 aOutSize, TUint32& aOffset, TUint32 aExtraIds = 0)
+	{
+	TUint32* ptr = (TUint32*)aData;
+	if(aData[BTrace::ECategoryIndex]!=BTrace::ETest1)
+		return EFalse;
+	if(aData[BTrace::ESubCategoryIndex]!=KTest1SubCategory)
+		return EFalse;
+//	TUint32 header = *ptr++;
+	++ptr;
+
+	if(aData[BTrace::EFlagsIndex]&BTrace::ERecordTruncated)
+		return EFalse;
+
+	if(!(aData[BTrace::EFlagsIndex]&BTrace::EHeader2Present))
+		return EFalse;
+	TUint32 header2 = *ptr++;
+	if(aData[BTrace::EFlagsIndex]&BTrace::ETimestampPresent)
+		++ptr;
+	if(aData[BTrace::EFlagsIndex]&BTrace::ETimestamp2Present)
+		++ptr;
+
+	if(aData[BTrace::EFlagsIndex]&BTrace::EContextIdPresent)
+		++ptr;
+	if(aData[BTrace::EFlagsIndex]&BTrace::EPcPresent)
+		++ptr;
+
+	if(!(aData[BTrace::EFlagsIndex]&BTrace::EExtraPresent))
+		return EFalse;
+	TUint id = *ptr++;
+
+	if(*ptr++ != aOutSize)
+		return EFalse;
+
+	if(aOffset && *ptr++ != aOffset)
+		return EFalse;
+
+	TInt size = aData[BTrace::ESizeIndex]-((TInt)ptr-(TInt)aData);
+	TUint8* data = (TUint8*)ptr;
+	TUint8* out = (TUint8*)KTestTrace1+4+aOffset;
+
+	if(!aOffset)
+		{
+		if((header2&BTrace::EMultipartFlagMask) != BTrace::EMultipartFirst)
+			return EFalse;
+		BigTraceId = id;
+		aOffset += size-4-aExtraIds;
+		BigTraceFirst = ETrue;
+		}
+	else
+		{
+		if(id!=BigTraceId)
+			return EFalse;
+		aOffset += size;
+		out += 4 + aExtraIds;
+		if(aOffset==aOutSize)
+			{
+			if((header2&BTrace::EMultipartFlagMask) != BTrace::EMultipartLast)
+				return EFalse;
+			BigTraceEnd = ETrue;
+			}
+		else
+			{
+			if((header2&BTrace::EMultipartFlagMask) != BTrace::EMultipartMiddle)
+				return EFalse;
+			BigTraceMiddle = ETrue;
+			}
+		}
+	if(aOffset>aOutSize)
+		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<TUint32(aOutSize))
+			if(!DoCheckBigTrace1(aData,aOutSize,aOffset,aExtraIds))
+				return EFalse;
+		aData = (TUint8*)(((TInt)aData+3)&~3);
+		if(aData != end)
+			return EFalse;
+		}
+	return ETrue;
+	}
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBASE-T_BTRACE-0061
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1030
+//! @SYMTestCaseDesc Test Big (mutipart) kernel traces.
+//! @SYMTestActions Generate traces from kernel code using the BTraceBig,
+//!		BTracePcBig, BTraceContextBig and BTraceContextPcBig macros.
+//! @SYMTestExpectedResults Traces where broken down into mutiple 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 Implemented
+//---------------------------------------------
+void TestBig(TBool aUserTrace, TBool aFilter2)
+	{
+	test.Start(_L("Reset trace buffer"));
+	TInt oldSize = Trace.BufferSize();
+	TInt r = Trace.ResizeBuffer(0x100000);
+	test_KErrNone(r);
+	Trace.SetMode(RBTrace::EEnable);
+
+	// 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;
+		}
+
+	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;
+			}
+
+		test.Start(_L("Big traces without special context"));
+		TInt i;
+		for(i=minSize; i<=(TInt)sizeof(KTestTrace1)-4; i++)
+			{
+			TestTrace1(RBTraceTest::EBigTrace|extraFlags,i);
+
+			TUint8* data;
+			TInt size;
+			size = Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+			test(CheckBigTrace1(data,size,i,KTest1SubCategory));
+			Trace.DataUsed();
+			}
+
+		test.Next(_L("Big traces with PC"));
+		BigTraceBeginTest();
+		for(i=minSize; i<=(TInt)sizeof(KTestTrace1)-4; i++)
+			{
+			TraceTest.Trace(RBTraceTest::EBigTrace|BTrace::EPcPresent|extraFlags,KTestTrace1,i);
+
+			TUint8* data;
+			TUint8* data2;
+			TInt size;
+			size=Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+			size /= 2;
+			data2 = data+size;
+
+			test(CheckBigTrace1(data,size,i,KTest1SubCategory));
+			test(CheckBigTrace1(data2,size,i,KTest1SubCategory));
+
+			test(!(data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+			test((data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+			TInt offset = ContextOffset(data);
+			test( ((TUint32*)(data+offset))[0] != ((TUint32*)(data2+offset))[0]);
+
+			Trace.DataUsed();
+			}
+		test_Equal(expectTrace,BigTraceEndTest()); // check we actually got mutilpart traces
+
+		test.Next(_L("Big traces with Context ID"));
+		BigTraceBeginTest();
+		for(i=minSize; i<=(TInt)sizeof(KTestTrace1)-4; i++)
+			{
+			TestTrace1(RBTraceTest::EBigTrace|BTrace::EContextIdPresent|extraFlags,i);
+
+			TUint8* data;
+			TUint8* data2;
+			TInt size;
+			size=Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+			size /= 2;
+			data2 = data+size;
+
+			test(CheckBigTrace1(data,size,i,KTest1SubCategory));
+			test(CheckBigTrace1(data2,size,i,KTest1SubCategory));
+
+			test((data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+			test(!(data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+			TUint offset = ContextOffset(data);
+			test_Equal(ThisTraceContextId, ((TUint32*)(data+offset))[0]);
+			test_Equal(ThisTraceContextId, ((TUint32*)(data2+offset))[0]);
+
+			Trace.DataUsed();
+			}
+		test_Equal(expectTrace,BigTraceEndTest()); // check we actually got mutilpart traces
+
+		test.Next(_L("Big traces with Context ID and PC"));
+		BigTraceBeginTest();
+		for(i=minSize; i<=(TInt)sizeof(KTestTrace1)-4; i++)
+			{
+			TestTrace1(RBTraceTest::EBigTrace|BTrace::EContextIdPresent|BTrace::EPcPresent|extraFlags,i);
+
+			TUint8* data;
+			TUint8* data2;
+			TInt size;
+			size=Trace.GetData(data);
+			if(!expectTrace)
+				{
+				test(!size);
+				continue;
+				}
+			size /= 2;
+			data2 = data+size;
+
+			test(CheckBigTrace1(data,size,i,KTest1SubCategory));
+			test(CheckBigTrace1(data2,size,i,KTest1SubCategory));
+
+			test((data[BTrace::EFlagsIndex]&BTrace::EContextIdPresent));
+			test((data[BTrace::EFlagsIndex]&BTrace::EPcPresent));
+
+			TUint offset = ContextOffset(data);
+			test_Equal(ThisTraceContextId, ((TUint32*)(data+offset))[0] );
+			test_Equal(ThisTraceContextId, ((TUint32*)(data2+offset))[0] );
+			test_Compare( ((TUint32*)(data+offset))[1], != ,((TUint32*)(data2+offset))[1]);
+
+			Trace.DataUsed();
+			}
+		test_Equal(expectTrace,BigTraceEndTest()); // check we actually got mutilpart traces
+		test.End();
+		}
+
+	test.Next(_L("Restore buffer"));
+	r = Trace.ResizeBuffer(oldSize);
+	test_KErrNone(r);
+	Trace.SetFilter2(0);
+
+	test.End();
+	}
+
+
+TUint MainThreadTraceId = 0;
+
+//---------------------------------------------
+//! @SYMTestCaseID KBASE-T_BTRACE-0064
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1030
+//! @SYMTestCaseDesc Test BTrace category EThreadIdentification.
+//! @SYMTestActions Enable the EThreadIdentification trace category, causing it to be 'primed'.
+//!		Rename a thread and a process, then create and destory a thread.
+//!		No actions are performed if the kernel doesn't support this trace category.
+//! @SYMTestExpectedResults All test actions produced traces and their contents matched
+//!		the expected results.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void TestThreadIdentification()
+	{
+	if(KErrNotSupported==Trace.Filter(BTrace::EThreadIdentification))
+		{
+		test.Start(_L("Trace category not supported by this build of kernel."));
+		test.End();
+		return;
+		}
+
+	TBuf8<KMaxKernelName> threadName = RThread().Name().Collapse();
+	TUint threadId = RThread().Id();
+	TBuf8<KMaxKernelName> 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<end; data=BTrace::NextRecord(data))
+		if(data[BTrace::ECategoryIndex]==BTrace::EThreadIdentification)
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EProcessName)
+				if(processName==Text(data))
+					{
+					processTraceId = Body(data)[1];
+					break;
+					}
+	test_Compare(data, < , end);
+	for(; data<end; data=BTrace::NextRecord(data))
+		if(data[BTrace::ECategoryIndex]==BTrace::EThreadIdentification)
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EThreadName)
+				if(processTraceId==Body(data)[1])
+					if(threadName==Text(data))
+						{
+						threadTraceId = Body(data)[0];
+						break;
+						}
+	test_Compare(data, < , end);
+	for(; data<end; data=BTrace::NextRecord(data))
+		if(data[BTrace::ECategoryIndex]==BTrace::EThreadIdentification)
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EThreadId)
+				if(threadTraceId==Body(data)[0])
+					if(processTraceId==Body(data)[1])
+						if(threadId==Body(data)[2])
+							{
+							break;
+							}
+	test_Compare(data, < ,end);
+	Trace.DataUsed();
+	MainThreadTraceId = threadTraceId;
+
+	test.Next(_L("Test thread rename traces"));
+	test_KErrNone(User::RenameThread(_L("t_btrace-main")));
+	threadName = RThread().Name().Collapse();
+	size=Trace.GetData(data);
+	test_NotNull(size);
+	end = data+size;
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::EThreadName, data[BTrace::ESubCategoryIndex]);
+	test_Equal(threadTraceId, Body(data)[0]);
+	test_Equal(processTraceId, Body(data)[1]);
+	test(threadName==Text(data));
+	data=BTrace::NextRecord(data);
+	test(data==end);
+	Trace.DataUsed();
+
+	test.Next(_L("Test process rename traces"));
+	test_KErrNone(User::RenameProcess(_L("T_BTRACE-renamed")));
+	processName = RProcess().Name().Collapse();
+	size=Trace.GetData(data);
+	test_NotNull(size);
+	end = data+size;
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::EProcessName ,data[BTrace::ESubCategoryIndex]);
+	test_Equal(processTraceId, Body(data)[1]);
+	test(processName==Text(data));
+	data=BTrace::NextRecord(data);
+	test(data==end);
+	Trace.DataUsed();
+
+	test.Next(_L("Test thread creation traces"));
+	RThread thread;
+	test_KErrNone(thread.Create(KNullDesC,0,0x1000,&User::Allocator(),0));
+	threadName = thread.Name().Collapse();
+	threadId = thread.Id();
+	size=Trace.GetData(data);
+	test_NotNull(size);
+	end = data+size;
+
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::ENanoThreadCreate ,data[BTrace::ESubCategoryIndex]);
+	threadTraceId = Body(data)[0];
+	data=BTrace::NextRecord(data);
+	test_Compare(data, < ,end);
+
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::EProcessName ,data[BTrace::ESubCategoryIndex]);
+	test_Equal(processTraceId, Body(data)[1]);
+	test(processName==Text(data));
+	data=BTrace::NextRecord(data);
+	test_Compare(data, < ,end);
+
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::EThreadCreate ,data[BTrace::ESubCategoryIndex]);
+	test_Equal(threadTraceId, Body(data)[0]);
+	processTraceId = Body(data)[1];
+	test(threadName==Text(data));
+	data=BTrace::NextRecord(data);
+	test_Compare(data, < ,end);
+
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::EThreadId ,data[BTrace::ESubCategoryIndex]);
+	test_Equal(threadTraceId, Body(data)[0]);
+	test_Equal(processTraceId, Body(data)[1]);
+	test(threadId==Body(data)[2]);
+	data=BTrace::NextRecord(data);
+	test_Equal(data,end);
+	Trace.DataUsed();
+
+	test.Next(_L("Test thread destruction traces"));
+	thread.Kill(0);
+	User::After(100000);
+	size=Trace.GetData(data);
+	test_NotNull(size);
+	end = data+size;
+
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::ENanoThreadDestroy ,data[BTrace::ESubCategoryIndex]);
+	test_Equal(threadTraceId, Body(data)[0]);
+	data=BTrace::NextRecord(data);
+	test_Compare(data, < ,end);
+
+	test_Equal(BTrace::EThreadIdentification,data[BTrace::ECategoryIndex]);
+	test_Equal(BTrace::EThreadDestroy ,data[BTrace::ESubCategoryIndex]);
+	test_Equal(threadTraceId, Body(data)[0]);
+	test_Equal(processTraceId, Body(data)[1]);
+	test(threadId==Body(data)[2]);
+	data=BTrace::NextRecord(data);
+	test_Equal(data,end);
+	Trace.DataUsed();
+
+	test.Next(_L("Cleanup after tests"));
+	Trace.SetFilter(BTrace::EThreadIdentification,0);
+	Trace.SetMode(0);
+	r = Trace.ResizeBuffer(oldSize);
+	test_KErrNone(r);
+
+	test.End();
+	}
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBASE-T_BTRACE-0065
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1030
+//! @SYMTestCaseDesc Test BTrace category ECpuUsage.
+//! @SYMTestActions Enable the ECpuUsage trace category for one second, then obtain captured
+//!		traces using RBTrace.
+//! @SYMTestExpectedResults Traces are generated for the sub-categories EIrqStart, EIDFCStart,
+//!		EIDFCEnd and ENewThreadContext. The later must include the context ID of the main test
+//!		program thread.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void TestCpuUsage()
+	{
+	if(KErrNotSupported==Trace.Filter(BTrace::ECpuUsage))
+		{
+		test.Start(_L("Trace category 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.SetMode(RBTrace::EEnable);
+
+	test.Next(_L("Generate traces for a short time..."));
+	Trace.SetFilter(BTrace::ECpuUsage,1);
+	User::After(1000*1000);
+	Trace.SetFilter(BTrace::ECpuUsage,0);
+
+	test.Next(_L("Process traces"));
+	TUint8 subCategories[256] = {0};
+	TUint8* data;
+	TInt size;
+	while((size=Trace.GetData(data))!=0)
+		{
+		TUint8* end = data+size;
+		for( ; data<end; data=BTrace::NextRecord(data))
+			{
+			test_Equal(BTrace::ECpuUsage,data[BTrace::ECategoryIndex]);
+			TUint subCategory = data[BTrace::ESubCategoryIndex];
+			TUint8* context = data+ContextOffset(data);
+			TUint8* recordEnd = BTrace::NextRecord(data);
+			if(subCategory==BTrace::ENewThreadContext)
+				{
+				test_Equal(context+4, recordEnd); // trace record should end after context data
+				if(*(TUint32*)context != MainThreadTraceId)
+					continue; // not a context switch to this thread
+				}
+			else if (subCategory==BTrace::EIrqStart || subCategory==BTrace::EFiqStart)
+				{
+				// may or may not contain vector number
+				if (recordEnd != context)
+					{
+					test_Equal(context+4, recordEnd);
+					}
+				}
+			else
+				{
+				test_Equal(context, recordEnd); // trace record should have no context or any data after
+				}
+			subCategories[subCategory] = 1; // set flag to say we've seen this kind of trace
+			}
+		Trace.DataUsed();
+		}
+
+	test.Next(_L("Check for expected traces"));
+	// timer interrupts should have generated IRQ traces...
+	test(subCategories[BTrace::EIrqStart]);
+	 // User::After should have caused timer interrupt to queue a DFC...
+	test(subCategories[BTrace::EIDFCStart]);
+	test(subCategories[BTrace::EIDFCEnd]);
+	// Current thread must have got scheduled again...
+	test(subCategories[BTrace::ENewThreadContext]);
+
+	test.Next(_L("Cleanup after tests"));
+	Trace.SetFilter(BTrace::ECpuUsage,0);
+	Trace.SetMode(0);
+	r = Trace.ResizeBuffer(oldSize);
+	test_KErrNone(r);
+
+	test.End();
+	}
+
+
+volatile TBool SoakDone = EFalse; // always false, but stops compiler warnings in SoakThreadFunction
+
+RThread SoakThread[4];
+
+TInt SoakThreadFunction(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);
+
+		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<end; data=BTrace::NextRecord(data))
+		{
+		if(data[BTrace::ECategoryIndex]==BTrace::EChunks)
+			{
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EChunkCreated)
+				{
+				found_chunk_create=1;
+				chunk_ptr = Body(data)[0];
+				}
+			}
+		if(data[BTrace::ECategoryIndex]==BTrace::EHeap)
+			{
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EHeapCreate)
+				found_heap_create=1;
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EHeapChunkCreate)
+				{
+				found_heap_chunk_create=1;
+				heap_chunk_ptr = Body(data)[1];
+				}
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EHeapAlloc)
+				{
+				if(Body(data)[1]==(TUint)threadtest.alloc_addr)
+					{
+					found_heap_alloc=1;
+					test_Equal(4, Body(data)[2]);
+					test_Compare(Body(data)[3], >= ,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<end; data=BTrace::NextRecord(data))
+		{
+		if(data[BTrace::ECategoryIndex]==BTrace::EChunks)
+			{
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EChunkCreated)
+				{
+				test_Equal(4*1024*1024, Body(data)[1]);
+				found_chunk_create = 1;
+				}
+			if(data[BTrace::ESubCategoryIndex]==BTrace::EChunkMemoryAllocated)
+				{
+				test_Equal(4096, Body(data)[2]);
+				found_heap_alloc = 1;
+				}
+			}
+		}
+	test(found_heap_alloc && found_chunk_create);
+	Trace.DataUsed();
+
+	test.Next(_L("Cleanup after tests"));
+	Trace.SetFilter(BTrace::EHeap,0);
+	Trace.SetMode(0);
+	r = Trace.ResizeBuffer(oldSize);
+	test_KErrNone(r);
+
+	test.End();
+	}
+
+void SetBTraceFilter(const TUint32* aNew,TUint32* aOld)
+	{
+	TUint category = 0;
+	do
+		{
+		TUint32 newBits = *aNew++;
+		TUint32 oldBits = 0;
+		do
+			{
+			oldBits >>= 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<TInt32> 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<end; data=BTrace::NextRecord(data))
+		{
+		if(data[BTrace::ECategoryIndex]==BTrace::EHeap)
+			if(data[BTrace::ESubCategoryIndex]==subCat)
+				{
+				found_heap_allocfail = 1;
+				TInt allocfail_data_size = ((TInt)data[BTrace::ESizeIndex]) - ExtraSize(data);
+				test_Equal(allocfail_data_size,expectedDataSize);
+				break; //we're looking only for one record
+				}
+		}
+	test(found_heap_allocfail);
+
+	//closing trace
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+	Trace.Close();
+	}
+
+
+bool FindHeapCorruptionTrace(TUint8* aData, TInt aSize, TInt& aFoundSize)
+	{
+	TUint8* end = aData+aSize;
+	TUint8* data;
+	for(data=aData; data<end; data=BTrace::NextRecord(data))
+		{
+		if(data[BTrace::ECategoryIndex] == BTrace::EHeap)
+			if(data[BTrace::ESubCategoryIndex] == BTrace::EHeapCorruption)
+				{
+				aFoundSize = data[BTrace::ESizeIndex] - ExtraSize(data);
+				return true;
+				}
+		}
+	return false;
+	}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+//! @SYMTestCaseID				KBASE-T_BTRACE-0734
+//! @SYMTestCaseDesc			Test BTrace - EHeapCorruption subcategory.
+//! @SYMTestType				UT
+//! @SYMPREQ					PREQ1340
+//! @SYMTestPriority			Medium
+//! @SYMTestActions
+//! 	1.	Configure BTrace to use EHeap and EThreadIdentification categories.
+//! 	2.	Use test application (t_heapcorruption.exe) with parameters: 1, 2, 3 or 4 to
+//!			to corrupt heap memory (for this application)
+//! 	3.	Get trace data from BTrace and search for trace with category EHeap and
+//!			subcategory EHeapCorruption.
+//!		4.	Validate payload size for found traces.
+//!
+//! @SYMTestExpectedResults
+//! 	1.	Test application (when started with either argument) should generate at least
+//!			one trace with category EHeap and subcategory EHeapCorruption.
+//! 	2.	Trace data payload should be 12 bytes long (3x4 bytes values).
+//---------------------------------------------------------------------------------------------------------------------
+void TestHeapCorruptionEvents()
+	{
+	TInt r = KErrNone;
+	test.Next(_L("Test to check BTrace::EHeap::EHeapCorruption trace events"));
+	//configure BTrace
+	Trace.Open();
+	Trace.SetMode(0);
+	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);
+
+	_LIT(KHeapCorrApp, "t_heapcorruption.exe");
+	_LIT(KCorruption0, "0"); //RHeap:: corruption type (when EMonitorMemory flag is set)
+	_LIT(KCorruption1, "1"); //RHeap::EBadFreeCellAddress corruption type
+	_LIT(KCorruption2, "2"); //RHeap::EBadFreeCellSize corruption type
+	_LIT(KCorruption3, "3"); //RHeap::EBadAllocatedCellSize corruption type
+	_LIT(KCorruption4, "4"); //RHeap::EBadAllocatedCellAddress corruption type
+	_LIT(KCorruptionSpecial1, "1000"); //RHeap::EBadAllocatedCellSize (with EMonitorMemory flag set)
+	RProcess p;
+	TInt e = KErrNone;
+	TRequestStatus status;
+	TUint8* trace;
+	TInt size, payloadSize;
+	bool res;
+
+	//test 0 (for memory monitoring tools - when EMonitorMemory heap flag is set)
+	test.Printf(_L("test 0\n"));
+	Trace.SetMode(RBTrace::EEnable);
+	e = p.Create(KHeapCorrApp, KCorruption0);
+	test_KErrNone(e);
+	p.Resume();
+	p.Logon(status);
+	User::WaitForRequest(status);
+	p.Close();
+	size = Trace.GetData(trace);
+	test_NotNull(size);
+	res = FindHeapCorruptionTrace(trace, size, payloadSize);
+	test(res==true);
+	test(payloadSize == 12); //payload in this case must be 12 bytes long (3x4bytes)
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+
+	//test 1 -
+	test.Printf(_L("test 1\n"));
+	Trace.SetMode(RBTrace::EEnable);
+	e = p.Create(KHeapCorrApp, KCorruption1);
+	test_KErrNone(e);
+	p.Resume();
+	p.Logon(status);
+	User::WaitForRequest(status);
+	p.Close();
+	size = Trace.GetData(trace);
+	test_NotNull(size);
+	res = FindHeapCorruptionTrace(trace, size, payloadSize);
+	test(res==true);
+	test(payloadSize == 12); //payload in this case must be 12 bytes long (3x4bytes)
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+
+	//test 2
+	test.Printf(_L("test 2\n"));
+	Trace.SetMode(RBTrace::EEnable);
+	e = p.Create(KHeapCorrApp, KCorruption2);
+	test_KErrNone(e);
+	p.Resume();
+	p.Logon(status);
+	User::WaitForRequest(status);
+	p.Close();
+	size = Trace.GetData(trace);
+	test_NotNull(size);
+	res = FindHeapCorruptionTrace(trace, size, payloadSize);
+	test(res==true);
+	test(payloadSize == 12); //payload in this case must be 12 bytes long (3x4bytes)
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+
+	//test 3
+	test.Printf(_L("test 3\n"));
+	Trace.SetMode(RBTrace::EEnable);
+	e = p.Create(KHeapCorrApp, KCorruption3);
+	test_KErrNone(e);
+	p.Resume();
+	p.Logon(status);
+	User::WaitForRequest(status);
+	p.Close();
+	size = Trace.GetData(trace);
+	test_NotNull(size);
+	res = FindHeapCorruptionTrace(trace, size, payloadSize);
+	test(res==true);
+	test(payloadSize == 12); //payload in this case must be 12 bytes long (3x4bytes)
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+
+	//test 4
+	test.Printf(_L("test 4\n"));
+	Trace.SetMode(RBTrace::EEnable);
+	e = p.Create(KHeapCorrApp, KCorruption4);
+	test_KErrNone(e);
+	p.Resume();
+	p.Logon(status);
+	User::WaitForRequest(status);
+	p.Close();
+	size = Trace.GetData(trace);
+	test_NotNull(size);
+	res = FindHeapCorruptionTrace(trace, size, payloadSize);
+	test(res==true);
+	test(payloadSize == 12); //payload in this case must be 12 bytes long (3x4bytes)
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+
+	//test 5 (test ____MEMORY_MONITOR_CHECK_CELL macro)
+	test.Printf(_L("test 5\n"));
+	Trace.SetMode(RBTrace::EEnable);
+	e = p.Create(KHeapCorrApp, KCorruptionSpecial1);
+	test_KErrNone(e);
+	p.Resume();
+	p.Logon(status);
+	User::WaitForRequest(status);
+	p.Close();
+	size = Trace.GetData(trace);
+	test_NotNull(size);
+	res = FindHeapCorruptionTrace(trace, size, payloadSize);
+	test(res==true);
+	test(payloadSize == 12); //payload in this case must be 12 bytes long (3x4bytes)
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+
+	//closing trace
+	Trace.DataUsed();
+	Trace.Empty();
+	Trace.SetMode(0);
+	Trace.Close();
+	}
+
+
+//Set up utrace
+TUint32 KUtracePcValues[3]={0, 0x123456, 0x987654};
+
+#define T_UTRACE_HEADER(aSize,aClassification,aContext,aPc)																\
+	((((aSize) + (aContext?4:0) + (aPc?4:0)) << BTrace::ESizeIndex*8)										\
+	+(((aContext?BTrace::EContextIdPresent:0) | (aPc?BTrace::EPcPresent:0)) << BTrace::EFlagsIndex*8)			\
+	+((aClassification) << BTrace::ECategoryIndex*8)																				\
+	+((KTest1SubCategory) << BTrace::ESubCategoryIndex*8))
+
+#define UTRACE_SECONDARY(aClassification,aModuleUid,aThreadIdPresent,aPcPresent,aPc,aFormatId)	\
+	BTrace::OutFilteredPcFormatBig(T_UTRACE_HEADER(8,aClassification,aThreadIdPresent,aPcPresent),(TUint32)(aModuleUid),aPc,aFormatId,0,0)
+
+#define UTRACE_SECONDARY_4(aClassification,aModuleUid,aThreadIdPresent,aPcPresent,aPc,aFormatId, aData1) \
+	BTrace::OutFilteredPcFormatBig(T_UTRACE_HEADER(8,aClassification,aThreadIdPresent,aPcPresent),(TUint32)(aModuleUid),aPc,aFormatId,&aData1,4)
+
+#define UTRACE_SECONDARY_ANY(aClassification, aModuleUid, aThreadIdPresent, aPcPresent, aPc, aFormatId, aData, aDataSize) \
+	BTrace::OutFilteredPcFormatBig(T_UTRACE_HEADER(8,aClassification,aThreadIdPresent,aPcPresent),(TUint32)(aModuleUid),aPc,aFormatId,aData,(TInt)(aDataSize))
+
+void UTraceUserBenchmark(TUint& aTime1,TUint& aTime2,TUint& aTime3,TBool aTraceEnabled)
+	{
+	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;
+	TUint32* frm = (TUint32*)KTestTrace1;
+	TUint16 formatId = (TUint16)frm[2];
+
+	do
+		{
+		UTRACE_SECONDARY(BTrace::ETest1,KBTraceFilterTestUid1,EFalse,EFalse,0,formatId);
+		++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;
+	do
+		{
+		//BTraceFilteredContextN(BTrace::ETest1,0,KBTraceFilterTestUid1,0,KTestTrace1,KMaxBTraceDataArray);
+		UTRACE_SECONDARY_ANY(BTrace::ETest1,KBTraceFilterTestUid1,ETrue,EFalse,0,formatId,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;
+	do
+		{
+		check = BTrace::CheckFilter2(BTrace::ETest1,KBTraceFilterTestUid1);
+		++r;
+		}
+	while(status==KRequestPending);
+	test(check == aTraceEnabled);
+	aTime3 = 1000000000/r;
+
+	r = Trace.ResizeBuffer(oldSize);
+	test_KErrNone(r);
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID 		KBASE-T_BTRACE-2442
+//! @SYMTestType 		UT
+//! @SYMPREQ 			CR1623
+//! @SYMTestCaseDesc 	Benchmark utracing.
+//! @SYMTestActions 	Time the generation of minimum and maximum sized utraces 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 		Prototype
+//---------------------------------------------
+void TestUtraceBenchmark(TBool aUserTrace)
+	{
+	TUint t1 = 0;
+	TUint t2 = 0;
+	TUint t3 = 0;
+//This uses btrace kernel benching atm, need to change once kernel is implemented
+#define UBENCH(a1) aUserTrace ? UTraceUserBenchmark(t1,t2,t3,a1) : KernelBenchmark(t1,t2,t3,a1,1)
+
+	test.Printf(_L("                                      Min Trace   Max Trace      Filter\n"));
+
+	Trace.SetFilter(BTrace::ETest1,0);
+	Trace.SetFilter2(0);
+	UBENCH(0);
+	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);
+	UBENCH(0);
+	test.Printf(_L("filter1 on    global filter2 off      %6d ns   %6d ns   %6d ns\n"),t1,t2,t3);
+
+	Trace.SetFilter2(1);
+	UBENCH(1);
+	test.Printf(_L("filter1 on    global filter2 on       %6d ns   %6d ns   %6d ns\n"),t1,t2,t3);
+
+	Trace.SetFilter2(&KBTraceFilterTestUid2,1);
+	UBENCH(0);
+	test.Printf(_L("filter1 on    1 UID filter2 off       %6d ns   %6d ns   %6d ns\n"),t1,t2,t3);
+
+	Trace.SetFilter2(&KBTraceFilterTestUid1,1);
+	UBENCH(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);
+	UBENCH(0);
+	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));
+	UBENCH(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);
+	}
+
+
+void CallUtrace(TBool aType, TBool aContextPresent, TBool aPcPresent, TInt aSizeOfData)
+	{
+	if(!(aType&RBTraceTest::EUserTrace))
+		{
+		// use driver to create a kernel trace...
+		TraceTest.Trace(aType,KTestTrace1,aSizeOfData);
+		return;
+		}
+
+	TUint32* data = (TUint32*)KTestTrace1;
+	TUint16 formatId = (TUint16)data[2];
+	//multiparted traces (depending on size)
+	if(aSizeOfData <= 0)
+		{
+		UTRACE_SECONDARY(BTrace::ETest1, KBTraceFilterTestUid1, aContextPresent, aPcPresent, KUtracePcValues[1], formatId);
+		UTRACE_SECONDARY(BTrace::ETest1, KBTraceFilterTestUid1, aContextPresent, aPcPresent, KUtracePcValues[2], formatId);
+		}
+	else if(aSizeOfData <= 4)
+		{
+		UTRACE_SECONDARY_4(BTrace::ETest1, KBTraceFilterTestUid1, aContextPresent, aPcPresent, KUtracePcValues[1], formatId, data[3]);
+		UTRACE_SECONDARY_4(BTrace::ETest1, KBTraceFilterTestUid1, aContextPresent, aPcPresent, KUtracePcValues[2], formatId, data[3]);
+		}
+	else //aSizeOfData > 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<sizeof(KTestTrace1); i++)
+		{
+		KTestTrace1[i] = (TUint8)i;
+		KTestTrace2[i] = (TUint8)~i;
+		}
+	KTestTrace1[4] = (KBTraceFilterTestUid1>>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<KNumBTraceFilterTestUids; i++)
+		BigFilter2[i] = KBTraceFilterTestUid+i;
+
+	test.Title();
+	TInt r;
+
+	test.Start(_L("Open LDD"));
+	r = Trace.Open();
+	test_KErrNone(r);
+
+	test.Next(_L("Open test LDD"));
+	r = User::LoadLogicalDevice(RBTraceTest::Name());
+	test(r==KErrNone || r==KErrAlreadyExists);
+	r = TraceTest.Open();
+	test_KErrNone(r);
+
+	// save trace settings...
+	TUint savedMode = Trace.Mode();
+	SetBTraceFilter(OldTraceFilter,OldTraceFilter);
+
+	TBuf<256> 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);
+    }
+