cellular/telephonysettings/xqbindings/psetwrapper/tsrc/common/testutilities.cpp
branchRCL_3
changeset 19 7d48bed6ce0c
--- /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 <QByteArray>
+#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<void*> 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<int>(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;
+}