diff options
author | Marc Mutz <marc.mutz@qt.io> | 2021-12-07 17:46:26 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2021-12-08 16:39:27 +0000 |
commit | d4a88e4ea4dd0d24c9c43553dd4c48a79635803c (patch) | |
tree | 2c31d0b6c2203a718e0f247e7d09baba046d5661 /tests/auto/corelib/tools | |
parent | 0f88e79ed80aaf3c02def55c6d507dde17eada60 (diff) |
QVarLengthArray: fix size update on failed append()
If the in-place constructor throws, the old code had already updated
the container's size(). Fix by delaying the update to after the
in-place construction.
[ChangeLog][QtCore][QVarLengthArray] Fixed a bug whereby a failed
append() would leave the container with an inconsistent size().
Pick-to: 6.2 5.15
Change-Id: Ief1e668d945149bd8ba96c8af1398baaa7876880
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'tests/auto/corelib/tools')
-rw-r--r-- | tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 3631f4f977..4944da71a9 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -30,6 +30,7 @@ #include <qvarlengtharray.h> #include <qvariant.h> #include <qscopeguard.h> +#include <qscopedvaluerollback.h> #include <memory> @@ -85,6 +86,7 @@ private slots: void removeLast(); void oldTests(); void appendCausingRealloc(); + void appendIsStronglyExceptionSafe(); void resize(); void realloc(); void iterators(); @@ -402,6 +404,49 @@ void tst_QVarLengthArray::appendCausingRealloc() d.append(i); } +void tst_QVarLengthArray::appendIsStronglyExceptionSafe() +{ +#ifdef QT_NO_EXCEPTIONS + QSKIP("This test requires exception support enabled in the compiler."); +#else + static bool throwOnCopyNow = false; + static bool throwOnMoveNow = false; + struct Thrower { + Thrower() = default; + Thrower(const Thrower &) + { + if (throwOnCopyNow) + throw 1; + } + Thrower &operator=(const Thrower &) = default; + Thrower(Thrower &&) + { + if (throwOnMoveNow) + throw 1; + } + Thrower &operator=(Thrower &&) = default; + ~Thrower() = default; + }; + + { + // ### TODO: QVLA isn't exception-safe when throwing during reallocation, + // ### so check with size() < capacity() for now + QVarLengthArray<Thrower, 2> vla(1); + { + Thrower t; + const QScopedValueRollback rb(throwOnCopyNow, true); + QVERIFY_THROWS_EXCEPTION(int, vla.push_back(t)); + QCOMPARE(vla.size(), 1); + } + { + const QScopedValueRollback rb(throwOnMoveNow, true); + QVERIFY_THROWS_EXCEPTION(int, vla.push_back({})); + QCOMPARE(vla.size(), 1); + } + } +#endif +} + void tst_QVarLengthArray::resize() { // Empty Movable |