summaryrefslogtreecommitdiffstats
path: root/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp
diff options
context:
space:
mode:
authorHarald Fernengel <harald@trolltech.com>2009-08-03 13:12:46 (GMT)
committerHarald Fernengel <harald@trolltech.com>2009-08-03 13:12:46 (GMT)
commit41a83e1ff19ad1396e6001e6b0ac003c701ba55a (patch)
tree609e40eda10418bbf925002c36552074796b96b6 /tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp
parentd1f3b9df2bc5c57d414da73a7d4f9ed7b25df3db (diff)
downloadQt-41a83e1ff19ad1396e6001e6b0ac003c701ba55a.zip
Qt-41a83e1ff19ad1396e6001e6b0ac003c701ba55a.tar.gz
Qt-41a83e1ff19ad1396e6001e6b0ac003c701ba55a.tar.bz2
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/exceptionsafety_objects/tst_exceptionsafety_objects.cpp')
-rw-r--r--tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp257
1 files changed, 215 insertions, 42 deletions
diff --git a/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp b/tests/auto/exceptionsafety_objects/tst_exceptionsafety_objects.cpp
index dd5f8da..c867899 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)