// Copyright (c) 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:
// Test wrapper for unit tests of the sELF lib
/**
* @file CSELFLibWrapper.cpp
* @internalTechnology
*/
#include <f32file.h>
#include <bautils.h>
#include "CSELFLibWrapper.h"
CSELFLibWrapper::CSELFLibWrapper()
{}
CSELFLibWrapper::~CSELFLibWrapper()
{
iFs.Close();
}
/**
* Two phase constructor for CFlashDataSourceWrapper
* @return CFlashDataSourceWrapper object
* @leave
*/
CSELFLibWrapper* CSELFLibWrapper::NewL()
{
CSELFLibWrapper* ret = new (ELeave) CSELFLibWrapper();
CleanupStack::PushL(ret);
ret->ConstructL();
CleanupStack::Pop(ret);
return ret;
}
/**
* Safe construction
* @leave
*/
void CSELFLibWrapper::ConstructL()
{
User::LeaveIfError(iFs.Connect());
}
/**
* Process command to see what test to run
*/
TBool CSELFLibWrapper::DoCommandL(const TTEFFunction& aCommand, const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
{
__UHEAP_MARK;
(void)aSection;
(void)aAsyncErrorIndex;
RBuf8 name;
name.CreateL(aCommand.Length());
name.Copy(aCommand);
RDebug::Printf("\nNext Test Case... [%S]", &name);
name.Close();
if(KSELFNewL() == aCommand)
TestNewL_L();
else if(KSELFNewLC() == aCommand)
TestNewLC_L();
else if(KSELF_InvalidSignature() == aCommand)
TestConstruction_InvalidELF_SignatureL();
else if(KSELF_InvalidSize() == aCommand)
TestConstruction_InvalidELF_SizeL();
else if(KSELF_NotSupported() == aCommand)
TestConstruction_ValidELF_NotSupported();
else if(KSELF_TestConstruction_Inuse() == aCommand)
TestConstruction_Inuse();
else if(KSELF_GetElfHeaderL() == aCommand)
TestGetElfHeaderL();
else if(KSELF_InsertVariantSpecificData() == aCommand)
TestInsertDataL();
else if(KSELF_InsertMultipleVariants() == aCommand)
TestMultipleInsertionL();
else if(KSELF_InsertNothingAndUpdate() == aCommand)
TestInsertNothingL();
else if(KSELF_TestPerformance() == aCommand)
TestPerformanceL();
else if(KSELF_TestStress() == aCommand)
TestStressL();
else if(KPrepareFiles() == aCommand)
CopyFilesToWritablePlaceL();
else if(KTearDownFiles() == aCommand)
TearDownFilesL();
__UHEAP_MARKEND;
return ETrue;
}
/**
* Unit test for:
* CSELFEditor* CSELFEditor::NewL()
* @see CSELFEditor
*/
void CSELFLibWrapper::TestNewL_L()
{
INFO_PRINTF1(_L("Testing CSELFEditor::NewL"));
//Try a file we know does not exist
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileNameNonExistant()));
INFO_PRINTF3(_L("CSELFEditor::NewL(%S) returns [%d]"), &KSELFFileNameNonExistant, err);
T_SELFLIB_ASSERT_TRUE(KErrNotFound == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
//Try a file we know does exist
TRAP(err, editor = CSELFEditor::NewL(KSELFFileName()));
INFO_PRINTF3(_L("CSELFEditor::NewL(%S) returns [%d]"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 0);
T_SELFLIB_ASSERT_TRUE(editor != NULL, 0);
delete editor;
editor = NULL;
#ifdef _DEBUG //__UHEAP_FAILNEXT won't work on urel
//Try with an allocation fail
__UHEAP_FAILNEXT(1);
TRAP(err, editor = CSELFEditor::NewL(KSELFFileName()));
INFO_PRINTF3(_L("CSELFEditor::NewL(%S) returns [%d] (with __UHEAP_FAILNEXT)"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrNoMemory == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
#endif
}
/**
* Unit test for:
* CSELFEditor* CSELFEditor::NewLC()
* @see CSELFEditor
*/
void CSELFLibWrapper::TestNewLC_L()
{
INFO_PRINTF1(_L("Testing CSELFEditor::NewLC"));
//Try a file we know does not exist
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewLC(KSELFFileNameNonExistant()); CleanupStack::Pop(););
INFO_PRINTF3(_L("CSELFEditor::NewLC(%S) returns [%d]"), &KSELFFileNameNonExistant, err);
T_SELFLIB_ASSERT_TRUE(KErrNotFound == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
//Try a file we know does exist
TRAP(err, editor = CSELFEditor::NewLC(KSELFFileName()); CleanupStack::Pop(););
INFO_PRINTF3(_L("CSELFEditor::NewLC(%S) returns [%d]"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 0);
T_SELFLIB_ASSERT_TRUE(editor != NULL, 0);
delete editor;
editor = NULL;
#ifdef _DEBUG //__UHEAP_FAILNEXT won't work on urel
//Try with an allocation fail
__UHEAP_FAILNEXT(1);
TRAP(err, editor = CSELFEditor::NewLC(KSELFFileName()); CleanupStack::Pop());
INFO_PRINTF3(_L("CSELFEditor::NewLC(%S) returns [%d] (with __UHEAP_FAILNEXT)"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrNoMemory == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
#endif
}
/**
* Unit test for:
* CSELFEditor::InsertVariantSpecificDataL()
* @see CSELFEditor
*/
void CSELFLibWrapper::TestInsertDataL()
{
INFO_PRINTF1(_L("Testing CSELFEditor Insert Variant Sepcific data"));
//Get the number of variant data segments there before
TInt prenumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments before the test"), prenumsegments);
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 0);
T_SELFLIB_ASSERT_TRUE(editor != NULL, 0);
CleanupStack::PushL(editor);
INFO_PRINTF1(_L("Inserting the variant specific"));
TRAP(err, editor->InsertVariantSpecificDataL(KTestData1()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
TRAP(err, editor->InsertVariantSpecificDataL(KTestData2()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
TRAP(err, editor->InsertVariantSpecificDataL(KTestData3()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
INFO_PRINTF1(_L("Updating the ELF file"));
TRAP(err, editor->WriteELFUpdatesL());
INFO_PRINTF2(_L("ELF File updating returned [%d]"), err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
CleanupStack::PopAndDestroy(editor);
TInt postnumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments after the test"),postnumsegments);
T_SELFLIB_ASSERT_TRUE(prenumsegments + 3 == postnumsegments, 0);
TInt bufferRequired = GetVariantSegmentSizeL(postnumsegments - 1, KSELFFileName());
RBuf8 data;
data.CreateL(bufferRequired);
data.CleanupClosePushL();
TRAP(err, GetVariantSegmentDataL(postnumsegments - 1, data, KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 1);
T_SELFLIB_ASSERT_TRUE(0 == KTestData3().Compare(data), 1);
TRAP(err, GetVariantSegmentDataL(postnumsegments - 2, data, KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 1);
T_SELFLIB_ASSERT_TRUE(0 == KTestData2().Compare(data), 1);
TRAP(err, GetVariantSegmentDataL(postnumsegments - 3, data, KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 1);
T_SELFLIB_ASSERT_TRUE(0 == KTestData1().Compare(data), 1);
INFO_PRINTF1(_L("Data looks good"));
CleanupStack::PopAndDestroy(&data);
}
/**
* Tests that you can't have mutliple CSELFEditors open on the same ELF file
* @see CSELFEditor
*/
void CSELFLibWrapper::TestConstruction_Inuse()
{
INFO_PRINTF1(_L("Testing CSELFEditor multiple handles"));
CSELFEditor* handle1 = NULL;
CSELFEditor* handle2 = NULL;
//Open one handle
TRAPD(err, handle1 = CSELFEditor::NewL(KSELFFileName()));
INFO_PRINTF3(_L("CSELFEditor::NewL(%S) returns [%d]"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 0);
T_SELFLIB_ASSERT_TRUE(handle1 != NULL, 0);
//Try handle two
TRAP(err, handle2 = CSELFEditor::NewL(KSELFFileName()));
INFO_PRINTF3(_L("CSELFEditor::NewL(%S) returns [%d] (this is the second handle)"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrInUse == err, 0);
T_SELFLIB_ASSERT_TRUE(handle2 == NULL, 0);
delete handle1;
}
/**
* Unit test for:
* CSELFEditor::NewL
* Tests with an invalid ELF file. This is invalid due to its signature
* @see CSELFEditor
*/
void CSELFLibWrapper::TestConstruction_InvalidELF_SignatureL()
{
INFO_PRINTF1(_L("Testing CSELFEditor construction with an invalid file - bad signature"));
//Create an ELF file editor
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileNameInvalidBySignature()));
INFO_PRINTF3(_L("Opening [%S] returned [%d]"), &KSELFFileNameInvalidBySignature, err);
T_SELFLIB_ASSERT_TRUE(KErrCorrupt == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
#ifdef _DEBUG //__UHEAP_FAILNEXT won't work on urel
//Try it again with a failed memory alloc
__UHEAP_FAILNEXT(1);
TRAP(err, editor = CSELFEditor::NewL(KSELFFileNameInvalidBySignature()));
INFO_PRINTF3(_L("Opening [%S] returned [%d] (with __UHEAP_FAILNEXT)"), &KSELFFileNameInvalidBySignature, err);
T_SELFLIB_ASSERT_TRUE(KErrNoMemory == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
#endif
}
/**
* There are valid ELF files that the ELF lib won't support (mainly) none Core files
* This tests that it throws a KErrNotSupported.
* @see CSELFEditor
*/
void CSELFLibWrapper::TestConstruction_ValidELF_NotSupported()
{
INFO_PRINTF1(_L("Testing CSELFEditor construction with an valid file but unsupported"));
//Create an ELF file editor
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileNameExe()));
INFO_PRINTF3(_L("Opening [%S] returned [%d]"), &KSELFFileNameExe, err);
T_SELFLIB_ASSERT_TRUE(KErrNotSupported == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
}
/**
* Unit test for:
* CSELFEditor::NewL
* Tests with an invalid ELF file. This is invalid due to its size
* @see CSELFEditor
*/
void CSELFLibWrapper::TestConstruction_InvalidELF_SizeL()
{
INFO_PRINTF1(_L("Testing CSELFEditor construction with an invalid file - bad size"));
//Create an ELF file editor
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileNameTiny()));
INFO_PRINTF3(_L("Opening [%S] returned [%d]"), &KSELFFileNameTiny, err);
T_SELFLIB_ASSERT_TRUE(KErrCorrupt == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
#ifdef _DEBUG //__UHEAP_FAILNEXT won't work on urel
//Try it again with a failed memory alloc
__UHEAP_FAILNEXT(1);
TRAP(err, editor = CSELFEditor::NewL(KSELFFileNameTiny()));
INFO_PRINTF3(_L("Opening [%S] returned [%d] (with __UHEAP_FAILNEXT)"), &KSELFFileNameTiny, err);
T_SELFLIB_ASSERT_TRUE(KErrNoMemory == err, 0);
T_SELFLIB_ASSERT_TRUE(editor == NULL, 0);
#endif
}
/**
* Unit test for:
* CSELFEditor::GetElfHeaderL()
* @see CSELFEditor
*/
void CSELFLibWrapper::TestGetElfHeaderL()
{
INFO_PRINTF1(_L("Testing CSELFEditor::GetElfHeaderL()"));
//Try a file we know does exist
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileName()));
INFO_PRINTF3(_L("CSELFEditor::NewL(%S) returns [%d]"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 0);
T_SELFLIB_ASSERT_TRUE(editor != NULL, 0);
CleanupStack::PushL(editor);
Elf32_Ehdr header;
editor->GetELFHeader(header);
LogELFHeader(header);
//Assert on the values we can be sure of to be sure potatoes
T_SELFLIB_ASSERT_TRUE(header.e_type == ET_CORE, 1);
T_SELFLIB_ASSERT_TRUE(header.e_version == EV_CURRENT, 1);
T_SELFLIB_ASSERT_TRUE(header.e_machine == EM_ARM, 1);
T_SELFLIB_ASSERT_TRUE(header.e_entry == 0, 1);
T_SELFLIB_ASSERT_TRUE(header.e_ehsize == sizeof(Elf32_Ehdr), 1);
T_SELFLIB_ASSERT_TRUE(header.e_phnum > 0, 1);
CleanupStack::PopAndDestroy(editor);
}
/**
* Test we can insert more than one variant specific segment
* @leave One of the system wide codes
*/
void CSELFLibWrapper::TestMultipleInsertionL()
{
INFO_PRINTF1(_L("Testing CSELFEditor Insert Multiple Variant Sepcific data"));
//Get the number of variant data segments there before
TInt prenumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments before the test"), prenumsegments);
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 0);
T_SELFLIB_ASSERT_TRUE(editor != NULL, 0);
CleanupStack::PushL(editor);
INFO_PRINTF1(_L("Inserting the variant specific data"));
TRAP(err, editor->InsertVariantSpecificDataL(KTestData1()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
INFO_PRINTF1(_L("Updating the ELF file"));
TRAP(err, editor->WriteELFUpdatesL());
INFO_PRINTF2(_L("ELF File updating returned [%d]"), err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
//Write a second time
INFO_PRINTF1(_L("Inserting more variant specific data"));
TRAP(err, editor->InsertVariantSpecificDataL(KTestData2()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
INFO_PRINTF1(_L("Updating the ELF file"));
TRAP(err, editor->WriteELFUpdatesL());
CleanupStack::PopAndDestroy(editor);
TInt postnumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments after the test"),postnumsegments);
T_SELFLIB_ASSERT_TRUE(prenumsegments + 2 == postnumsegments, 0);
TInt bufferRequired = GetVariantSegmentSizeL(postnumsegments - 1, KSELFFileName());
RBuf8 data;
data.CreateL(bufferRequired);
data.CleanupClosePushL();
TRAP(err, GetVariantSegmentDataL(postnumsegments - 1, data, KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 1);
T_SELFLIB_ASSERT_TRUE(0 == KTestData2().Compare(data), 1);
TRAP(err, GetVariantSegmentDataL(postnumsegments - 2, data, KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 1);
T_SELFLIB_ASSERT_TRUE(0 == KTestData1().Compare(data), 1);
INFO_PRINTF1(_L("Data looks good"));
CleanupStack::PopAndDestroy(&data);
}
/**
* Adds nothing to the ELF file but calls the update function. Verifies that the
* file remains the same
* @leave One of the system wide codes
*/
void CSELFLibWrapper::TestInsertNothingL()
{
INFO_PRINTF1(_L("Testing Inserting nothing"));
//Get size of file before
RFile theFile;
User::LeaveIfError(theFile.Open(iFs, KSELFFileName(), EFileRead));
CleanupClosePushL(theFile);
TInt previousFileSize = 0;
User::LeaveIfError(theFile.Size(previousFileSize));
CleanupStack::PopAndDestroy(&theFile);
INFO_PRINTF2(_L("The test file before is [0x%X] bytes"), previousFileSize);
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileName()));
INFO_PRINTF3(_L("CSELFEditor::NewL(%S) returns [%d]"), &KSELFFileName, err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 1);
T_SELFLIB_ASSERT_TRUE(editor != NULL, 1);
CleanupStack::PushL(editor);
//Update having made no updates
INFO_PRINTF1(_L("Updating the ELF file"));
TRAP(err, editor->WriteELFUpdatesL());
CleanupStack::PopAndDestroy(editor);
//Now get the file size again, should be the same
TInt currentFileSize = 0;
User::LeaveIfError(theFile.Open(iFs, KSELFFileName(), EFileRead));
CleanupClosePushL(theFile);
User::LeaveIfError(theFile.Size(currentFileSize));
INFO_PRINTF2(_L("The test file after is [0x%X] bytes"), currentFileSize);
CleanupStack::PopAndDestroy(&theFile);
T_SELFLIB_ASSERT_TRUE(currentFileSize == previousFileSize, 0);
}
/**
* Logs an ELF header to the test logs
* @param aHeader Header to log
*/
void CSELFLibWrapper::LogELFHeader(const Elf32_Ehdr& aHeader)
{
INFO_PRINTF1(_L("The ELF Header looks like:"));
INFO_PRINTF2(_L("\te_type:\t\t0x%X"), aHeader.e_type);
INFO_PRINTF2(_L("\te_version:\t0x%X"), aHeader.e_version);
INFO_PRINTF2(_L("\te_machine:\t0x%X"), aHeader.e_machine);
INFO_PRINTF2(_L("\te_entry:\t0x%X"), aHeader.e_entry);
INFO_PRINTF2(_L("\te_phoff:\t0x%X"), aHeader.e_phoff);
INFO_PRINTF2(_L("\te_shoff:\t0x%X"), aHeader.e_shoff);
INFO_PRINTF2(_L("\te_flags:\t0x%X"), aHeader.e_flags);
INFO_PRINTF2(_L("\te_ehsize:\t0x%X"), aHeader.e_ehsize);
INFO_PRINTF2(_L("\te_phentsize:\t0x%X"), aHeader.e_phentsize);
INFO_PRINTF2(_L("\te_phnum:\t0x%X"), aHeader.e_phnum);
INFO_PRINTF2(_L("\te_shentsize:\t0x%X"), aHeader.e_shentsize);
INFO_PRINTF2(_L("\te_shnum:\t0x%X"), aHeader.e_shnum);
INFO_PRINTF2(_L("\te_shstrndx:\t0x%X"), aHeader.e_shstrndx);
}
void CSELFLibWrapper::TestPerformanceL()
{
INFO_PRINTF1(_L("Testing performance"));
//Use case 1: Normal use case, insert 1 variant specific data segment
TUint startTick = User::NTickCount();
CSELFEditor* editor = NULL;
editor = CSELFEditor::NewLC(KSELFFileName());
editor->InsertVariantSpecificDataL(KTestData1());
editor->WriteELFUpdatesL();
TUint stopTick = User::NTickCount();
TReal seconds = (TReal)(stopTick - startTick)/(TReal)HelpTicksPerSecond();
INFO_PRINTF2(_L("Inserting one segment takes %f seconds"), seconds);
CleanupStack::PopAndDestroy(editor);
//Use case 2: Lots of inserts
//Get size of file before
RFile theFile;
User::LeaveIfError(theFile.Open(iFs, KSELFFileName(), EFileRead));
CleanupClosePushL(theFile);
TInt startingFileSize = 0;
User::LeaveIfError(theFile.Size(startingFileSize));
CleanupStack::PopAndDestroy(&theFile);
TInt prenumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments before the test"), prenumsegments);
editor = CSELFEditor::NewLC(KSELFFileName());
INFO_PRINTF1(_L("Inserting the variant specific data"));
static const int numToTest = 50;
startTick = User::NTickCount();
for(TUint i = 0; i < numToTest; i++)
{
editor->InsertVariantSpecificDataL(KTestData1());
}
INFO_PRINTF1(_L("Updating the ELF file"));
editor->WriteELFUpdatesL();
stopTick = User::NTickCount();
seconds = (TReal)(stopTick - startTick)/(TReal)HelpTicksPerSecond();
CleanupStack::PopAndDestroy(editor);
TInt postnumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments after the test"), postnumsegments);
T_SELFLIB_ASSERT_TRUE(prenumsegments + numToTest == postnumsegments, 0);
INFO_PRINTF4(_L("Starting file size: 0x%X %d and took %f seconds"), startingFileSize, startingFileSize, seconds);
}
/**
* Tests we can insert a large amount of data into the ELF file
* @leave ONe of the system wide codes
*/
void CSELFLibWrapper::TestStressL()
{
INFO_PRINTF1(_L("Testing CSELFEditor Insert Large amount of Variant Sepcific data"));
//Get the number of variant data segments there before
TInt prenumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments before the test"), prenumsegments);
RBuf8 largeData;
largeData.CreateL(KLargeDataSize);
largeData.CleanupClosePushL();
CSELFEditor* editor = NULL;
TRAPD(err, editor = CSELFEditor::NewL(KSELFFileName()));
INFO_PRINTF2(_L("getting %d"), err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 1);
T_SELFLIB_ASSERT_TRUE(editor != NULL, 1);
CleanupStack::PushL(editor);
INFO_PRINTF1(_L("Inserting the variant specific"));
TRAP(err, editor->InsertVariantSpecificDataL(largeData));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
INFO_PRINTF1(_L("Updating the ELF file"));
TRAP(err, editor->WriteELFUpdatesL());
INFO_PRINTF2(_L("ELF File updating returned [%d]"), err);
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
CleanupStack::PopAndDestroy(editor);
TInt postnumsegments = GetNumberofVariantSegmentsL(KSELFFileName());
INFO_PRINTF2(_L("There are [0x%X] variant data segments after the test"),postnumsegments);
T_SELFLIB_ASSERT_TRUE(prenumsegments + 1 == postnumsegments, 0);
TInt bufferRequired = GetVariantSegmentSizeL(postnumsegments - 1, KSELFFileName());
RBuf8 data;
data.CreateL(bufferRequired);
data.CleanupClosePushL();
TRAP(err, GetVariantSegmentDataL(postnumsegments - 1, data, KSELFFileName()));
T_SELFLIB_ASSERT_TRUE(KErrNone == err, 2);
T_SELFLIB_ASSERT_TRUE(0 == largeData.Compare(data), 2);
INFO_PRINTF1(_L("Data looks good"));
CleanupStack::PopAndDestroy(&data);
CleanupStack::PopAndDestroy(&largeData);
}
/**
* Returns the number of nanokernel ticks in one second
* @return Number of nanokernel ticks. 0 if unsuccesful
*/
TInt CSELFLibWrapper::HelpTicksPerSecond()
{
TInt nanokernel_tick_period;
HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
static const TInt KOneMillion = 1000000;
return KOneMillion/nanokernel_tick_period;
}
/**
* Utility to get the number of variant data segments in the file
* @leave One of the system wide codes
*/
TInt CSELFLibWrapper::GetNumberofVariantSegmentsL(const TDesC& aFilename)
{
RFile elfFile;
User::LeaveIfError(elfFile.Open(iFs, aFilename, EFileRead));
CleanupClosePushL(elfFile);
READ_STRUCTL(Elf32_Ehdr, ehdr, elfFile, 0);
TUint count = 0;
//Now go through program headers and count relevant dhdrs
for(TUint i = 0; i < ehdr.e_phnum; i++)
{
READ_STRUCTL(Elf32_Phdr, phdr, elfFile, ehdr.e_phoff + (i * sizeof(Elf32_Phdr)));
if(phdr.p_type == PT_NOTE)
{
READ_STRUCTL(Sym32_dhdr, dhdr, elfFile, phdr.p_offset);
if(dhdr.d_type == ESYM_NOTE_VARIANT_DATA)
++count;
}
}
CleanupStack::PopAndDestroy(&elfFile);
return count;
}
/**
* Gets the size of the aIndexth variant segment element we find
* in the ELF file
* @param aIndex Index of the segment of interest
* @return The size required to read this data
* @leave KErrNotFound if the index is wrong or one of the system wide codes
*/
TInt CSELFLibWrapper::GetVariantSegmentSizeL(const TUint aIndex, const TDesC& aFilename)
{
RFile elfFile;
User::LeaveIfError(elfFile.Open(iFs, aFilename, EFileRead));
CleanupClosePushL(elfFile);
READ_STRUCTL(Elf32_Ehdr, ehdr, elfFile, 0);
TUint count = 0;
//Now go through program headers and count relevant dhdrs
for(TUint i = 0; i < ehdr.e_phnum; i++)
{
READ_STRUCTL(Elf32_Phdr, phdr, elfFile, ehdr.e_phoff + (i * sizeof(Elf32_Phdr)));
if(phdr.p_type == PT_NOTE)
{
READ_STRUCTL(Sym32_dhdr, dhdr, elfFile, phdr.p_offset);
if(dhdr.d_type == ESYM_NOTE_VARIANT_DATA)
{
if(count == aIndex)
{
READ_STRUCTL(Sym32_variant_spec_data, vdata, elfFile, phdr.p_offset + sizeof(Sym32_dhdr));
CleanupStack::PopAndDestroy(&elfFile);
return vdata.es_size;
}
count++;
}
}
}
User::Leave(KErrNotFound);
return 0; //avoid warnings
}
/**
* Gets the data of the aIndexth variant segment element we find
* in the ELF file
* @param aIndex Index of the segment of interest
* @param aData buffer to hold data
* @leave KErrNotFound if the index is wrong or one of the system wide codes
*/
void CSELFLibWrapper::GetVariantSegmentDataL(TUint aIndex, TDes8& aData, const TDesC& aFilename)
{
RFile elfFile;
User::LeaveIfError(elfFile.Open(iFs, aFilename, EFileRead));
CleanupClosePushL(elfFile);
READ_STRUCTL(Elf32_Ehdr, ehdr, elfFile, 0);
TUint count = 0;
//Now go through program headers and count relevant dhdrs
for(TUint i = 0; i < ehdr.e_phnum; i++)
{
READ_STRUCTL(Elf32_Phdr, phdr, elfFile, ehdr.e_phoff + (i * sizeof(Elf32_Phdr)));
if(phdr.p_type == PT_NOTE)
{
READ_STRUCTL(Sym32_dhdr, dhdr, elfFile, phdr.p_offset);
if(dhdr.d_type == ESYM_NOTE_VARIANT_DATA)
{
if(count == aIndex)
{
READ_STRUCTL(Sym32_variant_spec_data, vdata, elfFile, phdr.p_offset + sizeof(Sym32_dhdr));
if(aData.MaxLength() < vdata.es_size)
{
User::Leave(KErrTooBig);
}
//read the data
elfFile.Read(vdata.es_data, aData);
CleanupStack::PopAndDestroy(&elfFile);
return;
}
count++;
}
}
}
User::Leave(KErrNotFound);
}
/**
* Copies test files from not writable z:\ drive to writable place
* @leave One of the system wide codes
*/
void CSELFLibWrapper::CopyFilesToWritablePlaceL()
{
INFO_PRINTF1(_L("Copying the files and setting correct attributes"));
BaflUtils::EnsurePathExistsL(iFs, KSELFFileName);
TUint attToRemove = KEntryAttReadOnly;
TUint attToSet = 0;
User::LeaveIfError(BaflUtils::CopyFile(iFs, KROMSELFFileName, KSELFFileName));
iFs.SetAtt(KSELFFileName, attToSet, attToRemove);
User::LeaveIfError(BaflUtils::CopyFile(iFs, KROMSELFFileNameInvalidBySignature, KSELFFileNameInvalidBySignature));
iFs.SetAtt(KSELFFileNameInvalidBySignature, attToSet, attToRemove);
User::LeaveIfError(BaflUtils::CopyFile(iFs, KROMSELFFileNameTiny, KSELFFileNameTiny));
iFs.SetAtt(KSELFFileNameTiny, attToSet, attToRemove);
User::LeaveIfError(BaflUtils::CopyFile(iFs, KROMSELFFileNameExe, KSELFFileNameExe));
iFs.SetAtt(KSELFFileNameExe, attToSet, attToRemove);
}
/**
* Cleans the files copied by CopyFilesToWritablePlaceL() to tidy up
*/
void CSELFLibWrapper::TearDownFilesL()
{
INFO_PRINTF1(_L("Deleting the files"));
User::LeaveIfError(BaflUtils::DeleteFile(iFs, KSELFFileName));
User::LeaveIfError(BaflUtils::DeleteFile(iFs, KSELFFileNameInvalidBySignature));
User::LeaveIfError(BaflUtils::DeleteFile(iFs, KSELFFileNameTiny));
User::LeaveIfError(BaflUtils::DeleteFile(iFs, KSELFFileNameExe));
}