cellular/telephonysettings/xqbindings/psetwrapper/tsrc/common/testutilities.cpp
branchRCL_3
changeset 20 987c9837762f
parent 19 7d48bed6ce0c
child 21 0a6dd2dc9970
equal deleted inserted replaced
19:7d48bed6ce0c 20:987c9837762f
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <QByteArray>
       
    19 #include "testutilities.h"
       
    20 
       
    21 /*!
       
    22   Replaces global new operator for utilizing binary. Enables OOM 
       
    23   simulation and memory leak detection.
       
    24   
       
    25   Note that creation of CBase derived Symbian classes 
       
    26   are not tracked, because CBase overloads new operator. 
       
    27  */
       
    28 void* operator new(std::size_t sz) throw(std::bad_alloc)
       
    29 {
       
    30     return MemoryAllocator::alloc(sz);
       
    31 }
       
    32 
       
    33 /*!
       
    34   Replaces global delete operator for utilizing binary. Enables OOM 
       
    35   simulation and memory leak detection. 
       
    36  */
       
    37 void operator delete(void* memoryAddr) throw()
       
    38 {
       
    39     return MemoryAllocator::free(memoryAddr);
       
    40 }
       
    41 
       
    42 void* operator new(std::size_t sz, const std::nothrow_t&) throw()
       
    43 {
       
    44     return qMalloc(sz);
       
    45 }
       
    46 
       
    47 void  operator delete(void* memoryAddress, const std::nothrow_t&) throw()
       
    48 {
       
    49     if (NULL != memoryAddress) {
       
    50         qFree(memoryAddress);
       
    51     }
       
    52 }
       
    53 
       
    54 bool MemoryAllocator::m_isOomSimulationEnabled = false;
       
    55 int MemoryAllocator::m_numOfAllocsSinceLastFail = 0;
       
    56 int MemoryAllocator::m_allocFailIndex = 1;
       
    57 QList<void*> MemoryAllocator::m_allocList;
       
    58 
       
    59 /*!
       
    60   MemoryAllocator::enableOomSimulation
       
    61  */
       
    62 void MemoryAllocator::enableOomSimulation()
       
    63 {
       
    64     m_isOomSimulationEnabled = true;
       
    65     m_allocFailIndex = 1;
       
    66     m_numOfAllocsSinceLastFail = 0;
       
    67 }
       
    68 
       
    69 /*!
       
    70   MemoryAllocator::disableOomSimulation
       
    71  */
       
    72 void MemoryAllocator::disableOomSimulation()
       
    73 {
       
    74     m_isOomSimulationEnabled = false;
       
    75 }
       
    76 
       
    77 /*!
       
    78   MemoryAllocator::isOomSimulationEnabled
       
    79  */
       
    80 bool MemoryAllocator::isOomSimulationEnabled()
       
    81 {
       
    82     return m_isOomSimulationEnabled;
       
    83 }
       
    84 
       
    85 /*!
       
    86   MemoryAllocator::currentAllocFailIndex
       
    87  */
       
    88 int MemoryAllocator::currentAllocFailIndex()
       
    89 {
       
    90     return m_allocFailIndex;
       
    91 }
       
    92 
       
    93 /*!
       
    94   MemoryAllocator::alloc
       
    95  */
       
    96 void* MemoryAllocator::alloc(std::size_t sz)
       
    97 {
       
    98     if (isOomSimulationEnabled()) {
       
    99         m_numOfAllocsSinceLastFail++;
       
   100         if (m_allocFailIndex == m_numOfAllocsSinceLastFail) {
       
   101             m_allocFailIndex++;
       
   102             m_numOfAllocsSinceLastFail = 0;
       
   103 #ifdef QT_NO_EXCEPTIONS
       
   104             return NULL;
       
   105 #else
       
   106             throw std::bad_alloc();
       
   107 #endif
       
   108         }
       
   109     }
       
   110     
       
   111     void *allocatedMemoryAddr = qMalloc(sz);
       
   112     m_allocList.append(allocatedMemoryAddr);
       
   113     return allocatedMemoryAddr;
       
   114 }
       
   115 
       
   116 /*!
       
   117   MemoryAllocator::free
       
   118  */
       
   119 void MemoryAllocator::free(void *memoryAddress)
       
   120 {
       
   121     if (memoryAddress) {
       
   122         int index = m_allocList.indexOf(memoryAddress);
       
   123         if (-1 != index) {
       
   124             m_allocList.removeAt(index);
       
   125         }
       
   126         qFree(memoryAddress);
       
   127     }
       
   128 }
       
   129 
       
   130 /*!
       
   131   MemoryAllocator::verifyMemoryAllocations
       
   132  */
       
   133 void MemoryAllocator::verifyMemoryAllocations()
       
   134 {
       
   135     int numOfUnfreedCells = m_allocList.count();
       
   136     if (0 != numOfUnfreedCells) {
       
   137         for ( int i = 0; i < numOfUnfreedCells; i++) {
       
   138             qDebug("UNFREED CELL: %x", reinterpret_cast<int>(m_allocList.at(i)));
       
   139         }
       
   140     
       
   141     m_allocList.clear();
       
   142     throw std::bad_alloc();
       
   143     }
       
   144     
       
   145     m_allocList.clear();
       
   146 }
       
   147 
       
   148 
       
   149 /*!
       
   150   OomTestExecuter::runTest
       
   151  */
       
   152 void OomTestExecuter::runTest(
       
   153     QObject &testObject, const char *testMethod)
       
   154 {
       
   155     qDebug() << "OomTestExecuter::runTest : IN :" << testMethod;
       
   156     
       
   157     MemoryAllocator::enableOomSimulation();
       
   158 
       
   159     bool exceptionCaught = false;
       
   160     do {
       
   161         exceptionCaught = false;
       
   162         int currentAllocFailIndex = MemoryAllocator::currentAllocFailIndex();
       
   163         
       
   164         try {
       
   165             try {
       
   166                 QMetaObject::invokeMethod(
       
   167                     &testObject, "init", Qt::DirectConnection);
       
   168                 QMetaObject::invokeMethod(
       
   169                     &testObject, testMethod, Qt::DirectConnection);
       
   170             } catch (const std::bad_alloc &ex) {
       
   171                 exceptionCaught = true;
       
   172                 QMetaObject::invokeMethod(
       
   173                     &testObject, "cleanup", Qt::DirectConnection);
       
   174             }
       
   175         // TODO: for some reason bad_alloc exception is corrupted to 
       
   176         // unknown exception and nested catch block is needed to be able to
       
   177         // handle situation. One level catch does not work for some reason.
       
   178         } catch (...) {
       
   179             exceptionCaught = true;
       
   180             QMetaObject::invokeMethod(
       
   181                 &testObject, "cleanup", Qt::DirectConnection);
       
   182             if (currentAllocFailIndex == MemoryAllocator::currentAllocFailIndex()) {
       
   183                 qDebug() << "OomTestExecuter::runTest, ERROR: unexpected exception!";
       
   184                 throw;
       
   185             }
       
   186         }
       
   187     } while(exceptionCaught);
       
   188     
       
   189     QMetaObject::invokeMethod(&testObject, "cleanup", Qt::DirectConnection);
       
   190     MemoryAllocator::disableOomSimulation();
       
   191     qDebug() << "OomTestExecuter::runTest : OUT :" << testMethod;
       
   192 }
       
   193 
       
   194 /*!
       
   195   OomTestExecuter::runAllTests
       
   196  */
       
   197 void OomTestExecuter::runAllTests(
       
   198     QObject &testObject, const char *callingTestMethod)
       
   199 {
       
   200     const QMetaObject *metaObject = testObject.metaObject();
       
   201     
       
   202     int methodCount = metaObject->methodCount();
       
   203     for (int i = 0; i < methodCount; ++i) {
       
   204         QMetaMethod slotMethodCandidate = metaObject->method(i);
       
   205         if (!isValidSlot(slotMethodCandidate)) {
       
   206             continue;
       
   207         }
       
   208         
       
   209         QByteArray slotMethodName(slotMethodCandidate.signature());
       
   210         // remove parentheses
       
   211         slotMethodName = slotMethodName.left(slotMethodName.length() - 2);
       
   212         
       
   213         // Prevent from infinite loop and do not execute test method, which
       
   214         // has called runAllTests.
       
   215         if (slotMethodName != callingTestMethod) {
       
   216             runTest(testObject, slotMethodName);
       
   217         }
       
   218     }
       
   219 }
       
   220 
       
   221 /*!
       
   222   OomTestExecuter::isValidSlot
       
   223  */
       
   224 bool OomTestExecuter::isValidSlot(const QMetaMethod &sl)
       
   225 {
       
   226     if ((sl.access() != QMetaMethod::Private) || !sl.parameterTypes().isEmpty()
       
   227         || qstrlen(sl.typeName()) || (sl.methodType() != QMetaMethod::Slot)) {
       
   228         return false;
       
   229     }
       
   230     
       
   231     const char *sig = sl.signature();
       
   232     int len = qstrlen(sig);
       
   233     if (len < 2) {
       
   234         return false;
       
   235     }
       
   236     
       
   237     if (sig[len - 2] != '(' || sig[len - 1] != ')') {
       
   238         return false;
       
   239     }
       
   240     
       
   241     if (len > 7 && strcmp(sig + (len - 7), "_data()") == 0) {
       
   242         return false;
       
   243     }
       
   244     
       
   245     if ((strcmp(sig, "initTestCase()") == 0) || (strcmp(sig, "cleanupTestCase()") == 0)
       
   246         || (strcmp(sig, "cleanup()") == 0) || (strcmp(sig, "init()") == 0)) {
       
   247         return false;
       
   248     }
       
   249     
       
   250     return true;
       
   251 }