summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp')
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp695
1 files changed, 633 insertions, 62 deletions
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index ab3b46fc90..6a92663bc4 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -1,36 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QTest>
-#include <qvarlengtharray.h>
+#include <QVarLengthArray>
#include <qvariant.h>
#include <qscopeguard.h>
+#include <qscopedvaluerollback.h>
+#include <algorithm>
+#include <q20iterator.h>
#include <memory>
struct Tracker
@@ -64,11 +42,35 @@ public:
{ return !operator==(lhs, rhs); }
};
+class NonCopyable
+{
+ Q_DISABLE_COPY(NonCopyable)
+ int n;
+public:
+ NonCopyable() : n(0) {}
+ explicit NonCopyable(int n) : n(n) {}
+
+ friend bool operator==(const NonCopyable &lhs, const NonCopyable &rhs) noexcept
+ { return lhs.n == rhs.n; }
+ friend bool operator!=(const NonCopyable &lhs, const NonCopyable &rhs) noexcept
+ { return !operator==(lhs, rhs); }
+};
+
class tst_QVarLengthArray : public QObject
{
Q_OBJECT
private slots:
+ void defaultConstructor_int() { defaultConstructor<int>(); }
+ void defaultConstructor_QString() { defaultConstructor<QString>(); }
+ void sizeConstructor_int() { sizeConstructor<int>(); }
+ void sizeConstructor_QString() { sizeConstructor<QString>(); }
+ void sizeConstructor_NonCopyable() { sizeConstructor<NonCopyable>(); }
void append();
+ void preallocatedSize();
+#if QT_DEPRECATED_SINCE(6, 3)
+ void prepend();
+#endif
+ void emplace();
void move_int_1() { move_int<1>(); }
void move_int_2() { move_int<2>(); }
void move_int_3() { move_int<3>(); }
@@ -81,8 +83,10 @@ private slots:
void removeLast();
void oldTests();
void appendCausingRealloc();
+ void appendIsStronglyExceptionSafe();
void resize();
void realloc();
+ void iterators();
void reverseIterators();
void count();
void cpp17ctad();
@@ -100,8 +104,21 @@ private slots:
void insertMove();
void nonCopyable();
void implicitDefaultCtor();
-
+ void reserve();
+ void value();
+ void insert();
+ void insert_data();
+ void replace();
+ void remove();
+ void erase();
+
+ // special cases:
+ void copesWithCopyabilityOfMoveOnlyVector(); // QTBUG-109745
private:
+ template <typename T>
+ void defaultConstructor();
+ template <typename T>
+ void sizeConstructor();
template <qsizetype N, typename T>
void move(T t1, T t2);
template <qsizetype N>
@@ -114,6 +131,48 @@ private:
void initializeList();
};
+template <typename T>
+void tst_QVarLengthArray::defaultConstructor()
+{
+ {
+ QVarLengthArray<T, 123> vla;
+ QCOMPARE(vla.size(), 0);
+ QVERIFY(vla.empty());
+ QVERIFY(vla.isEmpty());
+ QCOMPARE(vla.begin(), vla.end());
+ QCOMPARE(vla.capacity(), 123);
+ }
+ {
+ QVarLengthArray<T> vla;
+ QCOMPARE(vla.capacity(), 256); // notice, should we change the default
+ }
+}
+
+template <typename T>
+void tst_QVarLengthArray::sizeConstructor()
+{
+ {
+ QVarLengthArray<T, 123> vla(0);
+ QCOMPARE(vla.size(), 0);
+ QVERIFY(vla.empty());
+ QVERIFY(vla.isEmpty());
+ QCOMPARE(vla.begin(), vla.end());
+ QCOMPARE(vla.capacity(), 123);
+ }
+ {
+ QVarLengthArray<T, 124> vla(124);
+ QCOMPARE(vla.size(), 124);
+ QVERIFY(!vla.empty());
+ QCOMPARE(vla.capacity(), 124);
+ }
+ {
+ QVarLengthArray<T, 124> vla(125);
+ QCOMPARE(vla.size(), 125);
+ QVERIFY(!vla.empty());
+ QCOMPARE_GE(vla.capacity(), 125);
+ }
+}
+
void tst_QVarLengthArray::append()
{
QVarLengthArray<QString, 2> v;
@@ -136,6 +195,84 @@ void tst_QVarLengthArray::append()
v2.append(5);
}
+void tst_QVarLengthArray::preallocatedSize()
+{
+ // The default is 256:
+ static_assert(QVarLengthArray<int>::PreallocatedSize == 256);
+ // Otherwise, whatever was given as template argument:
+ static_assert(QVarLengthArray<int, 42>::PreallocatedSize == 42);
+ static_assert(QVarLengthArray<int, 1'000'000>::PreallocatedSize == 1'000'000);
+}
+
+#if QT_DEPRECATED_SINCE(6, 3)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+void tst_QVarLengthArray::prepend()
+{
+ QVarLengthArray<QString, 2> v;
+ v.prepend(QString("1"));
+ v.prepend(v.front());
+ QCOMPARE(v.capacity(), 2);
+ // transition from stack to heap
+ v.prepend(v.back());
+ QVERIFY(v.capacity() > 2);
+ QCOMPARE(v.front(), v.back());
+ while (v.size() < v.capacity())
+ v.prepend(v.back());
+ QCOMPARE(v.front(), v.back());
+ QCOMPARE(v.size(), v.capacity());
+ // transition from heap to larger heap:
+ v.prepend(v.back());
+ QCOMPARE(v.front(), v.back());
+}
+QT_WARNING_POP
+#endif // QT_DEPRECATED_SINCE(6, 3)
+
+void tst_QVarLengthArray::emplace()
+{
+ {
+ QVarLengthArray<QString, 2> strings;
+ strings.emplace_back();
+ QCOMPARE(strings.size(), 1);
+ QCOMPARE(strings.front().isNull(), true);
+ strings.emplace(strings.begin(), 42, u'x');
+ QCOMPARE(strings.size(), 2);
+ QCOMPARE(strings.back().isNull(), true);
+ QCOMPARE(strings.front(), QString(42, u'x'));
+ auto &r = strings.emplace_back(42, u'y');
+ QCOMPARE(&r, &strings.back());
+ QCOMPARE(strings.size(), 3);
+ QCOMPARE(strings.back(), QString(42, u'y'));
+
+ // test growing from empty arrays
+ QVarLengthArray<QString> emptyArrDefaultPrealloc;
+ QCOMPARE(emptyArrDefaultPrealloc.size(), 0);
+ emptyArrDefaultPrealloc.emplace_back();
+ QCOMPARE(emptyArrDefaultPrealloc.size(), 1);
+ emptyArrDefaultPrealloc.resize(1024);
+ QCOMPARE(emptyArrDefaultPrealloc.size(), 1024);
+ emptyArrDefaultPrealloc.resize(0);
+ QCOMPARE(emptyArrDefaultPrealloc.size(), 0);
+ emptyArrDefaultPrealloc.squeeze();
+ QCOMPARE(emptyArrDefaultPrealloc.size(), 0);
+ emptyArrDefaultPrealloc.emplace_back();
+ QCOMPARE(emptyArrDefaultPrealloc.size(), 1);
+
+ QVarLengthArray<QString, 1> emptyArrSmallPrealloc;
+ QCOMPARE(emptyArrSmallPrealloc.size(), 0);
+ emptyArrSmallPrealloc.emplace_back();
+ QCOMPARE(emptyArrSmallPrealloc.size(), 1);
+ emptyArrSmallPrealloc.resize(1024);
+ QCOMPARE(emptyArrSmallPrealloc.size(), 1024);
+ emptyArrSmallPrealloc.resize(0);
+ QCOMPARE(emptyArrSmallPrealloc.size(), 0);
+ emptyArrSmallPrealloc.squeeze();
+ QCOMPARE(emptyArrSmallPrealloc.size(), 0);
+ emptyArrSmallPrealloc.emplace_back();
+ QCOMPARE(emptyArrSmallPrealloc.size(), 1);
+ }
+}
+
template <qsizetype N>
void tst_QVarLengthArray::move_Tracker()
{
@@ -305,10 +442,109 @@ void tst_QVarLengthArray::appendCausingRealloc()
QVarLengthArray<float, 1> d(1);
for (int i=0; i<30; i++)
d.append(i);
+
+ // Regression test for QTBUG-110412:
+ constexpr qsizetype InitialCapacity = 10;
+ QVarLengthArray<float, InitialCapacity> d2(InitialCapacity);
+ std::iota(d2.begin(), d2.end(), 0.0f);
+ QCOMPARE_EQ(d2.size(), d2.capacity()); // by construction
+ float floats[1000];
+ std::iota(std::begin(floats), std::end(floats), InitialCapacity + 0.0f);
+ d2.append(floats, q20::ssize(floats));
+ QCOMPARE_EQ(d2.size(), q20::ssize(floats) + InitialCapacity);
+ QCOMPARE_GE(d2.capacity(), d2.size());
+}
+
+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;
+ };
+
+ {
+ 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);
+ }
+ vla.push_back({});
+ QCOMPARE(vla.size(), 2);
+ {
+ Thrower t;
+ {
+ // tests the copy inside append()
+ const QScopedValueRollback rb(throwOnCopyNow, true);
+ QVERIFY_THROWS_EXCEPTION(int, vla.push_back(t));
+ QCOMPARE(vla.size(), 2);
+ }
+ {
+ // tests the move inside reallocate()
+ const QScopedValueRollback rb(throwOnMoveNow, true);
+ QVERIFY_THROWS_EXCEPTION(int, vla.push_back(t));
+ QCOMPARE(vla.size(), 2);
+ }
+ }
+ {
+ const QScopedValueRollback rb(throwOnMoveNow, true);
+ QVERIFY_THROWS_EXCEPTION(int, vla.push_back({}));
+ QCOMPARE(vla.size(), 2);
+ }
+ }
+#endif
}
void tst_QVarLengthArray::resize()
{
+ // Empty Movable
+ {
+ QVarLengthArray<QVariant, 1> values;
+ QCOMPARE(values.size(), 0);
+ values.resize(2);
+ QCOMPARE(values.size(), 2);
+ QCOMPARE(values[0], QVariant());
+ QCOMPARE(values[1], QVariant());
+ }
+
+ // Empty POD
+ {
+ QVarLengthArray<int, 1> values;
+ QCOMPARE(values.size(), 0);
+ values.resize(2);
+ QCOMPARE(values.size(), 2);
+ // POD values are uninitialized, but we can check that we can assign
+ // new values
+ values[0] = 0;
+ values[1] = 1;
+
+ QCOMPARE(values[0], 0);
+ QCOMPARE(values[1], 1);
+ }
+
//MOVABLE
{
QVarLengthArray<QVariant,1> values(1);
@@ -408,6 +644,12 @@ struct MyBase
bool hasMoved() const { return !wasConstructedAt(this); }
protected:
+ void swap(MyBase &other) {
+ using std::swap;
+ swap(data, other.data);
+ swap(isCopy, other.isCopy);
+ }
+
MyBase(const MyBase *data, bool isCopy)
: data(data), isCopy(isCopy) {}
@@ -482,6 +724,14 @@ struct MyMovable
return *this;
}
+ void swap(MyMovable &other) noexcept
+ {
+ MyBase::swap(other);
+ std::swap(i, other.i);
+ }
+
+ friend void swap(MyMovable &lhs, MyMovable &rhs) noexcept { lhs.swap(rhs); }
+
bool operator==(const MyMovable &other) const
{
return i == other.i;
@@ -497,6 +747,15 @@ struct MyComplex
{
return i == other.i;
}
+
+ void swap(MyComplex &other) noexcept
+ {
+ MyBase::swap(other);
+ std::swap(i, other.i);
+ }
+
+ friend void swap(MyComplex &lhs, MyComplex &rhs) noexcept { lhs.swap(rhs); }
+
char i;
};
@@ -704,8 +963,53 @@ void tst_QVarLengthArray::realloc()
QVERIFY(reallocTestProceed);
}
+void tst_QVarLengthArray::iterators()
+{
+ QVarLengthArray<int> emptyArr;
+ QCOMPARE(emptyArr.constBegin(), emptyArr.constEnd());
+ QCOMPARE(emptyArr.cbegin(), emptyArr.cend());
+ QCOMPARE(emptyArr.begin(), emptyArr.end());
+
+ QVarLengthArray<int> arr { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ auto it = arr.begin();
+ auto constIt = arr.cbegin();
+ qsizetype idx = 0;
+
+ QCOMPARE(*it, arr[idx]);
+ QCOMPARE(*constIt, arr[idx]);
+
+ it++;
+ constIt++;
+ idx++;
+ QCOMPARE(*it, arr[idx]);
+ QCOMPARE(*constIt, arr[idx]);
+
+ it += 5;
+ constIt += 5;
+ idx += 5;
+ QCOMPARE(*it, arr[idx]);
+ QCOMPARE(*constIt, arr[idx]);
+
+ it -= 3;
+ constIt -= 3;
+ idx -= 3;
+ QCOMPARE(*it, arr[idx]);
+ QCOMPARE(*constIt, arr[idx]);
+
+ it--;
+ constIt--;
+ idx--;
+ QCOMPARE(*it, arr[idx]);
+ QCOMPARE(*constIt, arr[idx]);
+}
+
void tst_QVarLengthArray::reverseIterators()
{
+ QVarLengthArray<int> emptyArr;
+ QCOMPARE(emptyArr.crbegin(), emptyArr.crend());
+ QCOMPARE(emptyArr.rbegin(), emptyArr.rend());
+
QVarLengthArray<int> v;
v << 1 << 2 << 3 << 4;
QVarLengthArray<int> vr = v;
@@ -724,26 +1028,29 @@ void tst_QVarLengthArray::count()
// tests size(), count() and length(), since they're the same thing
{
const QVarLengthArray<int> list;
- QCOMPARE(list.length(), 0);
- QCOMPARE(list.count(), 0);
QCOMPARE(list.size(), 0);
+ QCOMPARE(list.size(), 0);
+ QCOMPARE(list.size(), 0);
+ QVERIFY(list.isEmpty());
}
{
QVarLengthArray<int> list;
list.append(0);
- QCOMPARE(list.length(), 1);
- QCOMPARE(list.count(), 1);
QCOMPARE(list.size(), 1);
+ QCOMPARE(list.size(), 1);
+ QCOMPARE(list.size(), 1);
+ QVERIFY(!list.isEmpty());
}
{
QVarLengthArray<int> list;
list.append(0);
list.append(1);
- QCOMPARE(list.length(), 2);
- QCOMPARE(list.count(), 2);
QCOMPARE(list.size(), 2);
+ QCOMPARE(list.size(), 2);
+ QCOMPARE(list.size(), 2);
+ QVERIFY(!list.isEmpty());
}
{
@@ -751,9 +1058,10 @@ void tst_QVarLengthArray::count()
list.append(0);
list.append(0);
list.append(0);
- QCOMPARE(list.length(), 3);
- QCOMPARE(list.count(), 3);
QCOMPARE(list.size(), 3);
+ QCOMPARE(list.size(), 3);
+ QCOMPARE(list.size(), 3);
+ QVERIFY(!list.isEmpty());
}
// test removals too
@@ -762,27 +1070,30 @@ void tst_QVarLengthArray::count()
list.append(0);
list.append(0);
list.append(0);
- QCOMPARE(list.length(), 3);
- QCOMPARE(list.count(), 3);
QCOMPARE(list.size(), 3);
+ QCOMPARE(list.size(), 3);
+ QCOMPARE(list.size(), 3);
+ QVERIFY(!list.isEmpty());
list.removeLast();
- QCOMPARE(list.length(), 2);
- QCOMPARE(list.count(), 2);
QCOMPARE(list.size(), 2);
+ QCOMPARE(list.size(), 2);
+ QCOMPARE(list.size(), 2);
+ QVERIFY(!list.isEmpty());
list.removeLast();
- QCOMPARE(list.length(), 1);
- QCOMPARE(list.count(), 1);
QCOMPARE(list.size(), 1);
+ QCOMPARE(list.size(), 1);
+ QCOMPARE(list.size(), 1);
+ QVERIFY(!list.isEmpty());
list.removeLast();
- QCOMPARE(list.length(), 0);
- QCOMPARE(list.count(), 0);
QCOMPARE(list.size(), 0);
+ QCOMPARE(list.size(), 0);
+ QCOMPARE(list.size(), 0);
+ QVERIFY(list.isEmpty());
}
}
void tst_QVarLengthArray::cpp17ctad()
{
-#ifdef __cpp_deduction_guides
#define QVERIFY_IS_VLA_OF(obj, Type) \
QVERIFY2((std::is_same<decltype(obj), QVarLengthArray<Type>>::value), \
QMetaType::fromType<decltype(obj)::value_type>().name())
@@ -802,10 +1113,6 @@ void tst_QVarLengthArray::cpp17ctad()
CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three"));
#undef QVERIFY_IS_VLA_OF
#undef CHECK
-#else
- QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
-#endif
-
}
void tst_QVarLengthArray::first()
@@ -818,16 +1125,16 @@ void tst_QVarLengthArray::first()
QCOMPARE(list.first(), 27);
list.append(1987);
QCOMPARE(list.first(), 27);
- QCOMPARE(list.length(), 3);
+ QCOMPARE(list.size(), 3);
// remove some, make sure it stays sane
list.removeLast();
QCOMPARE(list.first(), 27);
- QCOMPARE(list.length(), 2);
+ QCOMPARE(list.size(), 2);
list.removeLast();
QCOMPARE(list.first(), 27);
- QCOMPARE(list.length(), 1);
+ QCOMPARE(list.size(), 1);
}
void tst_QVarLengthArray::last()
@@ -840,23 +1147,27 @@ void tst_QVarLengthArray::last()
QCOMPARE(list.last(), 4);
list.append(1987);
QCOMPARE(list.last(), 1987);
- QCOMPARE(list.length(), 3);
+ QCOMPARE(list.size(), 3);
// remove some, make sure it stays sane
list.removeLast();
QCOMPARE(list.last(), 4);
- QCOMPARE(list.length(), 2);
+ QCOMPARE(list.size(), 2);
list.removeLast();
QCOMPARE(list.last(), 27);
- QCOMPARE(list.length(), 1);
+ QCOMPARE(list.size(), 1);
}
void tst_QVarLengthArray::squeeze()
{
- QVarLengthArray<int> list;
- int sizeOnStack = list.capacity();
- int sizeOnHeap = sizeOnStack * 2;
+ QVarLengthArray<int, 100> list;
+ qsizetype sizeOnStack = list.capacity();
+ QCOMPARE(sizeOnStack, 100);
+ list.squeeze();
+ QCOMPARE(list.capacity(), sizeOnStack);
+
+ qsizetype sizeOnHeap = sizeOnStack * 2;
list.resize(0);
QCOMPARE(list.capacity(), sizeOnStack);
list.resize(sizeOnHeap);
@@ -889,7 +1200,7 @@ void tst_QVarLengthArray::operators()
// +=: not provided, emulate
//myvla += myvlatwo;
- for (const QString &s : qAsConst(myvlatwo))
+ for (const QString &s : std::as_const(myvlatwo))
myvla.push_back(s);
QCOMPARE(myvla, combined);
@@ -921,6 +1232,10 @@ void tst_QVarLengthArray::operators()
void tst_QVarLengthArray::indexOf()
{
QVarLengthArray<QString> myvec;
+
+ QCOMPARE(myvec.indexOf("A"), -1);
+ QCOMPARE(myvec.indexOf("A", 5), -1);
+
myvec << "A" << "B" << "C" << "B" << "A";
QVERIFY(myvec.indexOf("B") == 1);
@@ -945,6 +1260,10 @@ void tst_QVarLengthArray::indexOf()
void tst_QVarLengthArray::lastIndexOf()
{
QVarLengthArray<QString> myvec;
+
+ QCOMPARE(myvec.lastIndexOf("A"), -1);
+ QCOMPARE(myvec.lastIndexOf("A", 5), -1);
+
myvec << "A" << "B" << "C" << "B" << "A";
QVERIFY(myvec.lastIndexOf("B") == 3);
@@ -968,6 +1287,10 @@ void tst_QVarLengthArray::lastIndexOf()
void tst_QVarLengthArray::contains()
{
QVarLengthArray<QString> myvec;
+
+ QVERIFY(!myvec.contains(QLatin1String("aaa")));
+ QVERIFY(!myvec.contains(QString()));
+
myvec << "aaa" << "bbb" << "ccc";
QVERIFY(myvec.contains(QLatin1String("aaa")));
@@ -983,6 +1306,9 @@ void tst_QVarLengthArray::contains()
void tst_QVarLengthArray::clear()
{
QVarLengthArray<QString, 5> myvec;
+ QCOMPARE(myvec.size(), 0);
+ myvec.clear();
+ QCOMPARE(myvec.size(), 0);
for (int i = 0; i < 10; ++i)
myvec << "aaa";
@@ -1062,6 +1388,17 @@ void tst_QVarLengthArray::insertMove()
QCOMPARE(MyBase::copyCount, 0);
{
+ MyMovable m1, m2;
+ QCOMPARE(MyBase::liveCount, 2);
+ QCOMPARE(MyBase::copyCount, 0);
+ using std::swap;
+ swap(m1, m2);
+ QCOMPARE(MyBase::liveCount, 2);
+ QCOMPARE(MyBase::movedCount, 0);
+ QCOMPARE(MyBase::copyCount, 0);
+ }
+
+ {
QVarLengthArray<MyMovable, 6> vec;
MyMovable m1;
MyMovable m2;
@@ -1087,7 +1424,7 @@ void tst_QVarLengthArray::insertMove()
QCOMPARE(MyBase::liveCount, 6);
QCOMPARE(MyBase::movedCount, 2);
- vec.prepend(std::move(m1));
+ vec.insert(vec.cbegin(), std::move(m1));
QVERIFY(m1.wasConstructedAt(nullptr));
QVERIFY(vec.at(0).wasConstructedAt(&m1));
QVERIFY(vec.at(1).wasConstructedAt(&m3));
@@ -1159,7 +1496,7 @@ void tst_QVarLengthArray::nonCopyable()
QVERIFY(!val4);
QVERIFY(ptr3 == vec.at(0).get());
QVERIFY(ptr4 == vec.at(1).get());
- vec.prepend(std::move(val1));
+ vec.insert(vec.cbegin(), std::move(val1));
QVERIFY(!val1);
QVERIFY(ptr1 == vec.at(0).get());
QVERIFY(ptr3 == vec.at(1).get());
@@ -1193,5 +1530,239 @@ void tst_QVarLengthArray::implicitDefaultCtor()
QCOMPARE(def.size(), 0);
}
+void tst_QVarLengthArray::reserve()
+{
+ QVarLengthArray<int, 100> arr;
+ QCOMPARE(arr.capacity(), 100);
+ QCOMPARE(arr.size(), 0);
+
+ const auto *stackPtr = arr.constData();
+ arr.reserve(50);
+ // Nothing changed, as we reserve less than pre-allocated
+ QCOMPARE(arr.capacity(), 100);
+ QCOMPARE(arr.size(), 0);
+ QCOMPARE(arr.constData(), stackPtr);
+
+ arr.reserve(150);
+ // Allocate memory on heap, as we reserve more than pre-allocated
+ QCOMPARE(arr.capacity(), 150);
+ QCOMPARE(arr.size(), 0);
+ const auto *heapPtr = arr.constData();
+ QVERIFY(heapPtr != stackPtr);
+
+ arr.reserve(50);
+ // Nothing changed
+ QCOMPARE(arr.capacity(), 150);
+ QCOMPARE(arr.constData(), heapPtr);
+
+ arr.squeeze();
+ // After squeeze() we go back to using stack
+ QCOMPARE(arr.capacity(), 100);
+ QCOMPARE(arr.constData(), stackPtr);
+}
+
+void tst_QVarLengthArray::value()
+{
+ const QString def("default value");
+
+ QVarLengthArray<QString> arr;
+ QCOMPARE(arr.value(0), QString());
+ QCOMPARE(arr.value(1, def), def);
+ QCOMPARE(arr.value(-1, def), def);
+
+ const qsizetype size = 5;
+ const QString dataStr("data%1");
+ arr.resize(size);
+ for (qsizetype i = 0; i < size; ++i)
+ arr[i] = dataStr.arg(i);
+
+ for (qsizetype i = 0; i < size; ++i)
+ QCOMPARE(arr.value(i, def), dataStr.arg(i));
+
+ QCOMPARE(arr.value(size + 1), QString());
+ QCOMPARE(arr.value(-1, def), def);
+}
+
+void tst_QVarLengthArray::insert()
+{
+ QFETCH(QVarLengthArray<QString>, arr);
+ QFETCH(int, pos);
+ QFETCH(int, count);
+ QFETCH(QString, data);
+ QFETCH(QVarLengthArray<QString>, expected);
+
+ // Insert using index
+ {
+ QVarLengthArray<QString> copy = arr;
+ if (count == 1) {
+ copy.insert(pos, data);
+ QCOMPARE(copy, expected);
+
+ copy = arr;
+ QString d = data;
+ copy.insert(pos, std::move(d));
+ QCOMPARE(copy, expected);
+ } else {
+ copy.insert(pos, count, data);
+ QCOMPARE(copy, expected);
+ }
+ }
+
+ // Insert using iterator
+ {
+ QVarLengthArray<QString> copy = arr;
+ if (count == 1) {
+ copy.insert(copy.cbegin() + pos, data);
+ QCOMPARE(copy, expected);
+
+ copy = arr;
+ QString d = data;
+ copy.insert(copy.cbegin() + pos, std::move(d));
+ QCOMPARE(copy, expected);
+ } else {
+ copy.insert(copy.cbegin() + pos, count, data);
+ QCOMPARE(copy, expected);
+ }
+ }
+}
+
+void tst_QVarLengthArray::insert_data()
+{
+ QTest::addColumn<QVarLengthArray<QString>>("arr");
+ QTest::addColumn<int>("pos");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<QString>("data");
+ QTest::addColumn<QVarLengthArray<QString>>("expected");
+
+ const QString data("Test");
+
+ QTest::newRow("empty")
+ << QVarLengthArray<QString>() << 0 << 1 << data << QVarLengthArray<QString>({ data });
+ QTest::newRow("empty-none")
+ << QVarLengthArray<QString>() << 0 << 0 << data << QVarLengthArray<QString>();
+ QTest::newRow("begin")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 0 << 1 << data
+ << QVarLengthArray<QString>({ data, "value1", "value2" });
+ QTest::newRow("end")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 2 << 1 << data
+ << QVarLengthArray<QString>({ "value1", "value2", data });
+ QTest::newRow("middle")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 1 << 1 << data
+ << QVarLengthArray<QString>({ "value1", data, "value2" });
+ QTest::newRow("begin-none")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 0 << 0 << data
+ << QVarLengthArray<QString>({ "value1", "value2" });
+ QTest::newRow("end-none")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 2 << 0 << data
+ << QVarLengthArray<QString>({ "value1", "value2" });
+ QTest::newRow("middle-none")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 1 << 0 << data
+ << QVarLengthArray<QString>({ "value1", "value2" });
+ QTest::newRow("multi begin")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 0 << 2 << data
+ << QVarLengthArray<QString>({ data, data, "value1", "value2" });
+ QTest::newRow("multi end")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 2 << 2 << data
+ << QVarLengthArray<QString>({ "value1", "value2", data, data });
+ QTest::newRow("multi middle")
+ << QVarLengthArray<QString>({ "value1", "value2" }) << 1 << 2 << data
+ << QVarLengthArray<QString>({ "value1", data, data, "value2" });
+}
+
+void tst_QVarLengthArray::replace()
+{
+ QVarLengthArray<QString> arr({ "val0", "val1", "val2" });
+
+ arr.replace(0, "data0");
+ QCOMPARE(arr, QVarLengthArray<QString>({ "data0", "val1", "val2" }));
+
+ arr.replace(2, "data2");
+ QCOMPARE(arr, QVarLengthArray<QString>({ "data0", "val1", "data2" }));
+
+ arr.replace(1, "data1");
+ QCOMPARE(arr, QVarLengthArray<QString>({ "data0", "data1", "data2" }));
+}
+
+void tst_QVarLengthArray::remove()
+{
+ auto isVal2 = [](const QString &str) { return str == "val2"; };
+
+ QVarLengthArray<QString> arr;
+ QCOMPARE(arr.removeAll("val0"), 0);
+ QVERIFY(!arr.removeOne("val1"));
+ QCOMPARE(arr.removeIf(isVal2), 0);
+
+ arr << "val0" << "val1" << "val2";
+ arr << "val0" << "val1" << "val2";
+ arr << "val0" << "val1" << "val2";
+
+ QCOMPARE(arr.size(), 9);
+
+ arr.remove(1, 3);
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val0", "val1", "val2", "val0", "val1", "val2" }));
+
+ arr.remove(2);
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val0", "val1", "val0", "val1", "val2" }));
+
+ QVERIFY(arr.removeOne("val1"));
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val0", "val0", "val1", "val2" }));
+
+ QCOMPARE(arr.removeAll("val0"), 2);
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val1", "val2" }));
+
+ QCOMPARE(arr.removeIf(isVal2), 1);
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val1" }));
+
+ arr.removeLast();
+ QVERIFY(arr.isEmpty());
+}
+
+void tst_QVarLengthArray::erase()
+{
+ QVarLengthArray<QString> arr;
+ QCOMPARE(arr.erase(arr.cbegin(), arr.cend()), arr.cend());
+
+ arr << "val0" << "val1" << "val2";
+ arr << "val0" << "val1" << "val2";
+ arr << "val0" << "val1" << "val2";
+
+ auto it = arr.erase(arr.cbegin() + 1, arr.cend() - 3);
+ QCOMPARE(it, arr.cend() - 3);
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val0", "val0", "val1", "val2" }));
+
+ it = arr.erase(arr.cbegin());
+ QCOMPARE(it, arr.cbegin());
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val0", "val1", "val2" }));
+
+ it = arr.erase(arr.cbegin() + 1);
+ QCOMPARE(it, arr.cend() - 1);
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val0", "val2" }));
+
+ it = arr.erase(arr.cend() - 1);
+ QCOMPARE(it, arr.cend());
+ QCOMPARE(arr, QVarLengthArray<QString>({ "val0" }));
+}
+
+void tst_QVarLengthArray::copesWithCopyabilityOfMoveOnlyVector()
+{
+ // std::vector<move-only-type> is_copyable
+ // (https://quuxplusone.github.io/blog/2020/02/05/vector-is-copyable-except-when-its-not/)
+
+ QVarLengthArray<std::vector<std::unique_ptr<int>>, 2> vla;
+ vla.emplace_back(42);
+ vla.emplace_back(43);
+ vla.emplace_back(44); // goes to the heap
+ QCOMPARE_EQ(vla.size(), 3);
+ QCOMPARE_EQ(vla.front().size(), 42U);
+ QCOMPARE_EQ(vla.front().front(), nullptr);
+ QCOMPARE_EQ(vla.back().size(), 44U);
+
+ auto moved = std::move(vla);
+ QCOMPARE_EQ(moved.size(), 3);
+ QCOMPARE_EQ(moved.front().size(), 42U);
+ QCOMPARE_EQ(moved.front().front(), nullptr);
+ QCOMPARE_EQ(moved.back().size(), 44U);
+}
+
QTEST_APPLESS_MAIN(tst_QVarLengthArray)
#include "tst_qvarlengtharray.moc"