diff -r 594d59766373 -r 7d48bed6ce0c cellular/telephonysettings/xqbindings/psetwrapper/tsrc/common/testutilities.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cellular/telephonysettings/xqbindings/psetwrapper/tsrc/common/testutilities.cpp Tue Aug 31 15:45:17 2010 +0300 @@ -0,0 +1,251 @@ +/* +* 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: +* +*/ + +#include +#include "testutilities.h" + +/*! + Replaces global new operator for utilizing binary. Enables OOM + simulation and memory leak detection. + + Note that creation of CBase derived Symbian classes + are not tracked, because CBase overloads new operator. + */ +void* operator new(std::size_t sz) throw(std::bad_alloc) +{ + return MemoryAllocator::alloc(sz); +} + +/*! + Replaces global delete operator for utilizing binary. Enables OOM + simulation and memory leak detection. + */ +void operator delete(void* memoryAddr) throw() +{ + return MemoryAllocator::free(memoryAddr); +} + +void* operator new(std::size_t sz, const std::nothrow_t&) throw() +{ + return qMalloc(sz); +} + +void operator delete(void* memoryAddress, const std::nothrow_t&) throw() +{ + if (NULL != memoryAddress) { + qFree(memoryAddress); + } +} + +bool MemoryAllocator::m_isOomSimulationEnabled = false; +int MemoryAllocator::m_numOfAllocsSinceLastFail = 0; +int MemoryAllocator::m_allocFailIndex = 1; +QList MemoryAllocator::m_allocList; + +/*! + MemoryAllocator::enableOomSimulation + */ +void MemoryAllocator::enableOomSimulation() +{ + m_isOomSimulationEnabled = true; + m_allocFailIndex = 1; + m_numOfAllocsSinceLastFail = 0; +} + +/*! + MemoryAllocator::disableOomSimulation + */ +void MemoryAllocator::disableOomSimulation() +{ + m_isOomSimulationEnabled = false; +} + +/*! + MemoryAllocator::isOomSimulationEnabled + */ +bool MemoryAllocator::isOomSimulationEnabled() +{ + return m_isOomSimulationEnabled; +} + +/*! + MemoryAllocator::currentAllocFailIndex + */ +int MemoryAllocator::currentAllocFailIndex() +{ + return m_allocFailIndex; +} + +/*! + MemoryAllocator::alloc + */ +void* MemoryAllocator::alloc(std::size_t sz) +{ + if (isOomSimulationEnabled()) { + m_numOfAllocsSinceLastFail++; + if (m_allocFailIndex == m_numOfAllocsSinceLastFail) { + m_allocFailIndex++; + m_numOfAllocsSinceLastFail = 0; +#ifdef QT_NO_EXCEPTIONS + return NULL; +#else + throw std::bad_alloc(); +#endif + } + } + + void *allocatedMemoryAddr = qMalloc(sz); + m_allocList.append(allocatedMemoryAddr); + return allocatedMemoryAddr; +} + +/*! + MemoryAllocator::free + */ +void MemoryAllocator::free(void *memoryAddress) +{ + if (memoryAddress) { + int index = m_allocList.indexOf(memoryAddress); + if (-1 != index) { + m_allocList.removeAt(index); + } + qFree(memoryAddress); + } +} + +/*! + MemoryAllocator::verifyMemoryAllocations + */ +void MemoryAllocator::verifyMemoryAllocations() +{ + int numOfUnfreedCells = m_allocList.count(); + if (0 != numOfUnfreedCells) { + for ( int i = 0; i < numOfUnfreedCells; i++) { + qDebug("UNFREED CELL: %x", reinterpret_cast(m_allocList.at(i))); + } + + m_allocList.clear(); + throw std::bad_alloc(); + } + + m_allocList.clear(); +} + + +/*! + OomTestExecuter::runTest + */ +void OomTestExecuter::runTest( + QObject &testObject, const char *testMethod) +{ + qDebug() << "OomTestExecuter::runTest : IN :" << testMethod; + + MemoryAllocator::enableOomSimulation(); + + bool exceptionCaught = false; + do { + exceptionCaught = false; + int currentAllocFailIndex = MemoryAllocator::currentAllocFailIndex(); + + try { + try { + QMetaObject::invokeMethod( + &testObject, "init", Qt::DirectConnection); + QMetaObject::invokeMethod( + &testObject, testMethod, Qt::DirectConnection); + } catch (const std::bad_alloc &ex) { + exceptionCaught = true; + QMetaObject::invokeMethod( + &testObject, "cleanup", Qt::DirectConnection); + } + // TODO: for some reason bad_alloc exception is corrupted to + // unknown exception and nested catch block is needed to be able to + // handle situation. One level catch does not work for some reason. + } catch (...) { + exceptionCaught = true; + QMetaObject::invokeMethod( + &testObject, "cleanup", Qt::DirectConnection); + if (currentAllocFailIndex == MemoryAllocator::currentAllocFailIndex()) { + qDebug() << "OomTestExecuter::runTest, ERROR: unexpected exception!"; + throw; + } + } + } while(exceptionCaught); + + QMetaObject::invokeMethod(&testObject, "cleanup", Qt::DirectConnection); + MemoryAllocator::disableOomSimulation(); + qDebug() << "OomTestExecuter::runTest : OUT :" << testMethod; +} + +/*! + OomTestExecuter::runAllTests + */ +void OomTestExecuter::runAllTests( + QObject &testObject, const char *callingTestMethod) +{ + const QMetaObject *metaObject = testObject.metaObject(); + + int methodCount = metaObject->methodCount(); + for (int i = 0; i < methodCount; ++i) { + QMetaMethod slotMethodCandidate = metaObject->method(i); + if (!isValidSlot(slotMethodCandidate)) { + continue; + } + + QByteArray slotMethodName(slotMethodCandidate.signature()); + // remove parentheses + slotMethodName = slotMethodName.left(slotMethodName.length() - 2); + + // Prevent from infinite loop and do not execute test method, which + // has called runAllTests. + if (slotMethodName != callingTestMethod) { + runTest(testObject, slotMethodName); + } + } +} + +/*! + OomTestExecuter::isValidSlot + */ +bool OomTestExecuter::isValidSlot(const QMetaMethod &sl) +{ + if ((sl.access() != QMetaMethod::Private) || !sl.parameterTypes().isEmpty() + || qstrlen(sl.typeName()) || (sl.methodType() != QMetaMethod::Slot)) { + return false; + } + + const char *sig = sl.signature(); + int len = qstrlen(sig); + if (len < 2) { + return false; + } + + if (sig[len - 2] != '(' || sig[len - 1] != ')') { + return false; + } + + if (len > 7 && strcmp(sig + (len - 7), "_data()") == 0) { + return false; + } + + if ((strcmp(sig, "initTestCase()") == 0) || (strcmp(sig, "cleanupTestCase()") == 0) + || (strcmp(sig, "cleanup()") == 0) || (strcmp(sig, "init()") == 0)) { + return false; + } + + return true; +}