diff options
author | Harald Fernengel <harald@trolltech.com> | 2009-08-03 15:12:46 +0200 |
---|---|---|
committer | Harald Fernengel <harald@trolltech.com> | 2009-08-03 15:12:46 +0200 |
commit | 41a83e1ff19ad1396e6001e6b0ac003c701ba55a (patch) | |
tree | 609e40eda10418bbf925002c36552074796b96b6 /tests/auto | |
parent | d1f3b9df2bc5c57d414da73a7d4f9ed7b25df3db (diff) | |
download | qt4-tools-41a83e1ff19ad1396e6001e6b0ac003c701ba55a.tar.gz |
Squashed commit of the topic/exceptions branch.
Contains some smaller fixes and renaming of macros. Looks big,
but isn't scary at all ;)
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/exceptionsafety_objects/oomsimulator.h | 158 | ||||
-rw-r--r-- | tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp | 257 | ||||
-rw-r--r-- | tests/auto/qfiledialog/tst_qfiledialog.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qglobal/tst_qglobal.cpp | 10 | ||||
-rw-r--r-- | tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp | 2 | ||||
-rw-r--r-- | tests/auto/symbian/qmainexceptions/tst_qmainexceptions.cpp | 156 |
7 files changed, 501 insertions, 86 deletions
diff --git a/tests/auto/exceptionsafety_objects/oomsimulator.h b/tests/auto/exceptionsafety_objects/oomsimulator.h index 3c8b389f3b..11dd769fdb 100644 --- a/tests/auto/exceptionsafety_objects/oomsimulator.h +++ b/tests/auto/exceptionsafety_objects/oomsimulator.h @@ -39,10 +39,29 @@ ** ****************************************************************************/ +#ifndef Q_OS_SYMBIAN #include <malloc.h> +#endif #include <limits.h> -#include "3rdparty/memcheck.h" +#include <stdio.h> +#include <exception> +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) +# include "3rdparty/memcheck.h" +#endif + +static bool mallocFailActive = false; +static int mallocFailIndex = 0; +static int mallocCount = 0; + +static void my_terminate_handler() +{ + // set a breakpoint here to get a backtrace for your uncaught exceptions + fprintf(stderr, "Uncaught Exception Detected. Set a breakpoint in my_terminate_handler()\n"); + exit(1); +} + +#ifdef __GLIBC__ /* Use glibc's memory allocation hooks */ /* our hooks */ @@ -88,40 +107,6 @@ void my_init_hook() enableHooks(); } -static bool mallocFailActive = false; -static int mallocFailIndex = 0; -static int mallocCount = 0; - -struct AllocFailer -{ - inline AllocFailer() { mallocFailActive = true; setAllocFailIndex(0); } - inline ~AllocFailer() { deactivate(); } - - inline void setAllocFailIndex(int index) - { - if (RUNNING_ON_VALGRIND) { - VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(VALGRIND_GET_ALLOC_INDEX + index + 1); - } else { - mallocFailIndex = index; - } - } - - inline void deactivate() - { - mallocFailActive = false; - VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(INT_MAX); - } - - inline int currentAllocIndex() const - { - if (RUNNING_ON_VALGRIND) { - return VALGRIND_GET_ALLOC_INDEX; - } else { - return mallocCount; - } - } -}; - void *my_malloc_hook(size_t size, const void *) { ++mallocCount; @@ -173,6 +158,98 @@ void my_free_hook(void *ptr, const void *) __free_hook = my_free_hook; } +#elif defined(Q_CC_MSVC) + +#include "crtdbg.h" + +static int qCrtAllocHook(int allocType, void * /*userData*/, size_t /*size*/, + int blockType, long /*requestNumber*/, + const unsigned char * /*filename*/, int /*lineNumber*/) +{ + if (blockType == _CRT_BLOCK) + return TRUE; // ignore allocations from the C library + + switch (allocType) { + case _HOOK_ALLOC: + case _HOOK_REALLOC: + ++mallocCount; + if (mallocFailActive && --mallocFailIndex < 0) + return FALSE; // simulate OOM + } + + return TRUE; +} + +static struct QCrtDebugRegistrator +{ + QCrtDebugRegistrator() + { + _CrtSetAllocHook(qCrtAllocHook); + } + +} crtDebugRegistrator; + +#endif + +struct AllocFailer +{ + inline AllocFailer(int index) { reactivateAt(index); } + inline ~AllocFailer() { deactivate(); } + + inline void reactivateAt(int index) + { +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) + VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(VALGRIND_GET_ALLOC_INDEX + index + 1); +#elif defined(Q_OS_SYMBIAN) + // symbian alloc fail index is 1 based + __UHEAP_BURSTFAILNEXT(index+1, KMaxTUint16); +#endif + mallocFailIndex = index; + mallocFailActive = true; + } + + inline void deactivate() + { + mallocFailActive = false; +#ifdef RUNNING_ON_VALGRIND + VALGRIND_ENABLE_OOM_AT_ALLOC_INDEX(0); +#elif defined(Q_OS_SYMBIAN) + __UHEAP_RESET; +#endif + } + + inline int currentAllocIndex() const + { +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) + return VALGRIND_GET_ALLOC_INDEX; +#endif + return mallocCount; + } + + static bool initialize() + { + std::set_terminate(my_terminate_handler); +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) { + if (VALGRIND_GET_ALLOC_INDEX == -1u) { + qWarning("You must use a valgrind with oom simulation support"); + return false; + } + // running in valgrind - don't use glibc hooks + disableHooks(); + + // never stop simulating OOM + VALGRIND_DISABLE_OOM_AT_ALLOC_INDEX(-1u); + } +#endif + return true; + } +}; + +#ifndef Q_OS_SYMBIAN + static void *new_helper(std::size_t size) { void *ptr = malloc(size); @@ -181,6 +258,11 @@ static void *new_helper(std::size_t size) return ptr; } +#ifdef Q_CC_MSVC +# pragma warning(push) +# pragma warning(disable: 4290) +#endif + // overload operator new void* operator new(size_t size) throw (std::bad_alloc) { return new_helper(size); } void* operator new[](size_t size) throw (std::bad_alloc) { return new_helper(size); } @@ -193,6 +275,12 @@ void operator delete[](void *ptr) throw() { if (ptr) free(ptr); } void operator delete(void *ptr, const std::nothrow_t&) throw() { if (ptr) free(ptr); } void operator delete[](void *ptr, const std::nothrow_t&) throw() { if (ptr) free (ptr); } +#ifdef Q_CC_MSVC +# pragma warning(pop) +#endif + +#endif + // ignore placement new and placement delete - those don't allocate. diff --git a/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp b/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp index dd5f8da90d..c867899640 100644 --- a/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp +++ b/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp @@ -42,15 +42,21 @@ #include <QtGui/QtGui> #include <QtTest/QtTest> +#include <stddef.h> + QT_USE_NAMESPACE -// this test only works with GLIBC (let moc run regardless, because it doesn't know about __GLIBC__) -#if defined(QT_NO_EXCEPTIONS) || (!defined(__GLIBC__) && !defined(Q_MOC_RUN)) +// this test only works with +// * GLIBC +// * MSVC - only debug builds (we need the crtdbg.h helpers) +#if (defined(QT_NO_EXCEPTIONS) || (!defined(__GLIBC__) && !defined(Q_CC_MSVC) && !defined(Q_OS_SYMBIAN))) && !defined(Q_MOC_RUN) QTEST_NOOP_MAIN #else #include "oomsimulator.h" +#if !defined(Q_OS_SYMBIAN) #include "3rdparty/memcheck.h" +#endif class tst_ExceptionSafetyObjects: public QObject { @@ -70,7 +76,7 @@ private slots: // helper structs to create an arbitrary widget struct AbstractObjectCreator { - virtual QObject *create(QObject *parent) = 0; + virtual void test(QObject *parent) = 0; }; Q_DECLARE_METATYPE(AbstractObjectCreator *) @@ -78,9 +84,57 @@ Q_DECLARE_METATYPE(AbstractObjectCreator *) template <typename T> struct ObjectCreator : public AbstractObjectCreator { - QObject *create(QObject *parent) + void test(QObject *) + { + QScopedPointer<T> ptr(new T); + } +}; + +struct BitArrayCreator : public AbstractObjectCreator +{ + void test(QObject *) + { QScopedPointer<QBitArray> bitArray(new QBitArray(100, true)); } +}; + +struct ByteArrayMatcherCreator : public AbstractObjectCreator +{ + void test(QObject *) + { QScopedPointer<QByteArrayMatcher> ptr(new QByteArrayMatcher("ralf test",8)); } +}; + +struct CryptographicHashCreator : public AbstractObjectCreator +{ + void test(QObject *) + { + QScopedPointer<QCryptographicHash> ptr(new QCryptographicHash(QCryptographicHash::Sha1)); + ptr->addData("ralf test",8); + } +}; + +struct DataStreamCreator : public AbstractObjectCreator +{ + void test(QObject *) { - return parent ? new T(parent) : new T; + QScopedPointer<QByteArray> arr(new QByteArray("hallo, test")); + QScopedPointer<QDataStream> ptr(new QDataStream(arr.data(), QIODevice::ReadWrite)); + ptr->writeBytes("ralf test",8); + } +}; + +struct DirCreator : public AbstractObjectCreator +{ + void test(QObject *) + { + QDir::cleanPath("../////././"); + QScopedPointer<QDir> ptr(new QDir(".")); + while( ptr->cdUp() ) + ; // just going up + ptr->count(); + ptr->exists(ptr->path()); + + QStringList filters; + filters << "*.cpp" << "*.cxx" << "*.cc"; + ptr->setNameFilters(filters); } }; @@ -90,46 +144,83 @@ void tst_ExceptionSafetyObjects::objects_data() #define NEWROW(T) QTest::newRow(#T) << static_cast<AbstractObjectCreator *>(new ObjectCreator<T >) NEWROW(QObject); + NEWROW(QBuffer); + NEWROW(QFile); + NEWROW(QProcess); + NEWROW(QSettings); + // NEWROW(QSocketNotifier); + NEWROW(QThread); + NEWROW(QThreadPool); + NEWROW(QTranslator); + NEWROW(QFSFileEngine); + +#define NEWROW2(T, CREATOR) QTest::newRow(#T) << static_cast<AbstractObjectCreator *>(new CREATOR) + NEWROW2(QBitArray, BitArrayCreator); + NEWROW2(QByteArrayMatcher, ByteArrayMatcherCreator); + NEWROW2(QCryptographicHash, CryptographicHashCreator); + NEWROW2(QDataStream, DataStreamCreator); + NEWROW2(QDir, DirCreator); + } // create and destructs an object, and lets each and every allocation // during construction and destruction fail. static void doOOMTest(AbstractObjectCreator *creator, QObject *parent) { - AllocFailer allocFailer; int currentOOMIndex = 0; bool caught = false; + bool done = false; - int allocStartIndex = 0; - int allocEndIndex = 0; - int lastAllocCount = 0; + AllocFailer allocFailer(0); + int allocCountBefore = allocFailer.currentAllocIndex(); do { - allocFailer.setAllocFailIndex(++currentOOMIndex); + allocFailer.reactivateAt(++currentOOMIndex); caught = false; - lastAllocCount = allocEndIndex - allocStartIndex; - allocStartIndex = allocFailer.currentAllocIndex(); try { - QScopedPointer<QObject> ptr(creator->create(parent)); + creator->test(parent); } catch (const std::bad_alloc &) { caught = true; + } catch (const std::exception &ex) { + if (strcmp(ex.what(), "autotest swallow") != 0) + throw; + caught = true; + } + + if (!caught) { + void *buf = malloc(42); + if (buf) { + // we got memory here - oom test is over. + free(buf); + done = true; + } } - allocEndIndex = allocFailer.currentAllocIndex(); +//#define REALLY_VERBOSE +#ifdef REALLY_VERBOSE + fprintf(stderr, " OOM Index: %d\n", currentOOMIndex); +#endif - } while (caught || allocEndIndex - allocStartIndex != lastAllocCount); + + } while (caught || !done); allocFailer.deactivate(); + +//#define VERBOSE +#ifdef VERBOSE + fprintf(stderr, "OOM Test done, checked allocs: %d (range %d - %d)\n", currentOOMIndex, + allocCountBefore, allocFailer.currentAllocIndex()); +#endif } -static bool alloc1Failed = false; -static bool alloc2Failed = false; -static bool alloc3Failed = false; -static bool alloc4Failed = false; -static bool malloc1Failed = false; -static bool malloc2Failed = false; +static int alloc1Failed = 0; +static int alloc2Failed = 0; +static int alloc3Failed = 0; +static int alloc4Failed = 0; +static int malloc1Failed = 0; +static int malloc2Failed = 0; // Tests that new, new[] and malloc() fail at least once during OOM testing. class SelfTestObject : public QObject @@ -138,54 +229,62 @@ public: SelfTestObject(QObject *parent = 0) : QObject(parent) { - try { delete new int; } catch (const std::bad_alloc &) { alloc1Failed = true; } - try { delete [] new double[5]; } catch (const std::bad_alloc &) { alloc2Failed = true; } + try { delete new int; } catch (const std::bad_alloc &) { ++alloc1Failed; throw; } + try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc2Failed; throw ;} void *buf = malloc(42); if (buf) free(buf); else - malloc1Failed = true; + ++malloc1Failed; } ~SelfTestObject() { - try { delete new int; } catch (const std::bad_alloc &) { alloc3Failed = true; } - try { delete [] new double[5]; } catch (const std::bad_alloc &) { alloc4Failed = true; } + try { delete new int; } catch (const std::bad_alloc &) { ++alloc3Failed; } + try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc4Failed; } void *buf = malloc(42); if (buf) free(buf); else - malloc2Failed = true; + ++malloc2Failed = true; } }; void tst_ExceptionSafetyObjects::initTestCase() { - if (RUNNING_ON_VALGRIND) { - QVERIFY2(VALGRIND_GET_ALLOC_INDEX != -1u, - "You must use a valgrind with oom simulation support"); - // running in valgrind - don't use glibc hooks - disableHooks(); - } + QVERIFY(AllocFailer::initialize()); // sanity check whether OOM simulation works - AllocFailer allocFailer; + AllocFailer allocFailer(0); // malloc fail index is 0 -> this malloc should fail. void *buf = malloc(42); + allocFailer.deactivate(); QVERIFY(!buf); // malloc fail index is 1 - second malloc should fail. - allocFailer.setAllocFailIndex(1); + allocFailer.reactivateAt(1); buf = malloc(42); + void *buf2 = malloc(42); + allocFailer.deactivate(); + QVERIFY(buf); free(buf); - buf = malloc(42); - QVERIFY(!buf); + QVERIFY(!buf2); - allocFailer.deactivate(); +#ifdef Q_OS_SYMBIAN + // temporary workaround for INC138398 + std::new_handler nh_func = std::set_new_handler(0); + (void) std::set_new_handler(nh_func); +#endif doOOMTest(new ObjectCreator<SelfTestObject>, 0); + QCOMPARE(alloc1Failed, 1); + QCOMPARE(alloc2Failed, 1); + QCOMPARE(alloc3Failed, 2); + QCOMPARE(alloc4Failed, 3); + QCOMPARE(malloc1Failed, 1); + QCOMPARE(malloc2Failed, 1); } void tst_ExceptionSafetyObjects::objects() @@ -198,23 +297,94 @@ void tst_ExceptionSafetyObjects::objects() template <typename T> struct WidgetCreator : public AbstractObjectCreator { - QObject *create(QObject *parent) + void test(QObject *parent) + { + Q_ASSERT(!parent || parent->isWidgetType()); + QScopedPointer<T> ptr(parent ? new T(static_cast<QWidget *>(parent)) : new T); + } +}; + +// QSizeGrip doesn't have a default constructor - always pass parent (even though it might be 0) +template <> struct WidgetCreator<QSizeGrip> : public AbstractObjectCreator +{ + void test(QObject *parent) { - return parent ? new T(static_cast<QWidget *>(parent)) : new T; + Q_ASSERT(!parent || parent->isWidgetType()); + QScopedPointer<QSizeGrip> ptr(new QSizeGrip(static_cast<QWidget *>(parent))); } }; +// QDesktopWidget doesn't need a parent. +template <> struct WidgetCreator<QDesktopWidget> : public AbstractObjectCreator +{ + void test(QObject *parent) + { + Q_ASSERT(!parent || parent->isWidgetType()); + QScopedPointer<QDesktopWidget> ptr(new QDesktopWidget()); + } +}; void tst_ExceptionSafetyObjects::widgets_data() { QTest::addColumn<AbstractObjectCreator *>("widgetCreator"); #undef NEWROW #define NEWROW(T) QTest::newRow(#T) << static_cast<AbstractObjectCreator *>(new WidgetCreator<T >) + NEWROW(QWidget); - NEWROW(QPushButton); - NEWROW(QLabel); + + NEWROW(QButtonGroup); + NEWROW(QDesktopWidget); + NEWROW(QCheckBox); + NEWROW(QComboBox); + NEWROW(QCommandLinkButton); + NEWROW(QDateEdit); + NEWROW(QDateTimeEdit); + NEWROW(QDial); + NEWROW(QDoubleSpinBox); + NEWROW(QFocusFrame); + NEWROW(QFontComboBox); NEWROW(QFrame); + NEWROW(QGroupBox); + NEWROW(QLCDNumber); + NEWROW(QLabel); + NEWROW(QLCDNumber); + NEWROW(QLineEdit); + NEWROW(QMenu); + NEWROW(QPlainTextEdit); + NEWROW(QProgressBar); + NEWROW(QPushButton); + NEWROW(QRadioButton); + NEWROW(QScrollArea); + NEWROW(QScrollBar); + NEWROW(QSizeGrip); + NEWROW(QSlider); + NEWROW(QSpinBox); + NEWROW(QSplitter); NEWROW(QStackedWidget); + NEWROW(QStatusBar); + NEWROW(QTabBar); + NEWROW(QTabWidget); + NEWROW(QTextBrowser); + NEWROW(QTextEdit); + NEWROW(QTimeEdit); + NEWROW(QToolBox); + NEWROW(QToolButton); + NEWROW(QStatusBar); + NEWROW(QSplitter); + NEWROW(QTextEdit); + NEWROW(QTextBrowser); + NEWROW(QToolBar); + NEWROW(QMenuBar); + NEWROW(QMainWindow); + NEWROW(QWorkspace); + NEWROW(QColumnView); + NEWROW(QListView); + NEWROW(QListWidget); + NEWROW(QTableView); + NEWROW(QTableWidget); + NEWROW(QTreeView); + NEWROW(QTreeWidget); + } void tst_ExceptionSafetyObjects::widgets() @@ -225,6 +395,9 @@ void tst_ExceptionSafetyObjects::widgets() QWidget parent; doOOMTest(widgetCreator, &parent); + + // if the test reaches here without crashing, we passed :) + QVERIFY(true); } QTEST_MAIN(tst_ExceptionSafetyObjects) diff --git a/tests/auto/qfiledialog/tst_qfiledialog.cpp b/tests/auto/qfiledialog/tst_qfiledialog.cpp index 19ea0b87ef..f412cfb8f9 100644 --- a/tests/auto/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/qfiledialog/tst_qfiledialog.cpp @@ -1353,7 +1353,7 @@ void tst_QFiledialog::heapCorruption() struct FriendlyQFileDialog : public QFileDialog { friend class tst_QFileDialog; - Q_DECLARE_PRIVATE(QFileDialog) + Q_DECLARE_SCOPED_PRIVATE(QFileDialog) }; diff --git a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp index c41f1d1f45..e6c003016f 100644 --- a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -770,7 +770,7 @@ void tst_QFileSystemModel::setData() class MyFriendFileSystemModel : public QFileSystemModel { friend class tst_QFileSystemModel; - Q_DECLARE_PRIVATE(QFileSystemModel) + Q_DECLARE_SCOPED_PRIVATE(QFileSystemModel) }; void tst_QFileSystemModel::sort_data() diff --git a/tests/auto/qglobal/tst_qglobal.cpp b/tests/auto/qglobal/tst_qglobal.cpp index 49e5d7de80..28556bea06 100644 --- a/tests/auto/qglobal/tst_qglobal.cpp +++ b/tests/auto/qglobal/tst_qglobal.cpp @@ -51,6 +51,7 @@ private slots: void for_each(); void qassert(); void qtry(); + void checkptr(); }; void tst_QGlobal::qIsNull() @@ -252,5 +253,14 @@ void tst_QGlobal::qtry() QCOMPARE(i, 4); } +void tst_QGlobal::checkptr() +{ + int i; + QCOMPARE(q_check_ptr(&i), &i); + + const char *c = "hello"; + QCOMPARE(q_check_ptr(c), c); +} + QTEST_MAIN(tst_QGlobal) #include "tst_qglobal.moc" diff --git a/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp index 85611e23b2..216fe8ac13 100644 --- a/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ b/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp @@ -1467,7 +1467,7 @@ static QModelIndex indexFromText(QStandardItemModel *model, const QString &text) struct FriendlyTreeView : public QTreeView { friend class tst_QStandardItemModel; - Q_DECLARE_PRIVATE(QTreeView) + Q_DECLARE_SCOPED_PRIVATE(QTreeView) }; void tst_QStandardItemModel::treeDragAndDrop() diff --git a/tests/auto/symbian/qmainexceptions/tst_qmainexceptions.cpp b/tests/auto/symbian/qmainexceptions/tst_qmainexceptions.cpp index adad544c3d..1601b7ed5f 100644 --- a/tests/auto/symbian/qmainexceptions/tst_qmainexceptions.cpp +++ b/tests/auto/symbian/qmainexceptions/tst_qmainexceptions.cpp @@ -41,6 +41,9 @@ #include <QtTest/QtTest> #include <e32base.h> +#include <typeinfo> +#include <stdexcept> +#include <euserhl.h> #ifdef Q_OS_SYMBIAN @@ -55,6 +58,7 @@ public: void TestSchedulerCatchesError(TLeavingFunc* f, int error); void TestSymbianRoundTrip(int leave, int trap); + void TestStdRoundTrip(const std::exception& thrown, const std::exception& caught); bool event(QEvent *event); @@ -72,6 +76,8 @@ private slots: void testDtor1(); void testDtor2(); void testNestedExceptions(); + void testScopedPointer(); + void testHybrid(); }; class CDummy : public CBase @@ -169,7 +175,7 @@ void ThrowBadAlloc() void TranslateThrowBadAllocL() { - QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(ThrowBadAlloc()); + QT_TRYCATCH_LEAVING(ThrowBadAlloc()); } void tst_qmainexceptions::testTranslateBadAlloc() @@ -186,7 +192,7 @@ void BigAlloc() void TranslateBigAllocL() { - QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(BigAlloc()); + QT_TRYCATCH_LEAVING(BigAlloc()); } void tst_qmainexceptions::testTranslateBigAlloc() @@ -199,13 +205,27 @@ void tst_qmainexceptions::TestSymbianRoundTrip(int leave, int trap) { // check that leave converted to exception, converted to error gives expected error code int trapped; - QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_ERROR( + QT_TRYCATCH_ERROR( trapped, - QT_TRANSLATE_SYMBIAN_LEAVE_TO_EXCEPTION( + QT_TRAP_THROWING( User::LeaveIfError(leave))); QCOMPARE(trap, trapped); } +void tst_qmainexceptions::TestStdRoundTrip(const std::exception& thrown, const std::exception& caught) +{ + bool ok = false; + try { + QT_TRAP_THROWING(qt_exception2SymbianLeaveL(thrown)); + } catch (const std::exception& ex) { + const std::type_info& exType = typeid(ex); + const std::type_info& caughtType = typeid(caught); + QCOMPARE(exType, caughtType); + ok = true; + } + QCOMPARE(ok, true); +} + void tst_qmainexceptions::testRoundTrip() { for (int e=-50; e<0; e++) @@ -214,12 +234,16 @@ void tst_qmainexceptions::testRoundTrip() // positive error codes are not errors TestSymbianRoundTrip(1, KErrNone); TestSymbianRoundTrip(1000000000, KErrNone); + TestStdRoundTrip(std::bad_alloc(), std::bad_alloc()); + TestStdRoundTrip(std::invalid_argument("abc"), std::invalid_argument("")); + TestStdRoundTrip(std::underflow_error("abc"), std::underflow_error("")); + TestStdRoundTrip(std::overflow_error("abc"), std::overflow_error("")); } void tst_qmainexceptions::testTrap() { - // testing qt_translateExceptionToSymbianErrorL - TRAPD(err, qt_translateExceptionToSymbianErrorL(std::bad_alloc())); + // testing qt_exception2SymbianLeaveL + TRAPD(err, qt_exception2SymbianLeaveL(std::bad_alloc())); QCOMPARE(err, KErrNoMemory); } @@ -310,6 +334,126 @@ void tst_qmainexceptions::testNestedExceptions() catch (const std::exception&) {} } +class CTestRef : public CBase +{ +public: + CTestRef(int& aX) : iX(aX) { iX++; } + ~CTestRef() { iX--; } + int& iX; +}; + +void tst_qmainexceptions::testScopedPointer() +{ + int x = 0; + { + QScopedPointer<CTestRef> ptr(q_check_ptr(new CTestRef(x))); + QCOMPARE(x, 1); + } + QCOMPARE(x, 0); + try { + QScopedPointer<CTestRef> ptr(q_check_ptr(new CTestRef(x))); + QCOMPARE(x, 1); + throw 1; + } catch (int) { + QCOMPARE(x, 0); + } + QCOMPARE(x, 0); +} + +int dtorFired[20]; +int* recDtor; + +class CDtorOrder : public CBase +{ +public: + CDtorOrder(TInt aId) : iId(aId) {} + ~CDtorOrder() { *(recDtor++)=iId; } + TInt iId; +}; + +class QDtorOrder +{ +public: + QDtorOrder(int aId) : iId(aId) {} + ~QDtorOrder() { *(recDtor++)=iId; } + int iId; +}; + +class RDtorOrder : public RHandleBase +{ +public: + TInt Connect(TInt aId) {iId = aId; SetHandle(aId); return KErrNone; } + void Close() { *(recDtor++)=iId; } + TInt iId; +}; + +enum THybridAction {EHybridLeave, EHybridThrow, EHybridPass}; + +void HybridFuncLX(THybridAction aAction) +{ + recDtor = dtorFired; + QDtorOrder q1(1); + {QDtorOrder q2(2);} + CDtorOrder* c1 = new(ELeave) CDtorOrder(11); + CleanupStack::PushL(c1); + {LManagedHandle<RDtorOrder> r1; + r1->Connect(21) OR_LEAVE;} + CDtorOrder* c2 = new(ELeave) CDtorOrder(12); + CleanupStack::PushL(c2); + QDtorOrder q3(3); + LManagedHandle<RDtorOrder> r2; + r2->Connect(22) OR_LEAVE; + CDtorOrder* c3 = new(ELeave) CDtorOrder(13); + CleanupStack::PushL(c3); + CleanupStack::PopAndDestroy(c3); + QDtorOrder q4(4); + switch (aAction) + { + case EHybridLeave: + User::Leave(KErrNotFound); + break; + case EHybridThrow: + throw std::bad_alloc(); + break; + default: + break; + } + CleanupStack::PopAndDestroy(2); +} + +void tst_qmainexceptions::testHybrid() +{ + TRAPD(error, + QT_TRYCATCH_LEAVING( + HybridFuncLX(EHybridLeave); + ) ); + QCOMPARE(error, KErrNotFound); + int expected1[] = {2, 21, 13, 12, 11, 4, 22, 3, 1}; + QCOMPARE(int(sizeof(expected1)/sizeof(int)), int(recDtor - dtorFired)); + for (int i=0; i<sizeof(expected1)/sizeof(int); i++) + QCOMPARE(expected1[i], dtorFired[i]); + + TRAP(error, + QT_TRYCATCH_LEAVING( + HybridFuncLX(EHybridThrow); + ) ); + QCOMPARE(error, KErrNoMemory); + int expected2[] = {2, 21, 13, 4, 22, 3, 1, 12, 11}; + QCOMPARE(int(sizeof(expected2)/sizeof(int)), int(recDtor - dtorFired)); + for (int i=0; i<sizeof(expected2)/sizeof(int); i++) + QCOMPARE(expected2[i], dtorFired[i]); + + TRAP(error, + QT_TRYCATCH_LEAVING( + HybridFuncLX(EHybridPass); + ) ); + QCOMPARE(error, KErrNone); + int expected3[] = {2, 21, 13, 12, 11, 4, 22, 3, 1}; + QCOMPARE(int(sizeof(expected3)/sizeof(int)), int(recDtor - dtorFired)); + for (int i=0; i<sizeof(expected3)/sizeof(int); i++) + QCOMPARE(expected3[i], dtorFired[i]); +} + QTEST_MAIN(tst_qmainexceptions) #include "tst_qmainexceptions.moc" |