diff -r 000000000000 -r c6b0df440bee dbgsrv/coredumpserver/test/automatictests/tcds_unit/src/cds/CFlashDataSourceWrapper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbgsrv/coredumpserver/test/automatictests/tcds_unit/src/cds/CFlashDataSourceWrapper.cpp Tue Mar 02 10:33:16 2010 +0530 @@ -0,0 +1,2279 @@ +// 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 (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(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(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(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(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(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(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(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(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(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(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(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(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;iAnalyseCrashL(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;iCount();i++) + { + TCodeSegInfo* csinf1 = (*list)[i]; + for(TInt j=1;jCount();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(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; xCalculateChecksumL(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(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(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(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 + +