dbgsrv/coredumpserver/test/automatictests/tcds_unit/src/cds/CFlashDataSourceWrapper.cpp
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "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:
//
/**
@file CFlashDataSourceWrapper.cpp
@internalTechnology
*/
#include "CFlashDataSourceWrapper.h"
using namespace Debug;
//Names of functions to be tested - referenced from script file
_LIT(KNewL_Debug, "NewL");
_LIT(KReadCrashLog, "ReadCrashLog");
_LIT(KGetFlashBuffer, "GetFlashBuffer");
_LIT(KProcessCrashHeader1, "ProcessCrashHeader1");
_LIT(KProcessCrashHeader2, "ProcessCrashHeader2");
_LIT(KGetProcessListL1, "GetProcessListL1");
_LIT(KGetProcessListL2, "GetProcessListL2");
_LIT(KGetThreadListL1, "GetThreadListL1");
_LIT(KGetThreadListL2, "GetThreadListL2");
_LIT(KGetThreadListL3, "GetThreadListL3");
_LIT(KReadRegistersL1, "ReadRegistersL1");
_LIT(KReadMemoryL1, "ReadMemoryL1");
_LIT(KReadMemoryL2, "ReadMemoryL2");
_LIT(KGetCodeSegmentsL1, "GetCodeSegmentsL1");
_LIT(KGetCodeSegmentsL2, "GetCodeSegmentsL2");
_LIT(KGetCodeSegmentsL3, "GetCodeSegmentsL3");
_LIT(KReadTraceBufferL1, "ReadTraceBufferL1");
_LIT(KReadTraceBufferL2, "ReadTraceBufferL2");
_LIT(KCalcChecksum, "CalcChecksum");
_LIT(KTraceDataSize, "TraceDataSize");
_LIT(KTraceDataSizeNotFound, "TraceDataSizeNotFound");
_LIT8(KCrashDummyData, "This is a sample write");
const TInt FLASH_ALIGN = sizeof(TInt32);
const TInt START_OF_FLASH = 0;
/**
* Constructor for test wrapper
*/
CFlashDataSourceWrapper::CFlashDataSourceWrapper()
:iObject(NULL)
{
}
/**
* Destructor
*/
CFlashDataSourceWrapper::~CFlashDataSourceWrapper()
{
}
/**
* Two phase constructor for CFlashDataSourceWrapper
* @return CFlashDataSourceWrapper object
* @leave
*/
CFlashDataSourceWrapper* CFlashDataSourceWrapper::NewL()
{
CFlashDataSourceWrapper* ret = new (ELeave) CFlashDataSourceWrapper();
CleanupStack::PushL(ret);
ret->ConstructL();
CleanupStack::Pop(ret);
return ret;
}
/**
* Safe construction
* @leave
*/
void CFlashDataSourceWrapper::ConstructL()
{
}
/**
* Assign the object
*
* @param aObject TAny* to the object to test
* @leave
*/
void CFlashDataSourceWrapper::SetObjectL(TAny* aObject)
{
delete iObject;
iObject = NULL;
iObject = static_cast<CFlashDataSource*> (aObject);
}
/**
* Runs a test preamble
*/
void CFlashDataSourceWrapper::PrepareTestL()
{
SetBlockResult(EPass);
INFO_PRINTF1(_L("Connecting to DSS"));
//get a session to the security server
User::LeaveIfError(iSecSess.Connect(securityServerVersion));
INFO_PRINTF1(_L("Erasing crash log"));
User::LeaveIfError(iSecSess.EraseCrashLog(0, 1));
INFO_PRINTF1(_L("Creating data source"));
//Hackage: TEF doesnt support preamble/postamble and destructs iObject each time. Until they sort it out
//or document how it is done the hackage shall have to continue. Oh for JUnit....
delete iObject; //to be sure
iObject = CFlashDataSource::NewL(iSecSess);
//end of hackage
INFO_PRINTF1(_L("Ready to start test"));
}
/**
* Process command to see what test to run
*/
TBool CFlashDataSourceWrapper::DoCommandL(const TTEFFunction& aCommand, const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
{
__UHEAP_MARK;
PrepareTestL();
if (KNewL_Debug() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::NewL()");
TRAPD(err , DoCmdCrashFlashDataSource_NewL_TestL());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed!");
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if (KReadCrashLog() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::ReadCrashLog()");
TRAPD(err , DoCmd_ReadCrashLog_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if (KGetFlashBuffer() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::GetFlashBuffer()");
TRAPD(err , DoCmd_GetFlashBuffer_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if (KProcessCrashHeader1() == aCommand)
{
TRAPD(err , DoCmd_ProcessCrashHeader1_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if (KProcessCrashHeader2() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::ProcessCrashHeader() - 2nd test");
TRAPD(err , DoCmd_ProcessCrashHeader2_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KGetProcessListL1() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::GetProcessListL() - 1st test");
TRAPD(err , DoCmd_GetProcessListL1_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if ( KGetProcessListL2() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::GetProcessListL() - 2nd test");
TRAPD(err , DoCmd_GetProcessListL2_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if (KGetThreadListL1() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::GetThreadListL() - 1st test");
TRAPD(err , DoCmd_GetThreadListL1_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KGetThreadListL2() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::GetThreadListL() - 2nd test");
TRAPD(err , DoCmd_GetThreadListL2_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KGetThreadListL3() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::GetThreadListL() - 3rd test");
TRAPD(err , DoCmd_GetThreadListL3_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KReadRegistersL1() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::ReadRegistersL() - 1st test");
TRAPD(err , DoCmd_ReadRegistersL1_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KReadMemoryL1() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::ReadMemoryL() - 1st test");
TRAPD(err , DoCmd_ReadMemoryL1_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KReadMemoryL2() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::ReadMemoryL() - 2nd test");
TRAPD(err , DoCmd_ReadMemoryL2_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KGetCodeSegmentsL1() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource::GetCodeSegmentsL() - 1st test");
TRAPD(err , DoCmd_GetCodeSegmentsL1_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KGetCodeSegmentsL2() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource - Code Segment Analysis - 2nd test");
TRAPD(err , DoCmd_GetCodeSegmentsL2_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KGetCodeSegmentsL3() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource - Code Segment Analysis - 3rd test");
TRAPD(err , DoCmd_GetCodeSegmentsL3_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if( KReadTraceBufferL1() == aCommand)
{
RDebug::Printf("Looking at CFlashDataSource - Trace Buffer - 1st test");
TRAPD(err , DoCmd_ReadTraceBufferL1_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
INFO_PRINTF2(_L("Failed with err = [%d]"), err);
SetBlockResult(EFail);
}
}
else if(KCalcChecksum() == aCommand)
{
TRAPD(err , DoCmd_CalculateChecksum_TestL());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
}
}
else if(KTraceDataSizeNotFound() == aCommand)
{
TRAPD(err , DoCmd_TraceDataSizeNotFoundL_TestL());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
}
}
else if(KTraceDataSize() == aCommand)
{
TRAPD(err , DoCmd_TraceDataSizeL_TestL());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
}
}
else if(KReadTraceBufferL2() == aCommand)
{
TRAPD(err , DoCmd_ReadTraceBufferL2_Test_L());
if(BlockResult() != EPass || KErrNone != err)
{
RDebug::Printf("\tFailed! [%d]", err);
}
}
else
{
RDebug::Printf("Not found");
delete iObject;
iSecSess.Close();
__UHEAP_MARKEND;
return EFalse;
}
delete iObject;
iSecSess.Close();
__UHEAP_MARKEND;
return ETrue;
}
/**
* This tests that we can succesfully construct
* @leave
*/
void CFlashDataSourceWrapper::DoCmdCrashFlashDataSource_NewL_TestL()
{
//first we delete the CFlashDataSource created by our post amble to ensure we are testing a fresh object
delete iObject;
SetBlockResult(EPass);
INFO_PRINTF1(_L("Testing: CFlashDataSource::NewL()"));
//Try to create a flash data source object
TRAPD(err, iObject = CFlashDataSource::NewL(iSecSess));
//Check errors
if(KErrNone != err)
{
ERR_PRINTF2(_L("Leave when creating CFlashDataSource: [%d]"),err);
SetBlockResult(EFail);
}
//make sure its not null
if(!iObject)
{
ERR_PRINTF1(_L("Problems with creating CFlashDataSource object"));
SetBlockResult(EFail);
}
INFO_PRINTF1(_L("CFlashDataSource object constructed succesfully"));
}
/**
* Tests the ReadCrashLog method on the flash data source
*/
void CFlashDataSourceWrapper::DoCmd_ReadCrashLog_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::ReadCrashLog()"));
//Write some expected data to the flash partition
TUint32 size = 0;
INFO_PRINTF1(_L("Writing dummy data to crash log"));
iSecSess.WriteCrashConfig(START_OF_FLASH, KCrashDummyData, size);
INFO_PRINTF1(_L("Reading dummy data back from crash log"));
TInt err = iObject->ReadCrashLog(START_OF_FLASH, size);
//make sure we got the right data back
if( KErrNone != err || 0 != iObject->GetFlashBuffer().Compare(KCrashDummyData) )
{
ERR_PRINTF2(_L("Failed to read the correct data back via flash data source: Err = [%d]"), err);
SetBlockResult(EFail);
return;
}
//test the parameters
INFO_PRINTF1(_L("Testing that reading from a negative position will fail"));
TInt32 negative = -2;
err = iObject->ReadCrashLog(negative, size);
if(err != KErrArgument)
{
ERR_PRINTF1(_L("We were able to read data from a negative position"));
SetBlockResult(EFail);
return;
}
}
/**
* Tests the flash data source get flash buffer
*/
void CFlashDataSourceWrapper::DoCmd_GetFlashBuffer_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::GetFlashBuffer()"));
//Ensure that the buffer has been created
INFO_PRINTF1(_L("Ensuring the buffer has been succesfully created"));
TDes8& buf = iObject->GetFlashBuffer();
if(KInitialBufferSize != buf.Size())
{
ERR_PRINTF1(_L("Buffer was not created"));
SetBlockResult(EFail);
return;
}
}
/**
* Tests that we correctly process the crash header
*/
void CFlashDataSourceWrapper::DoCmd_ProcessCrashHeader1_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::ProcessCrashHeader() - 1st Test"));
TInt64 tid = 22;
iContextHdr.iNumRegisters = 0;
iInfHdr.iFlashAlign = FLASH_ALIGN;
iInfHdr.iTid = tid;
iInfHdr.iCrashId = CRASH_ID;
TInt logSz = iInfHdr.GetSize() + iContextHdr.GetSize() + iOffsetsHdr.GetSize();
iInfHdr.iLogSize = logSz;
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize + TRegisterSet::KSCMRegisterSetMaxSize + KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
INFO_PRINTF1(_L("Writing header to flash"));
TUint32 size = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data, size));
CleanupStack::PopAndDestroy();
INFO_PRINTF1(_L("Processing crash header"));
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash log: [%d]"), err);
SetBlockResult(EFail);
return;
}
//Read the buffer back
TDes8& buf = iObject->GetFlashBuffer();
INFO_PRINTF1(_L("Ensuring crash header read back is correct"));
//Test our getters work correctly too
if(tid != iObject->GetCrashedThreadId())
{
ERR_PRINTF1(_L("Unable to Get Crashed Thread ID from header"));
SetBlockResult(EFail);
return;
}
if(FLASH_ALIGN != iObject->GetFlashAlignment())
{
ERR_PRINTF1(_L("Unable to Get Correct flash alignment from header"));
SetBlockResult(EFail);
return;
}
if(logSz != iObject->GetCrashLogSize())
{
ERR_PRINTF1(_L("Unable to Get correct log size from header"));
SetBlockResult(EFail);
return;
}
INFO_PRINTF1(_L("All is good. Move along now."));
}
/**
* Negative test to make sure if there is no header we get told so
*/
void CFlashDataSourceWrapper::DoCmd_ProcessCrashHeader2_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::ProcessCrashHeader() - 2nd Test"));
//write a struct that isnt TCrashInfoHeader
TProcessData dummy;
TPtr8 data((TUint8*)&dummy, sizeof(TProcessData), sizeof(TProcessData));
TUint32 size = 0;
INFO_PRINTF1(_L("Writing header to flash"));
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data, size));
INFO_PRINTF1(_L("Processing crash header"));
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNotFound != err)
{
ERR_PRINTF2(_L("Process header should have been corrupt but wasnt [%d]"), err);
SetBlockResult(EFail);
return;
}
}
/**
* Tests we can succesfully read back known processes from flash
*/
void CFlashDataSourceWrapper::DoCmd_GetProcessListL1_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::GetProcessListL() - 1st test"));
//We need to write some process data (will just do 2) to the flash, and update the header with its location
TInt64 p1id = 100;
TInt32 p1prior = 4;
TInt64 p2id = 200;
TInt32 p2prior = 5;
//Process names
_LIT8(KProc1, "t_proc1");
_LIT8(KProc2, "tproc2");
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize + TRegisterSet::KSCMRegisterSetMaxSize + 2 * TProcessData::KSCMProcessDataMaxSize + KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TCrashOffsetsHeader hdr;
hdr.iPLstOffset = sizeof(TCrashInfoHeader) + sizeof(TCrashOffsetsHeader); //starts right after headers
//The first process data
TProcessData proc1;
proc1.iPid = p1id;
proc1.iPriority = p1prior;
proc1.iNamesize = KProc1().Size();
proc1.iName = KProc1;
//The second process data
TProcessData proc2;
proc2.iPid = p2id;
proc2.iPriority = p2prior;
proc2.iNamesize = KProc2().Size();
proc2.iName = KProc2;
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iOffsetsHdr.iPLstOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize(); //starts right after headers
iInfHdr.iLogSize = iOffsetsHdr.iPLstOffset + proc1.GetSize() + proc2.GetSize();
INFO_PRINTF1(_L("Writing known processes to flash"));
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
proc1.Serialize(writer);
proc2.Serialize(writer);
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these processes back via GetProcessListL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
RProcessPointerList *processList = new(ELeave)RProcessPointerList;
TCleanupItem processCleanup(CFlashDataSource::CleanupProcessList, (TAny*)processList);
CleanupStack::PushL(processCleanup);
TUint wr = 0;
INFO_PRINTF1(_L("Getting process list"));
TRAP(err, iObject->GetProcessListL(*processList, wr));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to get process list: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(processList->Count() != 2)
{
ERR_PRINTF2(_L("Didnt find the expected 2 processes. There were [%d] instead"), processList->Count());
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
CProcessInfo* p1 = (*processList)[0];
CProcessInfo* p2 = (*processList)[1];
INFO_PRINTF1(_L("Retrieveing processes"));
if(!p1 || !p2)
{
ERR_PRINTF1(_L("Failed to retrieve non null processes"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
INFO_PRINTF1(_L("Making sure processes are as expected"));
//Check ID's
if(p1->Id() != proc1.iPid || p2->Id() != proc2.iPid)
{
ERR_PRINTF1(_L("Failed to retrieve correct process ID's:"));
ERR_PRINTF3(_L("P1 expected [%d] but found [%d]"), proc1.iPid, p1->Id());
ERR_PRINTF3(_L("P2 expected [%d] but found [%d]"), proc2.iPid, p2->Id());
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
//check names
RBuf wide;
wide.CreateL(KProc1().Size());
wide.CleanupClosePushL();
wide.Copy(KProc1);
INFO_PRINTF1(_L("Checking process 1 name is ok"));
if( p1->Name().Compare(wide) != 0 )
{
ERR_PRINTF3(_L("Wrong name retrieved, expected [%S] but got [%S]"), &KProc1, &wide);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
wide.Copy(KProc2);
INFO_PRINTF1(_L("Checking process 2 name is ok"));
if( p2->Name().Compare(wide) != 0 )
{
ERR_PRINTF3(_L("Wrong name retrieved, expected [%S] but got [%S]"), &KProc2, &wide);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
INFO_PRINTF1(_L("All looks good"));
CleanupStack::PopAndDestroy(3);
}
/**
* Negative tests should the flash contain corrupt data
*/
void CFlashDataSourceWrapper::DoCmd_GetProcessListL2_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::GetProcessList() - 2nd test"));
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize + 3 * TRegisterSet::KSCMRegisterSetMaxSize + KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iOffsetsHdr.iPLstOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize(); //starts right after headers
iInfHdr.iLogSize = iOffsetsHdr.iPLstOffset + 2 * iContextHdr.GetSize();
INFO_PRINTF1(_L("Writing known processes to flash"));
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
iContextHdr.Serialize(writer);
iContextHdr.Serialize(writer);
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
RProcessPointerList *processList = new(ELeave)RProcessPointerList;
TCleanupItem processCleanup(CFlashDataSource::CleanupProcessList, (TAny*)processList);
CleanupStack::PushL(processCleanup);
INFO_PRINTF1(_L("Getting process list"));
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to process header [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
TUint wr = 0;
TRAP(err, iObject->GetProcessListL( *processList, wr));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Should have retrieved zero sized process list"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(processList->Count() != 0)
{
ERR_PRINTF1(_L("Should have retrieved zero sized process list"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
INFO_PRINTF1(_L("Everything is as expected"));
CleanupStack::PopAndDestroy(2);
}
/**
* Tests to make sure we can get back a thread list (two here) from the flash
*/
void CFlashDataSourceWrapper::DoCmd_GetThreadListL1_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::GetThreadListL() 1st Test - System wide thread list"));
//We need to write some thread data (will just do 2) to the flash, and update the header with its location
TInt64 t1id = 100;
TInt32 t1prior = 4;
TInt32 t1SvcSp = 20;
TInt32 t1UsrStkSize = 40;
TInt64 t2id = 200;
TInt32 t2prior = 5;
TInt32 t2SvcSp = 25;
TInt32 t2UsrStkSize = 47;
//thread names
_LIT8(KThread1, "t_thread1");
_LIT8(KThread2, "thread2");
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize + 2 * TThreadData::KSCMThreadDataMaxSize +
KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TInt owner1 = 100;
TInt owner2 = 200;
//The first thread data
TThreadData t1;
t1.iTid = t1id;
t1.iPriority = t1prior;
t1.iSvcSP = t1SvcSp;
t1.iUsrStacksize = t1UsrStkSize;
t1.iNamesize = KThread1().Size();
t1.iName = KThread1;
t1.iOwnerId = owner1;
//The second thread data
TThreadData t2;
t2.iTid = t2id;
t2.iPriority = t2prior;
t2.iSvcSP = t2SvcSp;
t2.iUsrStacksize = t2UsrStkSize;
t2.iNamesize = KThread2().Size();
t2.iName = KThread2;
t2.iOwnerId = owner2;
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iOffsetsHdr.iTLstOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize(); //starts right after headers
iInfHdr.iLogSize = iOffsetsHdr.iTLstOffset + t1.GetSize() + t2.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
t1.Serialize(writer);
t2.Serialize(writer);
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these threads back via GetThreadListL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
RThreadPointerList *threadList = new(ELeave)RThreadPointerList;
TCleanupItem threadCleanup(CFlashDataSource::CleanupThreadList, (TAny*)threadList);
CleanupStack::PushL(threadCleanup);
TUint wr = 0;
INFO_PRINTF1(_L("Getting thread list"));
TRAP(err, iObject->GetThreadListL(((TUint64)-1), *threadList, wr));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to get thread list: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(threadList->Count() != 2)
{
ERR_PRINTF1(_L("Retrieved wrong number of threads"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
CThreadInfo* ti1 = (*threadList)[0];
CThreadInfo* ti2 = (*threadList)[1];
INFO_PRINTF1(_L("Retrieveing threads"));
if(!ti1 || !ti2)
{
ERR_PRINTF1(_L("Failed to retrieve non null threads"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
INFO_PRINTF1(_L("Making sure processes are as expected"));
//Check ID's
if(ti1->Id() != t1.iTid || ti2->Id() != t2.iTid)
{
ERR_PRINTF1(_L("Failed to retrieve correct thread ID's:"));
ERR_PRINTF3(_L("T1 expected [%d] but found [%d]"), t1.iTid, ti1->Id());
ERR_PRINTF3(_L("T2 expected [%d] but found [%d]"), t2.iTid, ti2->Id());
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
//check names
RBuf wide;
wide.CreateL(KThread1().Size());
wide.CleanupClosePushL();
wide.Copy(KThread1);
INFO_PRINTF1(_L("Checking thread 1 name is ok"));
if( ti1->Name().Compare(wide) != 0 )
{
ERR_PRINTF3(_L("Wrong name retrieved, expected [%S] but got [%S]"), &KThread1, &wide);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
if(KThread2().Size() > wide.Size())
{
wide.ReAllocL(KThread2().Size());
}
wide.Copy(KThread2);
INFO_PRINTF1(_L("Checking thread 2 name is ok"));
if( ti2->Name().Compare(wide) != 0 )
{
ERR_PRINTF3(_L("Wrong name retrieved, expected [%S] but got [%S]"), &KThread2, &wide);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
INFO_PRINTF1(_L("All looks good"));
CleanupStack::PopAndDestroy(3);
}
/**
* Looks at a process specific thread list
*/
void CFlashDataSourceWrapper::DoCmd_GetThreadListL3_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::GetThreadListL() 3rd Test - Process specific thread list"));
//We need to write some thread data (will just do 2) to the flash, and update the header with its location
TInt64 t1id = 100;
TInt32 t1prior = 4;
TInt32 t1SvcSp = 20;
TInt32 t1UsrStkSize = 40;
TInt64 t2id = 200;
TInt32 t2prior = 5;
TInt32 t2SvcSp = 25;
TInt32 t2UsrStkSize = 47;
//thread names
_LIT8(KThread1, "t_thread1");
_LIT8(KThread2, "thread2");
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize + 2 * TThreadData::KSCMThreadDataMaxSize +
KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TInt owner1 = 100;
TInt owner2 = 200;
//The first thread data
TThreadData t1;
t1.iTid = t1id;
t1.iPriority = t1prior;
t1.iSvcSP = t1SvcSp;
t1.iUsrStacksize = t1UsrStkSize;
t1.iNamesize = KThread1().Size();
t1.iName = KThread1;
t1.iOwnerId = owner1;
//The second thread data
TThreadData t2;
t2.iTid = t2id;
t2.iPriority = t2prior;
t2.iSvcSP = t2SvcSp;
t2.iUsrStacksize = t2UsrStkSize;
t2.iNamesize = KThread2().Size();
t2.iName = KThread2;
t2.iOwnerId = owner2;
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iOffsetsHdr.iTLstOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize(); //starts right after headers
iInfHdr.iLogSize = iOffsetsHdr.iTLstOffset + t1.GetSize() + t2.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
t1.Serialize(writer);
t2.Serialize(writer);
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these threads back via GetThreadListL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
RThreadPointerList *threadList = new(ELeave)RThreadPointerList;
TCleanupItem threadCleanup(CFlashDataSource::CleanupThreadList, (TAny*)threadList);
CleanupStack::PushL(threadCleanup);
TUint wr = 0;
INFO_PRINTF1(_L("Getting thread list"));
TRAP(err, iObject->GetThreadListL(owner1, *threadList, wr));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to get thread list: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(threadList->Count() != 1)
{
ERR_PRINTF1(_L("Retrieved wrong number of threads"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
CThreadInfo* ti1 = (*threadList)[0];
INFO_PRINTF1(_L("Retrieveing threads"));
if(!ti1)
{
ERR_PRINTF1(_L("Failed to retrieve non null threads"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
INFO_PRINTF1(_L("Making sure processes are as expected"));
//Check ID's
if(ti1->Id() != t1.iTid)
{
ERR_PRINTF1(_L("Failed to retrieve correct thread ID's:"));
ERR_PRINTF3(_L("T1 expected [%d] but found [%d]"), t1.iTid, ti1->Id());
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
//check names
RBuf wide;
wide.CreateL(KThread1().Size());
wide.CleanupClosePushL();
wide.Copy(KThread1);
INFO_PRINTF1(_L("Checking thread 1 name is ok"));
if( ti1->Name().Compare(wide) != 0 )
{
ERR_PRINTF3(_L("Wrong name retrieved, expected [%S] but got [%S]"), &KThread1, &wide);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
INFO_PRINTF1(_L("All looks good"));
CleanupStack::PopAndDestroy(3);
}
/**
* Negative tests should the flash contain corrupt data
*/
void CFlashDataSourceWrapper::DoCmd_GetThreadListL2_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::GetThreadList() - 2nd test"));
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize + 3 * TRegisterSet::KSCMRegisterSetMaxSize + KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iOffsetsHdr.iTLstOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize(); //starts right after headers
iInfHdr.iLogSize = iOffsetsHdr.iTLstOffset + 2 * iContextHdr.GetSize();
INFO_PRINTF1(_L("Writing known processes to flash"));
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
iContextHdr.Serialize(writer);
iContextHdr.Serialize(writer);
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
RThreadPointerList *threadList = new(ELeave)RThreadPointerList;
TCleanupItem threadCleanup(CFlashDataSource::CleanupThreadList, (TAny*)threadList);
CleanupStack::PushL(threadCleanup);
INFO_PRINTF1(_L("Getting thread list"));
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to process header [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
TUint wr = 0;
TRAP(err, iObject->GetThreadListL(START_OF_FLASH, *threadList, wr));
if(threadList->Count() != 0)
{
ERR_PRINTF1(_L("Should have retrieved zero sized thread list"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
INFO_PRINTF1(_L("Everything is as expected"));
CleanupStack::PopAndDestroy(2);
}
/**
* Tests we can read registers back from the flash succesfully
*/
void CFlashDataSourceWrapper::DoCmd_ReadRegistersL1_Test_L()
{
/**
* The 3 different register sets corrospond to the 3 different register related configuration
* options:
* ECrashedThreadFullRegisters starts from iCTFullReg
* EThreadsUsrRegisters starts from iSysSvrReg
* EThreadsSvrRegisters starts from iSysUsrReg
*
* Are going to write the following data to flash:
*
* |--TCrashHeader--||--TRegisterValue--| ... |--TRegisterValue--| at the ECrashedThreadFullRegisters point
* <-- For a crashed thread -->
* |--TRegisterValue--| ... |--TRegisterValue--| at the EThreadsUsrRegisters point
* <-- For a system thread (at user registers point) -->
* |--TRegisterValue--| ... |--TRegisterValue--| at the EThreadsSvrRegisters point
* <-- For a system thread (at svr register point) -->
*/
INFO_PRINTF1(_L("Testing CFlashDataSource::ReadRegistersL() Test1"));
TThreadId crashedThread = TThreadId(139); //arbitrary vals
TThreadId otherThread = TThreadId(15); //arbitrary vals
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize + 6 * TRegisterValue::KSCMRegisterValueMaxSize + KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
//Headers - as much as we need
iInfHdr.iTid = crashedThread.Id();
iInfHdr.iCrashId = CRASH_ID;
iOffsetsHdr.iCTFullRegOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize(); //starts right after headers
iContextHdr.iNumRegisters = 0; //no context
//For this test we will put in 2 registers for each config option
TRegisterValue r1;
r1.iValue32 = 0xDEADDEAA;
r1.iOwnId = crashedThread.Id();
TRegisterValue r2;
r2.iValue32 = 0xDEADEADB;
r2.iOwnId = crashedThread.Id();
TRegisterValue r3;
r3.iValue32 = 0xDEADEADC;
r3.iOwnId = otherThread.Id();
TRegisterValue r4;
r4.iValue32 = 0xDEADEADD;
r4.iOwnId = otherThread.Id();
TRegisterValue r5;
r5.iValue32 = 0xDEADEADE;
r5.iOwnId = otherThread.Id();
TRegisterValue r6;
r6.iValue32 = 0xDEADEADF;
r6.iOwnId = otherThread.Id();
iOffsetsHdr.iSysSvrRegOffset = iOffsetsHdr.iCTFullRegOffset + r1.GetSize() + r2.GetSize();
iOffsetsHdr.iSysUsrRegOffset = iOffsetsHdr.iSysSvrRegOffset + r3.GetSize() + r4.GetSize();
iInfHdr.iLogSize = iOffsetsHdr.iSysUsrRegOffset + r6.GetSize() + r5.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
r1.Serialize(writer);
r2.Serialize(writer);
r3.Serialize(writer);
r4.Serialize(writer);
r5.Serialize(writer);
r6.Serialize(writer);
INFO_PRINTF1(_L("Writing known registers to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(0, data ,written));
//Now we try and get them back via ReadRegistersL
RRegisterList regList;
CleanupClosePushL(regList);
INFO_PRINTF1(_L("Reading back registers"));
TRAPD(err, iObject->AnalyseCrashL(1));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to analyse crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
//Read for crashed thread first (hard coded in the absence of TSymbianInfo for now)
TRAP(err, iObject->ReadRegistersL(crashedThread.Id(), regList));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to read registers: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(regList.Count() != 2)
{
ERR_PRINTF2(_L("Got wrong amount of registers back: [%d]"), regList.Count());
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(regList[0].iValue32 != r1.iValue32 || regList[1].iValue32 != r2.iValue32)
{
ERR_PRINTF1(_L("Got wrong register values back"));
ERR_PRINTF3(_L("\tExpected Expected [0x%X] but got [0x%X]"),r1.iValue32,regList[0].iValue32);
ERR_PRINTF3(_L("\tExpected Expected [0x%X] but got [0x%X]"),r2.iValue32,regList[1].iValue32);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
//and for "system" thread
TRAP(err, iObject->ReadRegistersL(otherThread.Id(), regList));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to read registers: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(regList.Count() != 4)
{
ERR_PRINTF2(_L("Got wrong amount of registers back: [%d]"), regList.Count());
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
if(regList[0].iValue32 != r3.iValue32
|| regList[1].iValue32 != r4.iValue32
|| regList[2].iValue32 != r5.iValue32
|| regList[3].iValue32 != r6.iValue32)
{
ERR_PRINTF1(_L("Got wrong register values back"));
ERR_PRINTF3(_L("\tExpected Expected [0x%X] but got [0x%X]"),r3.iValue32,regList[0].iValue32);
ERR_PRINTF3(_L("\tExpected Expected [0x%X] but got [0x%X]"),r4.iValue32,regList[1].iValue32);
ERR_PRINTF3(_L("\tExpected Expected [0x%X] but got [0x%X]"),r5.iValue32,regList[2].iValue32);
ERR_PRINTF3(_L("\tExpected Expected [0x%X] but got [0x%X]"),r6.iValue32,regList[3].iValue32);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
INFO_PRINTF1(_L("Got back all registers as expected"));
CleanupStack::PopAndDestroy(2);
}
/**
* Tests that we can read memory from the crash log
*/
void CFlashDataSourceWrapper::DoCmd_ReadMemoryL1_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::ReadMemoryL() Test1"));
//buffer to hold memory
TInt32 numBytes = 8; //we will dump 8 bytes of memory
TUint8 memoryToDump = 0xAB;
RBuf8 mem;
mem.CreateL(numBytes * sizeof(TUint8));
mem.CleanupClosePushL();
for(TInt cnt = numBytes -1; cnt >= 0; cnt--)
{
mem.Append(&memoryToDump, sizeof(TUint8));
}
//buffer to hold log
TInt dataLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize + TRegisterSet::KSCMRegisterSetMaxSize + numBytes + TMemoryDump::KSCMMemDumpMaxSize + TRawData::KSCMRawDataMaxSize;
RBuf8 data;
data.CreateL(dataLength);
data.SetLength(dataLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TUint32 startAdd = 0x10000000;
TUint64 procId = 100;
TMemoryDump memDump;
memDump.iStartAddress = startAdd;
memDump.iPid = procId;
memDump.iLength = mem.Length();
TRawData rawData;
rawData.iLength = mem.Length();
rawData.iData.Set(mem.MidTPtr(0));
TInt32 crashSize = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize() + memDump.GetSize() + rawData.GetSize();
iInfHdr.iLogSize = crashSize;
iInfHdr.iCrashId = CRASH_ID;
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
memDump.Serialize(writer);
rawData.Serialize(writer);
INFO_PRINTF1(_L("Writing known memory to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to analyse crash: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
RBuf8 found;
found.CreateL(mem.Length());
found.CleanupClosePushL();
//We read memory by thread ID. So we will create an arbitrary thread and assign it to belong to the
//process ID we have dumped memory for
TInt64 threadId = 23;
iObject->AssignOwner(procId, threadId);
TRAP(err, iObject->ReadMemoryL(threadId, startAdd, mem.Length(), found));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to read memory: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
for(TInt cnt = found.Length() -1; cnt >= 0; cnt--)
{
if(found[cnt] != memoryToDump)
{
ERR_PRINTF2(_L("Wrong memory returned = [0x%X]"),found[cnt]);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
}
INFO_PRINTF1(_L("Got back all memory as expected"));
CleanupStack::PopAndDestroy(3);
}
/**
* Negative Tests to see we can handle dodgy params
*/
void CFlashDataSourceWrapper::DoCmd_ReadMemoryL2_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::ReadMemoryL() Test2"));
//buffer to hold memory
TInt32 numBytes = 8; //we will dump 8 bytes of memory
TUint8 memoryToDump = 0xAB;
RBuf8 mem;
mem.CreateL(numBytes * sizeof(TUint8));
mem.CleanupClosePushL();
for(TInt cnt = numBytes -1; cnt >= 0; cnt--)
{
mem.Append(&memoryToDump, sizeof(TUint8));
}
//buffer to hold log
TInt dataLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize + TRegisterSet::KSCMRegisterSetMaxSize + numBytes + TMemoryDump::KSCMMemDumpMaxSize + TRawData::KSCMRawDataMaxSize;
RBuf8 data;
data.CreateL(dataLength);
data.SetLength(dataLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TUint32 startAdd = 0x10000000;
TUint64 procId = 100;
TMemoryDump memDump;
memDump.iStartAddress = startAdd;
memDump.iPid = procId;
memDump.iLength = mem.Length();
TRawData rawData;
rawData.iLength = mem.Length();
rawData.iData.Set(mem.MidTPtr(0));
TInt32 crashSize = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize() + memDump.GetSize() + rawData.GetSize();
iInfHdr.iLogSize = crashSize;
iInfHdr.iCrashId = CRASH_ID;
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
memDump.Serialize(writer);
rawData.Serialize(writer);
INFO_PRINTF1(_L("Writing known memory to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to analyse crash: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
RBuf8 found;
found.CreateL(mem.Length());
found.CleanupClosePushL();
//reading from address not dumped
TRAP(err, iObject->ReadMemoryL(procId, 0xDEDEADAD, mem.Length(), found));
if(KErrNotFound != err)
{
ERR_PRINTF2(_L("Able to read memory not dumped: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
//read from a thread not dumped
TRAP(err, iObject->ReadMemoryL(50, startAdd, mem.Length(), found));
if(KErrNotFound != err)
{
ERR_PRINTF2(_L("able to read memory from thread not dumped: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
INFO_PRINTF1(_L("Got back all memory as expected"));
CleanupStack::PopAndDestroy(3);
}
/**
* Tests CFlashDataSource::GetCodeSegmentsL
* Writes known code segments to flash and ensures we can get them back
*
* Description:
* We will pretend we have a process ID of 100. We will also have a thread ID of 101.
* We will assign ownership between these two - ie. thread ID 101 exists in process ID 100.
* We will write a mini crash log to flash:
* <---Crash Header---><---Code Segment Set---><---Code Segment 1---><---Code Segment 2--->
*
* The code segments will exist for process ID 100. We will then try to read the code segments
* for thread ID 101 and we should retrieve code seg 1 and 2.
*
*/
void CFlashDataSourceWrapper::DoCmd_GetCodeSegmentsL1_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::GetCodeSegmentsL() - 1st test"));
TUint64 procId = 100; //arbitrary
TInt numSegs = 2;
TCodeSegmentSet segSet;
segSet.iNumSegs = 2;
segSet.iPid = procId;
segSet.iNumSegs = numSegs;
//seg names
_LIT8(KSeg1, "seg1");
_LIT8(KSeg2, "cseg2");
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize + 2 * TCodeSegment::KMaxSegmentNameSize +
KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TCodeSegment seg1;
seg1.iNameLength = KSeg1().Size();
seg1.iName = KSeg1;
seg1.iCodeSegType = EExeCodeSegType;
TCodeSegment seg2;
seg2.iNameLength = KSeg2().Size();
seg2.iName = KSeg2;
seg2.iCodeSegType = EExeCodeSegType;
//For code segments to make sense we need to assign thread to process ownership
TInt64 threadId = 101;
iObject->AssignOwner(procId, threadId);
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iInfHdr.iLogSize = iInfHdr.GetSize() + iContextHdr.GetSize() + iOffsetsHdr.GetSize() + segSet.GetSize() + seg1.GetSize() + seg2.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
segSet.Serialize(writer);
seg1.Serialize(writer);
seg2.Serialize(writer);
INFO_PRINTF1(_L("Writing known Code Segs to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these threads back via GetCodeSegmentsL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
RCodeSegPointerList* list = new(ELeave)RCodeSegPointerList;
TCleanupItem segCleanup(CFlashDataSource::CleanupCodeSegList, (TAny*)list);
CleanupStack::PushL(segCleanup);
TUint sz = 0;
TRAP(err, iObject->GetCodeSegmentsL(threadId, *list, sz));
if(list->Count() != numSegs)
{
ERR_PRINTF3(_L("Failed to retrieve right amount of code segs. Expected [%d] got [%d]"),numSegs, list->Count());
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
TCodeSegInfo* cs1 = (*list)[0];
TCodeSegInfo* cs2 = (*list)[1];
INFO_PRINTF1(_L("Retrieveing code segs"));
if(!cs1 || !cs2)
{
ERR_PRINTF1(_L("Failed to retrieve non null threads"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
//Check types
INFO_PRINTF1(_L("Checking code seg types are ok"));
if(cs1->iType != EExeCodeSegType || cs2->iType != EExeCodeSegType)
{
ERR_PRINTF1(_L("Failed to retrieve correct code seg types:"));
ERR_PRINTF3(_L("CS1 expected [%d] but found [%d]"), EExeCodeSegType, cs1->iType);
ERR_PRINTF3(_L("CS2 expected [%d] but found [%d]"), EExeCodeSegType, cs2->iType);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
//check names
RBuf wide;
wide.CreateL(KSeg1().Size());
wide.CleanupClosePushL();
wide.Copy(KSeg1);
INFO_PRINTF1(_L("Checking code seg name's are ok"));
TBool passed = (cs1->iName.Compare(wide) == 0) || (cs2->iName.Compare(wide) == 0);
if(!passed)
{
ERR_PRINTF4(_L("Wrong name retrieved, expected [%S] but got [%S] and [%S]"), &wide, &cs2->iName, &cs1->iName);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
if(2 *KSeg2().Size() > wide.Size())
{
wide.ReAllocL(2 * KSeg2().Size());
}
wide.Copy(KSeg2);
INFO_PRINTF1(_L("Checking second code seg name is ok"));
passed = (cs1->iName.Compare(wide) == 0) || (cs2->iName.Compare(wide) == 0);
if(!passed)
{
ERR_PRINTF4(_L("Wrong name retrieved, expected [%S] but got [%S] and [%S]"), &wide, &cs2->iName, &cs1->iName);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
CleanupStack::PopAndDestroy(3);
}
/**
* Tests CFlashDataSource::GetCodeSegmentsL
* Ensure we recognise corrupt segments (ie. no segment set to describe it)
*/
void CFlashDataSourceWrapper::DoCmd_GetCodeSegmentsL2_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource() - Code Segment Analysis - 2nd test"));
//seg names
_LIT8(KSeg1, "seg1");
_LIT8(KSeg2, "cseg2");
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize + 2 * TCodeSegment::KMaxSegmentNameSize +
KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TCodeSegment seg1;
seg1.iNameLength = KSeg1().Size();
seg1.iName = KSeg1;
seg1.iCodeSegType = EExeCodeSegType;
TCodeSegment seg2;
seg2.iNameLength = KSeg2().Size();
seg2.iName = KSeg2;
seg2.iCodeSegType = EExeCodeSegType;
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iInfHdr.iLogSize = iInfHdr.GetSize() + iContextHdr.GetSize() + iOffsetsHdr.GetSize()+ seg1.GetSize() + seg2.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
seg1.Serialize(writer);
seg2.Serialize(writer);
INFO_PRINTF1(_L("Writing known corrupt Code Segs to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these threads back via GetCodeSegmentsL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrCorrupt != err)
{
ERR_PRINTF2(_L("Failed to recognise corrupt data: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
CleanupStack::PopAndDestroy();
INFO_PRINTF1(_L("Corrupt data recognised"));
}
/**
* Tests CFlashDataSource::GetCodeSegmentsL
* Ensure we do not reciev duplicate segments
* even after we place then in flash
*/
void CFlashDataSourceWrapper::DoCmd_GetCodeSegmentsL3_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource() - Code Segment Analysis - 3rd test"));
TUint64 procId = 100; //arbitrary
const TInt KNumRepeatSegs = 3;
TCodeSegmentSet segSet;
segSet.iNumSegs = KNumRepeatSegs;
segSet.iPid = procId;
//seg names
_LIT8(KSeg1, "seg1");
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize + 2 * TCodeSegment::KMaxSegmentNameSize +
KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TCodeSegment seg1;
seg1.iNameLength = KSeg1().Size();
seg1.iName = KSeg1;
seg1.iCodeSegType = EExeCodeSegType;
//For code segments to make sense we need to assign thread to process ownership
TInt64 threadId = 101;
iObject->AssignOwner(procId, threadId);
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iInfHdr.iLogSize =
iInfHdr.GetSize() + iContextHdr.GetSize() + iOffsetsHdr.GetSize()
+ segSet.GetSize() + ( seg1.GetSize() * KNumRepeatSegs);
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
segSet.Serialize(writer);
// serialize the same segment a number of times
for(TInt i=0;i<segSet.iNumSegs;i++)
{
seg1.Serialize(writer);
}
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these threads back via GetCodeSegmentsL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
RCodeSegPointerList* list = new(ELeave)RCodeSegPointerList;
TCleanupItem segCleanup(CFlashDataSource::CleanupCodeSegList, (TAny*)list);
CleanupStack::PushL(segCleanup);
TUint sz = 0;
TRAP(err, iObject->GetCodeSegmentsL(threadId, *list, sz));
// loop through the code seg list check that none are the same
for(TInt i=0;i<list->Count();i++)
{
TCodeSegInfo* csinf1 = (*list)[i];
for(TInt j=1;j<list->Count();j++)
{
TCodeSegInfo* csinf2 = (*list)[j];
// check not checking same item
if( csinf1 != csinf2 )
{
if(csinf1->iDataRunAddr == csinf2->iDataRunAddr &&
csinf1->iDataSize == csinf2->iDataSize )
{
ERR_PRINTF1(_L("DUPLICATE code segs 1") );
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(2);
return;
}
}
}
}
CleanupStack::PopAndDestroy(2); // data , list
}
/**
* Tests we can get ALL expected trace data back
*/
void CFlashDataSourceWrapper::DoCmd_ReadTraceBufferL1_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::ReadTraceBufferL() Test1"));
//buffer to hold trace - will do in 2 parts to simulate the circular buffer
TInt32 numBytes = 8; //we will dump 8 bytes of trace
TUint8 traceToDump1 = 0xAB;
TUint8 traceToDump2 = 0xCD;
RBuf8 trace1;
trace1.CreateL(numBytes * sizeof(TUint8));
trace1.CleanupClosePushL();
for(TInt cnt = numBytes -1; cnt >= 0; cnt--)
{
trace1.Append(&traceToDump1, sizeof(TUint8));
}
RBuf8 trace2;
trace2.CreateL(numBytes * sizeof(TUint8));
trace2.CleanupClosePushL();
for(TInt cnt = numBytes -1; cnt >= 0; cnt--)
{
trace2.Append(&traceToDump2, sizeof(TUint8));
}
//buffer to hold log
TInt dataLength = TCrashInfoHeader::KSCMCrashInfoMaxSize +
TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize +
TTraceDump::KSCMTraceDumpMaxSize +
2 * (TRawData::KSCMRawDataMaxSize + numBytes);
RBuf8 data;
data.CreateL(dataLength);
data.SetLength(dataLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TTraceDump traceDump;
traceDump.iSizeOfMemory = 2 * numBytes;
traceDump.iNumberOfParts = 2;
TRawData rawData1;
rawData1.iLength = trace1.Length();
rawData1.iData.Set(trace1.MidTPtr(0));
TRawData rawData2;
rawData2.iLength = trace2.Length();
rawData2.iData.Set(trace2.MidTPtr(0));
TInt32 crashSize = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize() + traceDump.GetSize() + rawData1.GetSize() + rawData2.GetSize();
iInfHdr.iLogSize = crashSize;
iInfHdr.iCrashId = CRASH_ID;
iOffsetsHdr.iTraceOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
traceDump.Serialize(writer);
rawData1.Serialize(writer);
rawData2.Serialize(writer);
INFO_PRINTF1(_L("Writing known trace to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get the trace data back
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
TUint traceBufferAvailable = 0;
TRAP(err, traceBufferAvailable = iObject->GetAvailableTraceSizeL());
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to read trace data size: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
RBuf8 found;
found.CreateL(traceBufferAvailable);
found.CleanupClosePushL();
//reading from address not dumped
TRAP(err, iObject->ReadTraceBufferL(found));
RDebug::Printf("Printing trace found");
for(TInt x = 0; x<found.Length(); x++)
{
RDebug::Printf("[0x%X]", found[x]);
}
RBuf8 totalTrace;
totalTrace.CreateL(trace1.Length() + trace2.Length());
totalTrace.CleanupClosePushL();
totalTrace.Append(trace1);
totalTrace.Append(trace2);
if(totalTrace.Compare(found) != 0)
{
ERR_PRINTF1(_L("Found trace did not match expected trace"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(5);
return;
}
CleanupStack::PopAndDestroy(5);
}
void CFlashDataSourceWrapper::DoCmd_CalculateChecksum_TestL()
{
// check sum is commutative - so it should add up to same value
// however blocks were requested
INFO_PRINTF1(_L("DoCmd_CalculateChecksum_TestL called"));
TScmChecksum chksm1, chksm2;
iObject->CalculateChecksumL(0, 10, chksm1);
iObject->CalculateChecksumL(10, 10, chksm1);
iObject->CalculateChecksumL(0, 20, chksm2);
SetBlockResult((chksm1 == chksm2) ? EPass : EFail );
}
/**
* Tests we can get back the correct trace buffer size
*/
void CFlashDataSourceWrapper::DoCmd_TraceDataSizeL_TestL()
{
INFO_PRINTF1(_L("Testing CFlashDataSource() - Trace Size Test"));
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize + 2 * TCodeSegment::KMaxSegmentNameSize +
KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TUint memSize = 1243;
TTraceDump trace;
trace.iSizeOfMemory = memSize;
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iInfHdr.iLogSize = iInfHdr.GetSize() + iContextHdr.GetSize() + iOffsetsHdr.GetSize()+ trace.GetSize();
iOffsetsHdr.iTraceOffset = iInfHdr.GetSize() + iContextHdr.GetSize() + iOffsetsHdr.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
trace.Serialize(writer);
INFO_PRINTF1(_L("Writing known trace struct to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these threads back via GetCodeSegmentsL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to analyse crash: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
CleanupStack::PopAndDestroy();
TUint recoveredMemSize = 0;
TRAP(err, recoveredMemSize = iObject->GetAvailableTraceSizeL());
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to get back trace size: [%d]"), err);
SetBlockResult(EFail);
return;
}
if(recoveredMemSize != memSize)
{
ERR_PRINTF3(_L("Failed to get back correct trace size: Got [%d] Expected [%d]"), recoveredMemSize, memSize);
SetBlockResult(EFail);
return;
}
INFO_PRINTF1(_L("Trace size looks good"));
}
/**
* Tests we can get back the correct trace buffer size
*/
void CFlashDataSourceWrapper::DoCmd_TraceDataSizeNotFoundL_TestL()
{
INFO_PRINTF1(_L("Testing CFlashDataSource() - Trace Size Test - Negative"));
//buffer for data
TInt bufLength = TCrashInfoHeader::KSCMCrashInfoMaxSize + TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize + 2 * TCodeSegment::KMaxSegmentNameSize +
KMaxCacheSize;
RBuf8 data;
data.CreateL(bufLength);
data.SetLength(bufLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
iInfHdr.iCrashId = CRASH_ID;
iContextHdr.iNumRegisters = 0; //no context
iInfHdr.iLogSize = iInfHdr.GetSize() + iContextHdr.GetSize() + iOffsetsHdr.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
INFO_PRINTF1(_L("Writing known trace struct to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get these threads back via GetCodeSegmentsL
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to analyse crash: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy();
return;
}
CleanupStack::PopAndDestroy();
TRAP(err, TUint recoveredMemSize = iObject->GetAvailableTraceSizeL());
if(KErrNotFound != err)
{
ERR_PRINTF2(_L("Failed to get back KErrNone for non available trace size: [%d]"), err);
SetBlockResult(EFail);
return;
}
INFO_PRINTF1(_L("All as expected."));
}
/**
* Tests we can get ALL expected trace data back
*/
void CFlashDataSourceWrapper::DoCmd_ReadTraceBufferL2_Test_L()
{
INFO_PRINTF1(_L("Testing CFlashDataSource::ReadTraceBufferL() Test2"));
//buffer to hold trace - will do in 2 parts to simulate the circular buffer
TInt32 numBytes = 8; //we will dump 8 bytes of trace
TUint8 traceToDump1 = 0xAB;
TUint8 traceToDump2 = 0xCD;
RBuf8 trace1;
trace1.CreateL(numBytes * sizeof(TUint8));
trace1.CleanupClosePushL();
for(TInt cnt = numBytes -1; cnt >= 0; cnt--)
{
trace1.Append(&traceToDump1, sizeof(TUint8));
}
RBuf8 trace2;
trace2.CreateL(numBytes * sizeof(TUint8));
trace2.CleanupClosePushL();
for(TInt cnt = numBytes -1; cnt >= 0; cnt--)
{
trace2.Append(&traceToDump2, sizeof(TUint8));
}
//buffer to hold log
TInt dataLength = TCrashInfoHeader::KSCMCrashInfoMaxSize +
TCrashOffsetsHeader::KSCMCrashOffsetsMaxSize +
TRegisterSet::KSCMRegisterSetMaxSize +
TTraceDump::KSCMTraceDumpMaxSize +
2 * (TRawData::KSCMRawDataMaxSize + numBytes);
RBuf8 data;
data.CreateL(dataLength);
data.SetLength(dataLength);
data.CleanupClosePushL();
TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
TTraceDump traceDump;
traceDump.iSizeOfMemory = 2 * numBytes;
traceDump.iNumberOfParts = 2;
TRawData rawData1;
rawData1.iLength = trace1.Length();
rawData1.iData.Set(trace1.MidTPtr(0));
TRawData rawData2;
rawData2.iLength = trace2.Length();
rawData2.iData.Set(trace2.MidTPtr(0));
TInt32 crashSize = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize() + traceDump.GetSize() + rawData1.GetSize() + rawData2.GetSize();
iInfHdr.iLogSize = crashSize;
iInfHdr.iCrashId = CRASH_ID;
iOffsetsHdr.iTraceOffset = iInfHdr.GetSize() + iOffsetsHdr.GetSize() + iContextHdr.GetSize();
iInfHdr.Serialize(writer);
iOffsetsHdr.Serialize(writer);
iContextHdr.Serialize(writer);
traceDump.Serialize(writer);
rawData1.Serialize(writer);
rawData2.Serialize(writer);
INFO_PRINTF1(_L("Writing known trace to flash"));
TUint32 written = 0;
User::LeaveIfError(iSecSess.WriteCrashConfig(START_OF_FLASH, data ,written));
//Now we try get the trace data back
TRAPD(err, iObject->AnalyseCrashL(CRASH_ID));
if(KErrNone != err)
{
ERR_PRINTF2(_L("Failed to process crash header: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
TUint traceBufferAvailable = 0;
TRAP(err, traceBufferAvailable = iObject->GetAvailableTraceSizeL());
if(KErrNone != err)
{
ERR_PRINTF2(_L("Unable to read trace data size: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(3);
return;
}
RBuf8 totalTrace;
totalTrace.CreateL(trace1.Length() + trace2.Length());
totalTrace.CleanupClosePushL();
totalTrace.Append(trace1);
totalTrace.Append(trace2);
//Read 1 byte at a time
RBuf8 read;
read.CreateL(1);
read.CleanupClosePushL();
for(TInt x = 0; x< traceBufferAvailable; x++)
{
TRAP(err, iObject->ReadTraceBufferL(read, x));
if(err != KErrNone)
{
ERR_PRINTF2(_L("Unable to read trace data: [%d]"), err);
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(5);
return;
}
RDebug::Printf("Found [0x%X] expected [0x%X]", read[0], totalTrace[x]);
if(read[0] != totalTrace[x])
{
ERR_PRINTF1(_L("Didnt get back expected trace"));
SetBlockResult(EFail);
CleanupStack::PopAndDestroy(5);
return;
}
}
CleanupStack::PopAndDestroy(5);
}
//eof