Remove QWorkspace.
[qt:rb-qtbase.git] / tests / auto / other / exceptionsafety_objects / tst_exceptionsafety_objects.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtGui/QtGui>
43 #include <QtWidgets/QtWidgets>
44 #include <QtTest/QtTest>
45
46 #include <stddef.h>
47 #include <exception>
48
49 QT_USE_NAMESPACE
50
51 // this test only works with GLIBC
52
53 #include "oomsimulator.h"
54 #include "3rdparty/memcheck.h"
55
56 class tst_ExceptionSafety_Objects: public QObject
57 {
58     Q_OBJECT
59
60 public slots:
61     void initTestCase();
62 #ifndef QT_NO_EXCEPTIONS
63     void cleanupTestCase();
64
65 private slots:
66     void objects_data();
67     void objects();
68
69     void widgets_data();
70     void widgets();
71
72     void vector_data();
73     void vector();
74
75     void list_data();
76     void list();
77
78     void linkedList_data();
79     void linkedList();
80
81 private:
82     static QtMsgHandler testMessageHandler;
83     static void safeMessageHandler(QtMsgType, const char *);
84 #endif
85 };
86
87 #ifdef QT_NO_EXCEPTIONS
88 void tst_ExceptionSafety_Objects::initTestCase()
89 {
90     QSKIP("This test requires exception support");
91 }
92
93 #else
94 // helper structs to create an arbitrary widget
95 struct AbstractTester
96 {
97     virtual ~AbstractTester() {}
98     virtual void operator()(QObject *parent) = 0;
99 };
100 Q_DECLARE_METATYPE(AbstractTester *)
101
102 typedef void (*TestFunction)(QObject*);
103 Q_DECLARE_METATYPE(TestFunction)
104
105 template <typename T>
106 struct ObjectCreator : public AbstractTester
107 {
108     void operator()(QObject *)
109     {
110         QScopedPointer<T> ptr(new T);
111     }
112 };
113
114 struct BitArrayCreator : public AbstractTester
115 {
116     void operator()(QObject *)
117     { QScopedPointer<QBitArray> bitArray(new QBitArray(100, true)); }
118 };
119
120 struct ByteArrayMatcherCreator : public AbstractTester
121 {
122     void operator()(QObject *)
123     { QScopedPointer<QByteArrayMatcher> ptr(new QByteArrayMatcher("ralf test",8)); }
124 };
125
126 struct CryptographicHashCreator : public AbstractTester
127 {
128     void operator()(QObject *)
129     {
130         QScopedPointer<QCryptographicHash> ptr(new QCryptographicHash(QCryptographicHash::Sha1));
131         ptr->addData("ralf test",8);
132     }
133 };
134
135 struct DataStreamCreator : public AbstractTester
136 {
137     void operator()(QObject *)
138     {
139         QScopedPointer<QByteArray> arr(new QByteArray("hallo, test"));
140         QScopedPointer<QDataStream> ptr(new QDataStream(arr.data(), QIODevice::ReadWrite));
141         ptr->writeBytes("ralf test",8);
142     }
143 };
144
145 struct DirCreator : public AbstractTester
146 {
147     void operator()(QObject *)
148     {
149         QDir::cleanPath("../////././");
150         QScopedPointer<QDir> ptr(new QDir("."));
151         while( ptr->cdUp() )
152             ; // just going up
153         ptr->count();
154         ptr->exists(ptr->path());
155
156         QStringList filters;
157         filters << "*.cpp" << "*.cxx" << "*.cc";
158         ptr->setNameFilters(filters);
159     }
160 };
161
162 void tst_ExceptionSafety_Objects::objects_data()
163 {
164     QTest::addColumn<AbstractTester *>("objectCreator");
165
166 #define NEWROW(T) QTest::newRow(#T) << static_cast<AbstractTester *>(new ObjectCreator<T >)
167     NEWROW(QObject);
168     NEWROW(QBuffer);
169     NEWROW(QFile);
170     NEWROW(QProcess);
171     NEWROW(QSettings);
172     NEWROW(QThread);
173     NEWROW(QThreadPool);
174     NEWROW(QTranslator);
175
176 #define NEWROW2(T, CREATOR) QTest::newRow(#T) << static_cast<AbstractTester *>(new CREATOR)
177     NEWROW2(QBitArray, BitArrayCreator);
178     NEWROW2(QByteArrayMatcher, ByteArrayMatcherCreator);
179     NEWROW2(QCryptographicHash, CryptographicHashCreator);
180     NEWROW2(QDataStream, DataStreamCreator);
181     NEWROW2(QDir, DirCreator);
182 }
183
184 // create and destructs an object, and lets each and every allocation
185 // during construction and destruction fail.
186 template <typename T>
187 static void doOOMTest(T &testFunc, QObject *parent, int start=0)
188 {
189     int currentOOMIndex = start;
190     bool caught = false;
191     bool done = false;
192
193     AllocFailer allocFailer(0);
194     int allocCountBefore = allocFailer.currentAllocIndex();
195
196     do {
197         allocFailer.reactivateAt(++currentOOMIndex);
198
199         caught = false;
200
201         try {
202             testFunc(parent);
203         } catch (const std::bad_alloc &) {
204             caught = true;
205         } catch (const std::exception &ex) {
206             if (strcmp(ex.what(), "autotest swallow") != 0)
207                 throw;
208             caught = true;
209         }
210
211         if (!caught) {
212             void *buf = malloc(42);
213             if (buf) {
214                 // we got memory here - oom test is over.
215                 free(buf);
216                 done = true;
217             }
218         }
219
220         // if we get a FAIL, stop executing now
221         if (QTest::currentTestFailed())
222             done = true;
223
224 //#define REALLY_VERBOSE
225 #ifdef REALLY_VERBOSE
226     fprintf(stderr, " OOM Index: %d\n", currentOOMIndex);
227 #endif
228
229
230     } while (caught || !done);
231
232     allocFailer.deactivate();
233
234 //#define VERBOSE
235 #ifdef VERBOSE
236     fprintf(stderr, "OOM Test done, checked allocs: %d (range %d - %d)\n", currentOOMIndex,
237                 allocCountBefore, allocFailer.currentAllocIndex());
238 #else
239     Q_UNUSED(allocCountBefore);
240 #endif
241 }
242
243 static int alloc1Failed = 0;
244 static int alloc2Failed = 0;
245 static int alloc3Failed = 0;
246 static int alloc4Failed = 0;
247 static int malloc1Failed = 0;
248 static int malloc2Failed = 0;
249
250 // Tests that new, new[] and malloc() fail at least once during OOM testing.
251 class SelfTestObject : public QObject
252 {
253 public:
254     SelfTestObject(QObject *parent = 0)
255         : QObject(parent)
256     {
257         try { delete new int; } catch (const std::bad_alloc &) { ++alloc1Failed; throw; }
258         try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc2Failed; throw ;}
259         void *buf = malloc(42);
260         if (buf)
261             free(buf);
262         else
263             ++malloc1Failed;
264     }
265
266     ~SelfTestObject()
267     {
268         try { delete new int; } catch (const std::bad_alloc &) { ++alloc3Failed; }
269         try { delete [] new double[5]; } catch (const std::bad_alloc &) { ++alloc4Failed; }
270         void *buf = malloc(42);
271         if (buf)
272             free(buf);
273         else
274             ++malloc2Failed = true;
275     }
276 };
277
278 QtMsgHandler tst_ExceptionSafety_Objects::testMessageHandler;
279
280 void tst_ExceptionSafety_Objects::safeMessageHandler(QtMsgType type, const char *msg)
281 {
282     // this temporarily suspends OOM testing while handling a message
283     int currentIndex = mallocFailIndex;
284     AllocFailer allocFailer(0);
285     allocFailer.deactivate();
286     (*testMessageHandler)(type, msg);
287     allocFailer.reactivateAt(currentIndex);
288 }
289
290 typedef void (*PVF)();
291 PVF defaultTerminate;
292 void debugTerminate()
293 {
294     // you can detect uncaught exceptions with a breakpoint in here
295     (*defaultTerminate)();
296 }
297
298 PVF defaultUnexpected;
299 void debugUnexpected()
300 {
301     // you can detect unexpected exceptions with a breakpoint in here
302     (*defaultUnexpected)();
303 }
304
305 void tst_ExceptionSafety_Objects::initTestCase()
306 {
307     // set handlers for bad exception cases, you might want to step in and breakpoint the default handlers too
308     defaultTerminate = std::set_terminate(&debugTerminate);
309     defaultUnexpected = std::set_unexpected(&debugUnexpected);
310     testMessageHandler = qInstallMsgHandler(safeMessageHandler);
311
312     QVERIFY(AllocFailer::initialize());
313
314     // sanity check whether OOM simulation works
315     AllocFailer allocFailer(0);
316
317     // malloc fail index is 0 -> this malloc should fail.
318     void *buf = malloc(42);
319     allocFailer.deactivate();
320     QVERIFY(!buf);
321
322     // malloc fail index is 1 - second malloc should fail.
323     allocFailer.reactivateAt(1);
324     buf = malloc(42);
325     void *buf2 = malloc(42);
326     allocFailer.deactivate();
327
328     QVERIFY(buf);
329     free(buf);
330     QVERIFY(!buf2);
331
332     ObjectCreator<SelfTestObject> *selfTest = new ObjectCreator<SelfTestObject>;
333     doOOMTest(*selfTest, 0);
334     delete selfTest;
335     QCOMPARE(alloc1Failed, 1);
336     QCOMPARE(alloc2Failed, 1);
337     QCOMPARE(alloc3Failed, 2);
338     QCOMPARE(alloc4Failed, 3);
339     QCOMPARE(malloc1Failed, 1);
340     QCOMPARE(malloc2Failed, 1);
341 }
342
343 void tst_ExceptionSafety_Objects::cleanupTestCase()
344 {
345     qInstallMsgHandler(testMessageHandler);
346 }
347
348 void tst_ExceptionSafety_Objects::objects()
349 {
350     QLatin1String tag = QLatin1String(QTest::currentDataTag());
351     if (tag == QLatin1String("QFile")
352         || tag == QLatin1String("QProcess")
353         || tag == QLatin1String("QSettings")
354         || tag == QLatin1String("QThread")
355         || tag == QLatin1String("QThreadPool"))
356         QSKIP("This type of object is not currently strongly exception safe");
357
358     QFETCH(AbstractTester *, objectCreator);
359
360     doOOMTest(*objectCreator, 0);
361
362     delete objectCreator;
363 }
364
365 template <typename T>
366 struct WidgetCreator : public AbstractTester
367 {
368     void operator()(QObject *parent)
369     {
370         if (parent && !parent->isWidgetType())
371             qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO);
372         QScopedPointer<T> ptr(parent ? new T(static_cast<QWidget *>(parent)) : new T);
373     }
374 };
375
376 // QSizeGrip doesn't have a default constructor - always pass parent (even though it might be 0)
377 template <> struct WidgetCreator<QSizeGrip> : public AbstractTester
378 {
379     void operator()(QObject *parent)
380     {
381         if (parent && !parent->isWidgetType())
382             qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO);
383         QScopedPointer<QSizeGrip> ptr(new QSizeGrip(static_cast<QWidget *>(parent)));
384     }
385 };
386
387 // QDesktopWidget doesn't need a parent.
388 template <> struct WidgetCreator<QDesktopWidget> : public AbstractTester
389 {
390     void operator()(QObject *parent)
391     {
392         if (parent && !parent->isWidgetType())
393             qFatal("%s: parent must be either null or a widget type", Q_FUNC_INFO);
394         QScopedPointer<QDesktopWidget> ptr(new QDesktopWidget());
395     }
396 };
397 void tst_ExceptionSafety_Objects::widgets_data()
398 {
399     QTest::addColumn<AbstractTester *>("widgetCreator");
400
401 #undef NEWROW
402 #define NEWROW(T) QTest::newRow(#T) << static_cast<AbstractTester *>(new WidgetCreator<T >)
403
404     NEWROW(QWidget);
405
406     NEWROW(QButtonGroup);
407     NEWROW(QCheckBox);
408     NEWROW(QColumnView);
409     NEWROW(QComboBox);
410     NEWROW(QCommandLinkButton);
411     NEWROW(QDateEdit);
412     NEWROW(QDateTimeEdit);
413     NEWROW(QDesktopWidget);
414     NEWROW(QDial);
415     NEWROW(QDoubleSpinBox);
416     NEWROW(QFocusFrame);
417     NEWROW(QFontComboBox);
418     NEWROW(QFrame);
419     NEWROW(QGroupBox);
420     NEWROW(QLabel);
421     NEWROW(QLCDNumber);
422     NEWROW(QLineEdit);
423     NEWROW(QListView);
424     NEWROW(QListWidget);
425     NEWROW(QMainWindow);
426     NEWROW(QMenu);
427     NEWROW(QMenuBar);
428     NEWROW(QPlainTextEdit);
429     NEWROW(QProgressBar);
430     NEWROW(QPushButton);
431     NEWROW(QRadioButton);
432     NEWROW(QScrollArea);
433     NEWROW(QScrollBar);
434     NEWROW(QSizeGrip);
435     NEWROW(QSlider);
436     NEWROW(QSpinBox);
437     NEWROW(QSplitter);
438     NEWROW(QStackedWidget);
439     NEWROW(QStatusBar);
440     NEWROW(QTabBar);
441     NEWROW(QTableView);
442     NEWROW(QTableWidget);
443     NEWROW(QTabWidget);
444     NEWROW(QTextBrowser);
445     NEWROW(QTextEdit);
446     NEWROW(QTimeEdit);
447     NEWROW(QToolBar);
448     NEWROW(QToolBox);
449     NEWROW(QToolButton);
450     NEWROW(QTreeView);
451     NEWROW(QTreeWidget);
452 }
453
454 void tst_ExceptionSafety_Objects::widgets()
455 {
456     QLatin1String tag = QLatin1String(QTest::currentDataTag());
457     if (tag == QLatin1String("QColumnView")
458         || tag == QLatin1String("QComboBox")
459         || tag == QLatin1String("QCommandLinkButton")
460         || tag == QLatin1String("QDateEdit")
461         || tag == QLatin1String("QDateTimeEdit")
462         || tag == QLatin1String("QDesktopWidget")
463         || tag == QLatin1String("QDoubleSpinBox")
464         || tag == QLatin1String("QFontComboBox")
465         || tag == QLatin1String("QGroupBox")
466         || tag == QLatin1String("QLineEdit")
467         || tag == QLatin1String("QListView")
468         || tag == QLatin1String("QListWidget")
469         || tag == QLatin1String("QMainWindow")
470         || tag == QLatin1String("QMenu")
471         || tag == QLatin1String("QMenuBar")
472         || tag == QLatin1String("QPlainTextEdit")
473         || tag == QLatin1String("QProgressBar")
474         || tag == QLatin1String("QPushButton")
475         || tag == QLatin1String("QScrollArea")
476         || tag == QLatin1String("QSpinBox")
477         || tag == QLatin1String("QStackedWidget")
478         || tag == QLatin1String("QStatusBar")
479         || tag == QLatin1String("QTableView")
480         || tag == QLatin1String("QTableWidget")
481         || tag == QLatin1String("QTabWidget")
482         || tag == QLatin1String("QTextBrowser")
483         || tag == QLatin1String("QTextEdit")
484         || tag == QLatin1String("QTimeEdit")
485         || tag == QLatin1String("QToolBar")
486         || tag == QLatin1String("QToolBox")
487         || tag == QLatin1String("QTreeView")
488         || tag == QLatin1String("QTreeWidget"))
489         QSKIP("This type of widget is not currently strongly exception safe");
490
491     if (tag == QLatin1String("QWidget"))
492         QSKIP("QTBUG-18927");
493
494     QFETCH(AbstractTester *, widgetCreator);
495
496     doOOMTest(*widgetCreator, 0, 00000);
497
498     QWidget parent;
499     doOOMTest(*widgetCreator, &parent, 00000);
500
501     delete widgetCreator;
502
503     // if the test reaches here without crashing, we passed :)
504     QVERIFY(true);
505 }
506
507 struct Integer
508 {
509     Integer(int value = 42)
510         : ptr(new int(value))
511     {
512         ++instanceCount;
513     }
514
515     Integer(const Integer &other)
516         : ptr(new int(*other.ptr))
517     {
518         ++instanceCount;
519     }
520
521     Integer &operator=(const Integer &other)
522     {
523         int *newPtr = new int(*other.ptr);
524         delete ptr;
525         ptr = newPtr;
526         return *this;
527     }
528
529     ~Integer()
530     {
531         --instanceCount;
532         delete ptr;
533     }
534
535     int value() const
536     {
537         return *ptr;
538     }
539
540     int *ptr;
541     static int instanceCount;
542 };
543
544 int Integer::instanceCount = 0;
545
546 struct IntegerMoveable
547     {
548     IntegerMoveable(int value = 42)
549         : val(value)
550     {
551         delete new int;
552         ++instanceCount;
553     }
554
555     IntegerMoveable(const IntegerMoveable &other)
556         : val(other.val)
557     {
558         delete new int;
559         ++instanceCount;
560     }
561
562     IntegerMoveable &operator=(const IntegerMoveable &other)
563     {
564         delete new int;
565         val = other.val;
566         return *this;
567     }
568
569     ~IntegerMoveable()
570     {
571         --instanceCount;
572     }
573
574     int value() const
575     {
576         return val;
577     }
578
579     int val;
580     static int instanceCount;
581     };
582
583 int IntegerMoveable::instanceCount = 0;
584 QT_BEGIN_NAMESPACE
585 Q_DECLARE_TYPEINFO(IntegerMoveable, Q_MOVABLE_TYPE);
586 QT_END_NAMESPACE
587
588 template <typename T, template<typename> class Container>
589 void containerInsertTest(QObject*)
590 {
591     Container<T> container;
592
593     // insert an item in an empty container
594     try {
595         container.insert(container.begin(), 41);
596     } catch (...) {
597         QVERIFY(container.isEmpty());
598         QCOMPARE(T::instanceCount, 0);
599         return;
600     }
601
602     QCOMPARE(container.size(), 1);
603     QCOMPARE(T::instanceCount, 1);
604
605     // insert an item before another item
606     try {
607         container.insert(container.begin(), 42);
608     } catch (...) {
609         QCOMPARE(container.size(), 1);
610         QCOMPARE(container.first().value(), 41);
611         QCOMPARE(T::instanceCount, 1);
612         return;
613     }
614
615     QCOMPARE(T::instanceCount, 2);
616
617     // insert an item in between
618     try {
619         container.insert(container.begin() + 1, 43);
620     } catch (...) {
621         QCOMPARE(container.size(), 2);
622         QCOMPARE(container.first().value(), 41);
623         QCOMPARE((container.begin() + 1)->value(), 42);
624         QCOMPARE(T::instanceCount, 2);
625         return;
626     }
627
628     QCOMPARE(T::instanceCount, 3);
629 }
630
631 template <typename T, template<typename> class Container>
632 void containerAppendTest(QObject*)
633 {
634     Container<T> container;
635
636     // append to an empty container
637     try {
638         container.append(42);
639     } catch (...) {
640         QCOMPARE(container.size(), 0);
641         QCOMPARE(T::instanceCount, 0);
642         return;
643     }
644
645     // append to a container with one item
646     try {
647         container.append(43);
648     } catch (...) {
649         QCOMPARE(container.size(), 1);
650         QCOMPARE(container.first().value(), 42);
651         QCOMPARE(T::instanceCount, 1);
652         return;
653     }
654
655     Container<T> container2;
656
657     try {
658         container2.append(44);
659     } catch (...) {
660         // don't care
661         return;
662     }
663     QCOMPARE(T::instanceCount, 3);
664
665     // append another container with one item
666     try {
667         container += container2;
668     } catch (...) {
669         QCOMPARE(container.size(), 2);
670         QCOMPARE(container.first().value(), 42);
671         QCOMPARE((container.begin() + 1)->value(), 43);
672         QCOMPARE(T::instanceCount, 3);
673         return;
674     }
675
676     QCOMPARE(T::instanceCount, 4);
677 }
678
679 template <typename T, template<typename> class Container>
680 void containerEraseTest(QObject*)
681 {
682     Container<T> container;
683
684     try {
685         container.append(42);
686         container.append(43);
687         container.append(44);
688         container.append(45);
689         container.append(46);
690     } catch (...) {
691         // don't care
692         return;
693     }
694
695     // sanity checks
696     QCOMPARE(container.size(), 5);
697     QCOMPARE(T::instanceCount, 5);
698
699     // delete the first one
700     try {
701         container.erase(container.begin());
702     } catch (...) {
703         QCOMPARE(container.size(), 5);
704         QCOMPARE(container.first().value(), 42);
705         QCOMPARE(T::instanceCount, 5);
706         return;
707     }
708
709     QCOMPARE(container.size(), 4);
710     QCOMPARE(container.first().value(), 43);
711     QCOMPARE(T::instanceCount, 4);
712
713     // delete the last one
714     try {
715         container.erase(container.end() - 1);
716     } catch (...) {
717         QCOMPARE(container.size(), 4);
718         QCOMPARE(T::instanceCount, 4);
719         return;
720     }
721
722     QCOMPARE(container.size(), 3);
723     QCOMPARE(container.first().value(), 43);
724     QCOMPARE((container.begin() + 1)->value(), 44);
725     QCOMPARE((container.begin() + 2)->value(), 45);
726     QCOMPARE(T::instanceCount, 3);
727
728     // delete the middle one
729     try {
730         container.erase(container.begin() + 1);
731     } catch (...) {
732         QCOMPARE(container.size(), 3);
733         QCOMPARE(container.first().value(), 43);
734         QCOMPARE((container.begin() + 1)->value(), 44);
735         QCOMPARE((container.begin() + 2)->value(), 45);
736         QCOMPARE(T::instanceCount, 3);
737         return;
738     }
739
740     QCOMPARE(container.size(), 2);
741     QCOMPARE(container.first().value(), 43);
742     QCOMPARE((container.begin() + 1)->value(), 45);
743     QCOMPARE(T::instanceCount, 2);
744 }
745
746 template <template<typename T> class Container>
747 static void containerData()
748 {
749     QTest::addColumn<TestFunction>("testFunction");
750
751     QTest::newRow("insert static") << static_cast<TestFunction>(containerInsertTest<Integer, Container>);
752     QTest::newRow("append static") << static_cast<TestFunction>(containerAppendTest<Integer, Container>);
753     QTest::newRow("erase static") << static_cast<TestFunction>(containerEraseTest<Integer, Container>);
754     QTest::newRow("insert moveable") << static_cast<TestFunction>(containerInsertTest<IntegerMoveable, Container>);
755     QTest::newRow("append moveable") << static_cast<TestFunction>(containerAppendTest<IntegerMoveable, Container>);
756     QTest::newRow("erase moveable") << static_cast<TestFunction>(containerEraseTest<IntegerMoveable, Container>);
757 }
758
759 void tst_ExceptionSafety_Objects::vector_data()
760 {
761     containerData<QVector>();
762 }
763
764 void tst_ExceptionSafety_Objects::vector()
765 {
766     QFETCH(TestFunction, testFunction);
767
768     if (QLatin1String(QTest::currentDataTag()) == QLatin1String("insert static")
769         || QLatin1String(QTest::currentDataTag()) == QLatin1String("insert moveable"))
770         QSKIP("QVector::insert is currently not strongly exception safe");
771
772     doOOMTest(testFunction, 0);
773 }
774
775 void tst_ExceptionSafety_Objects::list_data()
776 {
777     containerData<QList>();
778 }
779
780 void tst_ExceptionSafety_Objects::list()
781 {
782     QFETCH(TestFunction, testFunction);
783
784     doOOMTest(testFunction, 0);
785 }
786
787 void tst_ExceptionSafety_Objects::linkedList_data()
788 {
789     containerData<QLinkedList>();
790 }
791
792 void tst_ExceptionSafety_Objects::linkedList()
793 {
794     QFETCH(TestFunction, testFunction);
795
796     doOOMTest(testFunction, 0);
797 }
798
799 #endif
800
801 QTEST_MAIN(tst_ExceptionSafety_Objects)
802 #include "tst_exceptionsafety_objects.moc"