diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-05-27 09:58:12 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-06-20 20:01:33 +0200 |
commit | 03326a2fec416405b437089874f6439e937bbada (patch) | |
tree | 48d7137c3cd5e6f537e06e97380d3c1e76a56af9 /tests/auto/corelib/tools/qvector/tst_qvector.cpp | |
parent | 1a9a4af388477efd9f7008d5c0bb74432c20279d (diff) |
Move implementation of QVector/List back to qlist.h
And name the main class QList. That's also the one we document.
This gives less porting pain for our users, and a lot less churn
in our API, as we use QList in Qt 5 in 95% of our API.
In addition, it gives more consistent naming with QStringList and
QByteArrayList and disambiguates QList vs QVector(2|3|4)D.
Fixes: QTBUG-84468
Change-Id: I3cba9d1d3179969d8bf9320b31be2230d021d1a9
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests/auto/corelib/tools/qvector/tst_qvector.cpp')
-rw-r--r-- | tests/auto/corelib/tools/qvector/tst_qvector.cpp | 2834 |
1 files changed, 0 insertions, 2834 deletions
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp deleted file mode 100644 index 899156545d..0000000000 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ /dev/null @@ -1,2834 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include <QtTest/QtTest> -#include <QAtomicInt> -#include <QThread> -#include <QSemaphore> -#include <qvector.h> - -struct Movable { - Movable(char input = 'j') - : i(input) - , that(this) - , state(Constructed) - { - counter.fetchAndAddRelaxed(1); - } - Movable(const Movable &other) - : i(other.i) - , that(this) - , state(Constructed) - { - check(other.state, Constructed); - counter.fetchAndAddRelaxed(1); - } - Movable(Movable &&other) - : i(other.i) - , that(other.that) - , state(Constructed) - { - check(other.state, Constructed); - counter.fetchAndAddRelaxed(1); - other.that = nullptr; - } - - ~Movable() - { - check(state, Constructed); - i = 0; - counter.fetchAndAddRelaxed(-1); - state = Destructed; - } - - bool operator ==(const Movable &other) const - { - check(state, Constructed); - check(other.state, Constructed); - return i == other.i; - } - - Movable &operator=(const Movable &other) - { - check(state, Constructed); - check(other.state, Constructed); - i = other.i; - that = this; - return *this; - } - Movable &operator=(Movable &&other) - { - check(state, Constructed); - check(other.state, Constructed); - i = other.i; - that = other.that; - other.that = nullptr; - return *this; - } - bool wasConstructedAt(const Movable *other) const - { - return that == other; - } - char i; - static QAtomicInt counter; -private: - Movable *that; // used to check if an instance was moved - - enum State { Constructed = 106, Destructed = 110 }; - State state; - - static void check(const State state1, const State state2) - { - QCOMPARE(int(state1), int(state2)); - } -}; - -inline size_t qHash(const Movable &key, size_t seed = 0) { return qHash(key.i, seed); } - -QAtomicInt Movable::counter = 0; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); -QT_END_NAMESPACE -Q_DECLARE_METATYPE(Movable); - -struct Custom { - Custom(char input = 'j') - : i(input) - , that(this) - , state(Constructed) - { - counter.fetchAndAddRelaxed(1); - } - Custom(const Custom &other) - : that(this) - , state(Constructed) - { - check(&other); - counter.fetchAndAddRelaxed(1); - this->i = other.i; - } - ~Custom() - { - check(this); - i = 0; - counter.fetchAndAddRelaxed(-1); - state = Destructed; - } - - bool operator ==(const Custom &other) const - { - check(&other); - check(this); - return i == other.i; - } - - bool operator<(const Custom &other) const - { - check(&other); - check(this); - return i < other.i; - } - - Custom &operator=(const Custom &other) - { - check(&other); - check(this); - i = other.i; - return *this; - } - static QAtomicInt counter; - - char i; // used to identify orgin of an instance -private: - Custom *that; // used to check if an instance was moved - - enum State { Constructed = 106, Destructed = 110 }; - State state; - - static void check(const Custom *c) - { - // check if c object has been moved - QCOMPARE(c, c->that); - QCOMPARE(int(c->state), int(Constructed)); - } -}; -QAtomicInt Custom::counter = 0; - -inline size_t qHash(const Custom &key, size_t seed = 0) { return qHash(key.i, seed); } - -Q_DECLARE_METATYPE(Custom); - -// tests depends on the fact that: -static_assert(!QTypeInfo<int>::isStatic); -static_assert(!QTypeInfo<int>::isComplex); -static_assert(!QTypeInfo<Movable>::isStatic); -static_assert(QTypeInfo<Movable>::isComplex); -static_assert(QTypeInfo<Custom>::isStatic); -static_assert(QTypeInfo<Custom>::isComplex); - - -class tst_QVector : public QObject -{ - Q_OBJECT -private slots: - void constructors_empty() const; - void constructors_emptyReserveZero() const; - void constructors_emptyReserve() const; - void constructors_reserveAndInitialize() const; - void copyConstructorInt() const; - void copyConstructorMovable() const; - void copyConstructorCustom() const; - void assignmentInt() const; - void assignmentMovable() const; - void assignmentCustom() const; - void assignFromInitializerListInt() const; - void assignFromInitializerListMovable() const; - void assignFromInitializerListCustom() const; - void addInt() const; - void addMovable() const; - void addCustom() const; - void appendInt() const; - void appendMovable() const; - void appendCustom() const; - void appendRvalue() const; - void at() const; - void capacityInt() const; - void capacityMovable() const; - void capacityCustom() const; - void clearInt() const; - void clearMovable() const; - void clearCustom() const; - void constData() const; - void constFirst() const; - void constLast() const; - void contains() const; - void countInt() const; - void countMovable() const; - void countCustom() const; - void cpp17ctad() const; - void data() const; - void emptyInt() const; - void emptyMovable() const; - void emptyCustom() const; - void endsWith() const; - void eraseEmptyInt() const; - void eraseEmptyMovable() const; - void eraseEmptyCustom() const; - void eraseEmptyReservedInt() const; - void eraseEmptyReservedMovable() const; - void eraseEmptyReservedCustom() const; - void eraseInt() const; - void eraseIntShared() const; - void eraseMovable() const; - void eraseMovableShared() const; - void eraseCustom() const; - void eraseCustomShared() const; - void eraseReservedInt() const; - void eraseReservedMovable() const; - void eraseReservedCustom() const; - void fillInt() const; - void fillMovable() const; - void fillCustom() const; - void fillDetaches() const; - void first() const; - void fromListInt() const; - void fromListMovable() const; - void fromListCustom() const; - void indexOf() const; - void insertInt() const; - void insertMovable() const; - void insertCustom() const; - void isEmpty() const; - void last() const; - void lastIndexOf() const; - void mid() const; - void moveInt() const; - void moveMovable() const; - void moveCustom() const; - void prependInt() const; - void prependMovable() const; - void prependCustom() const; - void qhashInt() const { qhash<int>(); } - void qhashMovable() const { qhash<Movable>(); } - void qhashCustom() const { qhash<Custom>(); } - void removeAllWithAlias() const; - void removeInt() const; - void removeMovable() const; - void removeCustom() const; - void removeFirstLast() const; - void resizePOD_data() const; - void resizePOD() const; - void resizeComplexMovable_data() const; - void resizeComplexMovable() const; - void resizeComplex_data() const; - void resizeComplex() const; - void resizeCtorAndDtor() const; - void reverseIterators() const; - void sizeInt() const; - void sizeMovable() const; - void sizeCustom() const; - void startsWith() const; - void swapInt() const; - void swapMovable() const; - void swapCustom() const; - void toList() const; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - void fromStdVector() const; - void toStdVector() const; -#endif - void value() const; - - void testOperators() const; - - void reserve(); - void reserveZero(); - void initializeListInt(); - void initializeListMovable(); - void initializeListCustom(); - - void const_shared_null(); - - void detachInt() const; - void detachMovable() const; - void detachCustom() const; - void detachThreadSafetyInt() const; - void detachThreadSafetyMovable() const; - void detachThreadSafetyCustom() const; - - void insertMove() const; - - void swapItemsAt() const; - - void emplaceInt(); - void emplaceCustom(); - void emplaceMovable(); - void emplaceConsistentWithStdVectorInt(); - void emplaceConsistentWithStdVectorCustom(); - void emplaceConsistentWithStdVectorMovable(); - void emplaceReturnsIterator(); - void emplaceBack(); - void emplaceBackReturnsRef(); - void emplaceWithElementFromTheSameContainer(); - void emplaceWithElementFromTheSameContainer_data(); - -private: - template<typename T> void copyConstructor() const; - template<typename T> void add() const; - template<typename T> void append() const; - template<typename T> void assignFromInitializerList() const; - template<typename T> void capacity() const; - template<typename T> void clear() const; - template<typename T> void count() const; - template<typename T> void empty() const; - template<typename T> void eraseEmpty() const; - template<typename T> void eraseEmptyReserved() const; - template<typename T> void erase(bool shared) const; - template<typename T> void eraseReserved() const; - template<typename T> void fill() const; - template<typename T> void fromList() const; - template<typename T> void insert() const; - template<typename T> void qhash() const; - template<typename T> void move() const; - template<typename T> void prepend() const; - template<typename T> void remove() const; - template<typename T> void size() const; - template<typename T> void swap() const; - template<typename T> void initializeList(); - template<typename T> void detach() const; - template<typename T> void detachThreadSafety() const; - template<typename T> void emplaceImpl() const; - template<typename T> void emplaceConsistentWithStdVectorImpl() const; -}; - - -template<typename T> struct SimpleValue -{ - static T at(int index) - { - return Values[index % MaxIndex]; - } - - static QVector<T> vector(int size) - { - QVector<T> ret; - for (int i = 0; i < size; i++) - ret.append(at(i)); - return ret; - } - - static const uint MaxIndex = 6; - static const T Values[MaxIndex]; -}; - -template<> -const int SimpleValue<int>::Values[] = { 110, 105, 101, 114, 111, 98 }; -template<> -const Movable SimpleValue<Movable>::Values[] = { 110, 105, 101, 114, 111, 98 }; -template<> -const Custom SimpleValue<Custom>::Values[] = { 110, 105, 101, 114, 111, 98 }; - -// Make some macros for the tests to use in order to be slightly more readable... -#define T_FOO SimpleValue<T>::at(0) -#define T_BAR SimpleValue<T>::at(1) -#define T_BAZ SimpleValue<T>::at(2) -#define T_CAT SimpleValue<T>::at(3) -#define T_DOG SimpleValue<T>::at(4) -#define T_BLAH SimpleValue<T>::at(5) - -void tst_QVector::constructors_empty() const -{ - QVector<int> emptyInt; - QVector<Movable> emptyMovable; - QVector<Custom> emptyCustom; -} - -void tst_QVector::constructors_emptyReserveZero() const -{ - QVector<int> emptyInt(0); - QVector<Movable> emptyMovable(0); - QVector<Custom> emptyCustom(0); -} - -void tst_QVector::constructors_emptyReserve() const -{ - // pre-reserve capacity - QVector<int> myInt(5); - QVERIFY(myInt.capacity() == 5); - QVector<Movable> myMovable(5); - QVERIFY(myMovable.capacity() == 5); - QVector<Custom> myCustom(4); - QVERIFY(myCustom.capacity() == 4); -} - -void tst_QVector::constructors_reserveAndInitialize() const -{ - // default-initialise items - - QVector<int> myInt(5, 42); - QVERIFY(myInt.capacity() == 5); - foreach (int meaningoflife, myInt) { - QCOMPARE(meaningoflife, 42); - } - - QVector<QString> myString(5, QString::fromLatin1("c++")); - QVERIFY(myString.capacity() == 5); - // make sure all items are initialised ok - foreach (QString meaningoflife, myString) { - QCOMPARE(meaningoflife, QString::fromLatin1("c++")); - } - - QVector<Custom> myCustom(5, Custom('n')); - QVERIFY(myCustom.capacity() == 5); - // make sure all items are initialised ok - foreach (Custom meaningoflife, myCustom) { - QCOMPARE(meaningoflife.i, 'n'); - } -} - -template<typename T> -void tst_QVector::copyConstructor() const -{ - T value1(SimpleValue<T>::at(0)); - T value2(SimpleValue<T>::at(1)); - T value3(SimpleValue<T>::at(2)); - T value4(SimpleValue<T>::at(3)); - { - QVector<T> v1; - QVector<T> v2(v1); - QCOMPARE(v1, v2); - } - { - QVector<T> v1; - v1 << value1 << value2 << value3 << value4; - QVector<T> v2(v1); - QCOMPARE(v1, v2); - } -} - -void tst_QVector::copyConstructorInt() const -{ - copyConstructor<int>(); -} - -void tst_QVector::copyConstructorMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - copyConstructor<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::copyConstructorCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - copyConstructor<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template <class T> -static inline void testAssignment() -{ - QVector<T> v1(5); - QCOMPARE(v1.size(), 5); - QVERIFY(v1.isDetached()); - - QVector<T> v2(7); - QCOMPARE(v2.size(), 7); - QVERIFY(v2.isDetached()); - - QVERIFY(!v1.isSharedWith(v2)); - - v1 = v2; - - QVERIFY(!v1.isDetached()); - QVERIFY(!v2.isDetached()); - QVERIFY(v1.isSharedWith(v2)); - - const void *const data1 = v1.constData(); - const void *const data2 = v2.constData(); - - QCOMPARE(data1, data2); - - v1.clear(); - - QVERIFY(v2.isDetached()); - QVERIFY(!v1.isSharedWith(v2)); - QCOMPARE((void *)v2.constData(), data2); -} - -void tst_QVector::assignmentInt() const -{ - testAssignment<int>(); -} - -void tst_QVector::assignmentMovable() const -{ - testAssignment<Movable>(); -} - -void tst_QVector::assignmentCustom() const -{ - testAssignment<Custom>(); -} - -template<typename T> -void tst_QVector::assignFromInitializerList() const -{ - T val1(SimpleValue<T>::at(1)); - T val2(SimpleValue<T>::at(2)); - T val3(SimpleValue<T>::at(3)); - - QVector<T> v1 = {val1, val2, val3}; - QCOMPARE(v1, QVector<T>() << val1 << val2 << val3); - QCOMPARE(v1, (QVector<T> {val1, val2, val3})); - - v1 = {}; - QCOMPARE(v1.size(), 0); -} - -void tst_QVector::assignFromInitializerListInt() const -{ - assignFromInitializerList<int>(); -} - -void tst_QVector::assignFromInitializerListMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - assignFromInitializerList<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::assignFromInitializerListCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - assignFromInitializerList<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> -void tst_QVector::add() const -{ - { - QVector<T> empty1; - QVector<T> empty2; - QVERIFY((empty1 + empty2).isEmpty()); - empty1 += empty2; - QVERIFY(empty1.isEmpty()); - QVERIFY(empty2.isEmpty()); - } - { - QVector<T> v(12); - QVector<T> empty; - QCOMPARE((v + empty), v); - v += empty; - QVERIFY(!v.isEmpty()); - QCOMPARE(v.size(), 12); - QVERIFY(empty.isEmpty()); - } - { - QVector<T> v1(12); - QVector<T> v2; - v2 += v1; - QVERIFY(!v1.isEmpty()); - QCOMPARE(v1.size(), 12); - QVERIFY(!v2.isEmpty()); - QCOMPARE(v2.size(), 12); - } -} - -void tst_QVector::addInt() const -{ - add<int>(); -} - -void tst_QVector::addMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - add<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::addCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - add<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> -void tst_QVector::append() const -{ - { - QVector<T> myvec; - myvec.append(SimpleValue<T>::at(0)); - QVERIFY(myvec.size() == 1); - myvec.append(SimpleValue<T>::at(1)); - QVERIFY(myvec.size() == 2); - myvec.append(SimpleValue<T>::at(2)); - QVERIFY(myvec.size() == 3); - - QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(0) - << SimpleValue<T>::at(1) - << SimpleValue<T>::at(2)); - } - { - QVector<T> v(2); - v.append(SimpleValue<T>::at(0)); - QVERIFY(v.size() == 3); - QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0)); - } - { - QVector<T> v(2); - v.reserve(12); - v.append(SimpleValue<T>::at(0)); - QVERIFY(v.size() == 3); - QCOMPARE(v.at(v.size() - 1), SimpleValue<T>::at(0)); - } - { - QVector<int> v; - v << 1 << 2 << 3; - QVector<int> x; - x << 4 << 5 << 6; - v.append(x); - - QVector<int> combined; - combined << 1 << 2 << 3 << 4 << 5 << 6; - - QCOMPARE(v, combined); - } -} - -void tst_QVector::appendInt() const -{ - append<int>(); -} - -void tst_QVector::appendMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - append<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::appendCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - append<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::appendRvalue() const -{ - QVector<QString> v; - v.append("hello"); - QString world = "world"; - v.append(std::move(world)); - QVERIFY(world.isEmpty()); - QCOMPARE(v.front(), QString("hello")); - QCOMPARE(v.back(), QString("world")); -} - -void tst_QVector::at() const -{ - QVector<QString> myvec; - myvec << "foo" << "bar" << "baz"; - - QVERIFY(myvec.size() == 3); - QCOMPARE(myvec.at(0), QLatin1String("foo")); - QCOMPARE(myvec.at(1), QLatin1String("bar")); - QCOMPARE(myvec.at(2), QLatin1String("baz")); - - // append an item - myvec << "hello"; - QVERIFY(myvec.size() == 4); - QCOMPARE(myvec.at(0), QLatin1String("foo")); - QCOMPARE(myvec.at(1), QLatin1String("bar")); - QCOMPARE(myvec.at(2), QLatin1String("baz")); - QCOMPARE(myvec.at(3), QLatin1String("hello")); - - // remove an item - myvec.remove(1); - QVERIFY(myvec.size() == 3); - QCOMPARE(myvec.at(0), QLatin1String("foo")); - QCOMPARE(myvec.at(1), QLatin1String("baz")); - QCOMPARE(myvec.at(2), QLatin1String("hello")); -} - -template<typename T> -void tst_QVector::capacity() const -{ - QVector<T> myvec; - - // TODO: is this guaranteed? seems a safe assumption, but I suppose preallocation of a - // few items isn't an entirely unforseeable possibility. - QVERIFY(myvec.capacity() == 0); - - // test it gets a size - myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); - QVERIFY(myvec.capacity() >= 3); - - // make sure it grows ok - myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); - QVERIFY(myvec.capacity() >= 6); - // let's try squeeze a bit - myvec.remove(3); - myvec.remove(3); - myvec.remove(3); - myvec.squeeze(); - QVERIFY(myvec.capacity() >= 3); - - myvec.remove(0); - myvec.remove(0); - myvec.remove(0); - myvec.squeeze(); - QVERIFY(myvec.capacity() == 0); -} - -void tst_QVector::capacityInt() const -{ - capacity<int>(); -} - -void tst_QVector::capacityMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - capacity<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::capacityCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - capacity<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> -void tst_QVector::clear() const -{ - QVector<T> myvec; - myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); - - const auto oldCapacity = myvec.capacity(); - QCOMPARE(myvec.size(), 3); - myvec.clear(); - QCOMPARE(myvec.size(), 0); - QCOMPARE(myvec.capacity(), oldCapacity); -} - -void tst_QVector::clearInt() const -{ - clear<int>(); -} - -void tst_QVector::clearMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - clear<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::clearCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - clear<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::constData() const -{ - int arr[] = { 42, 43, 44 }; - QVector<int> myvec; - myvec << 42 << 43 << 44; - - QVERIFY(memcmp(myvec.constData(), reinterpret_cast<const int *>(&arr), sizeof(int) * 3) == 0); -} - -void tst_QVector::contains() const -{ - QVector<QString> myvec; - myvec << "aaa" << "bbb" << "ccc"; - - QVERIFY(myvec.contains(QLatin1String("aaa"))); - QVERIFY(myvec.contains(QLatin1String("bbb"))); - QVERIFY(myvec.contains(QLatin1String("ccc"))); - QVERIFY(!myvec.contains(QLatin1String("I don't exist"))); - - // add it and make sure it does :) - myvec.append(QLatin1String("I don't exist")); - QVERIFY(myvec.contains(QLatin1String("I don't exist"))); -} - -template<typename T> -void tst_QVector::count() const -{ - // total size - { - // zero size - QVector<T> myvec; - QVERIFY(myvec.count() == 0); - - // grow - myvec.append(SimpleValue<T>::at(0)); - QVERIFY(myvec.count() == 1); - myvec.append(SimpleValue<T>::at(1)); - QVERIFY(myvec.count() == 2); - - // shrink - myvec.remove(0); - QVERIFY(myvec.count() == 1); - myvec.remove(0); - QVERIFY(myvec.count() == 0); - } - - // count of items - { - QVector<T> myvec; - myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); - - // initial tests - QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1); - QVERIFY(myvec.count(SimpleValue<T>::at(3)) == 0); - - // grow - myvec.append(SimpleValue<T>::at(0)); - QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 2); - - // shrink - myvec.remove(0); - QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1); - } -} - -void tst_QVector::countInt() const -{ - count<int>(); -} - -void tst_QVector::countMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - count<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::countCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - count<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::cpp17ctad() const -{ -#ifdef __cpp_deduction_guides -#define QVERIFY_IS_VECTOR_OF(obj, Type) \ - QVERIFY2((std::is_same<decltype(obj), QVector<Type>>::value), \ - QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>())) -#define CHECK(Type, One, Two, Three) \ - do { \ - const Type v[] = {One, Two, Three}; \ - QVector v1 = {One, Two, Three}; \ - QVERIFY_IS_VECTOR_OF(v1, Type); \ - QVector v2(v1.begin(), v1.end()); \ - QVERIFY_IS_VECTOR_OF(v2, Type); \ - QVector v3(std::begin(v), std::end(v)); \ - QVERIFY_IS_VECTOR_OF(v3, Type); \ - } while (false) \ - /*end*/ - CHECK(int, 1, 2, 3); - CHECK(double, 1.0, 2.0, 3.0); - CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three")); -#undef QVERIFY_IS_VECTOR_OF -#undef CHECK -#else - QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler."); -#endif -} - -void tst_QVector::data() const -{ - QVector<int> myvec; - myvec << 42 << 43 << 44; - - // make sure it starts off ok - QCOMPARE(*(myvec.data() + 1), 43); - - // alter it - *(myvec.data() + 1) = 69; - - // check it altered - QCOMPARE(*(myvec.data() + 1), 69); - - int arr[] = { 42, 69, 44 }; - QVERIFY(memcmp(myvec.data(), reinterpret_cast<int *>(&arr), sizeof(int) * 3) == 0); -} - -template<typename T> -void tst_QVector::empty() const -{ - QVector<T> myvec; - - // starts empty - QVERIFY(myvec.empty()); - - // not empty - myvec.append(SimpleValue<T>::at(2)); - QVERIFY(!myvec.empty()); - - // empty again - myvec.remove(0); - QVERIFY(myvec.empty()); -} - -void tst_QVector::emptyInt() const -{ - empty<int>(); -} - -void tst_QVector::emptyMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - empty<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::emptyCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - empty<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::endsWith() const -{ - QVector<int> myvec; - - // empty vector - QVERIFY(!myvec.endsWith(1)); - - // add the one, should work - myvec.append(1); - QVERIFY(myvec.endsWith(1)); - - // add something else, fails now - myvec.append(3); - QVERIFY(!myvec.endsWith(1)); - - // remove it again :) - myvec.remove(1); - QVERIFY(myvec.endsWith(1)); -} - -template<typename T> -void tst_QVector::eraseEmpty() const -{ - QVector<T> v; - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); -} - -void tst_QVector::eraseEmptyInt() const -{ - eraseEmpty<int>(); -} - -void tst_QVector::eraseEmptyMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - eraseEmpty<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseEmptyCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - eraseEmpty<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> -void tst_QVector::eraseEmptyReserved() const -{ - QVector<T> v; - v.reserve(10); - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); -} - -void tst_QVector::eraseEmptyReservedInt() const -{ - eraseEmptyReserved<int>(); -} - -void tst_QVector::eraseEmptyReservedMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - eraseEmptyReserved<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseEmptyReservedCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - eraseEmptyReserved<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> -struct SharedVectorChecker -{ - SharedVectorChecker(const QVector<T> &original, bool doCopyVector) - : originalSize(-1), - copy(0) - { - if (doCopyVector) { - originalSize = original.size(); - copy = new QVector<T>(original); - // this is unlikely to fail, but if the check in the destructor fails it's good to know that - // we were still alright here. - QCOMPARE(originalSize, copy->size()); - } - } - - ~SharedVectorChecker() - { - if (copy) - QCOMPARE(copy->size(), originalSize); - delete copy; - } - - int originalSize; - QVector<T> *copy; -}; - -template<typename T> -void tst_QVector::erase(bool shared) const -{ - // note: remove() is actually more efficient, and more dangerous, because it uses the non-detaching - // begin() / end() internally. you can also use constBegin() and constEnd() with erase(), but only - // using reinterpret_cast... because both iterator types are really just pointers. - // so we use a mix of erase() and remove() to cover more cases. - { - QVector<T> v = SimpleValue<T>::vector(12); - SharedVectorChecker<T> svc(v, shared); - v.erase(v.begin()); - QCOMPARE(v.size(), 11); - for (int i = 0; i < 11; i++) - QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1)); - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); - if (shared) - QCOMPARE(SimpleValue<T>::vector(12), *svc.copy); - } - { - QVector<T> v = SimpleValue<T>::vector(12); - SharedVectorChecker<T> svc(v, shared); - v.remove(1); - QCOMPARE(v.size(), 11); - QCOMPARE(v.at(0), SimpleValue<T>::at(0)); - for (int i = 1; i < 11; i++) - QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1)); - v.erase(v.begin() + 1, v.end()); - QCOMPARE(v.size(), 1); - QCOMPARE(v.at(0), SimpleValue<T>::at(0)); - if (shared) - QCOMPARE(SimpleValue<T>::vector(12), *svc.copy); - } - { - QVector<T> v = SimpleValue<T>::vector(12); - SharedVectorChecker<T> svc(v, shared); - v.erase(v.begin(), v.end() - 1); - QCOMPARE(v.size(), 1); - QCOMPARE(v.at(0), SimpleValue<T>::at(11)); - if (shared) - QCOMPARE(SimpleValue<T>::vector(12), *svc.copy); - } - { - QVector<T> v = SimpleValue<T>::vector(12); - SharedVectorChecker<T> svc(v, shared); - v.remove(5); - QCOMPARE(v.size(), 11); - for (int i = 0; i < 5; i++) - QCOMPARE(v.at(i), SimpleValue<T>::at(i)); - for (int i = 5; i < 11; i++) - QCOMPARE(v.at(i), SimpleValue<T>::at(i + 1)); - v.erase(v.begin() + 1, v.end() - 1); - QCOMPARE(v.at(0), SimpleValue<T>::at(0)); - QCOMPARE(v.at(1), SimpleValue<T>::at(11)); - QCOMPARE(v.size(), 2); - if (shared) - QCOMPARE(SimpleValue<T>::vector(12), *svc.copy); - } -} - -void tst_QVector::eraseInt() const -{ - erase<int>(false); -} - -void tst_QVector::eraseIntShared() const -{ - erase<int>(true); -} - -void tst_QVector::eraseMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - erase<Movable>(false); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseMovableShared() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - erase<Movable>(true); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - erase<Custom>(false); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::eraseCustomShared() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - erase<Custom>(true); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> void tst_QVector::eraseReserved() const -{ - { - QVector<T> v(12); - v.reserve(16); - v.erase(v.begin()); - QCOMPARE(v.size(), 11); - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); - } - { - QVector<T> v(12); - v.reserve(16); - v.erase(v.begin() + 1); - QCOMPARE(v.size(), 11); - v.erase(v.begin() + 1, v.end()); - QCOMPARE(v.size(), 1); - } - { - QVector<T> v(12); - v.reserve(16); - v.erase(v.begin(), v.end() - 1); - QCOMPARE(v.size(), 1); - } - { - QVector<T> v(12); - v.reserve(16); - v.erase(v.begin() + 5); - QCOMPARE(v.size(), 11); - v.erase(v.begin() + 1, v.end() - 1); - QCOMPARE(v.size(), 2); - } -} - -void tst_QVector::eraseReservedInt() const -{ - eraseReserved<int>(); -} - -void tst_QVector::eraseReservedMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - eraseReserved<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseReservedCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - eraseReserved<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> -void tst_QVector::fill() const -{ - QVector<T> myvec; - - // resize - myvec.resize(5); - myvec.fill(SimpleValue<T>::at(1)); - QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(1) << SimpleValue<T>::at(1) - << SimpleValue<T>::at(1) << SimpleValue<T>::at(1) - << SimpleValue<T>::at(1)); - - // make sure it can resize itself too - myvec.fill(SimpleValue<T>::at(2), 10); - QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(2) << SimpleValue<T>::at(2) - << SimpleValue<T>::at(2) << SimpleValue<T>::at(2) - << SimpleValue<T>::at(2) << SimpleValue<T>::at(2) - << SimpleValue<T>::at(2) << SimpleValue<T>::at(2) - << SimpleValue<T>::at(2) << SimpleValue<T>::at(2)); -} - -void tst_QVector::fillInt() const -{ - fill<int>(); -} - -void tst_QVector::fillMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - fill<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::fillCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - fill<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::fillDetaches() const -{ - QVector<int> test = { 1, 2, 3 }; - QVector<int> copy = test; - copy.fill(42); - - QCOMPARE(test, QVector<int>({1, 2, 3})); - QCOMPARE(copy, QVector<int>({42, 42, 42})); -} - -void tst_QVector::first() const -{ - QVector<int> myvec; - myvec << 69 << 42 << 3; - - // test it starts ok - QCOMPARE(myvec.first(), 69); - QCOMPARE(myvec.constFirst(), 69); - - // test removal changes - myvec.remove(0); - QCOMPARE(myvec.first(), 42); - QCOMPARE(myvec.constFirst(), 42); - - // test prepend changes - myvec.prepend(23); - QCOMPARE(myvec.first(), 23); - QCOMPARE(myvec.constFirst(), 23); -} - -void tst_QVector::constFirst() const -{ - QVector<int> myvec; - myvec << 69 << 42 << 3; - - // test it starts ok - QCOMPARE(myvec.constFirst(), 69); - QVERIFY(myvec.isDetached()); - - QVector<int> myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constFirst(), 69); - QCOMPARE(myvecCopy.constFirst(), 69); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test removal changes - myvec.remove(0); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constFirst(), 42); - QCOMPARE(myvecCopy.constFirst(), 69); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constFirst(), 42); - QCOMPARE(myvecCopy.constFirst(), 42); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test prepend changes - myvec.prepend(23); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constFirst(), 23); - QCOMPARE(myvecCopy.constFirst(), 42); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constFirst(), 23); - QCOMPARE(myvecCopy.constFirst(), 23); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); -} - - -template<typename T> -void tst_QVector::fromList() const -{ - QList<T> list; - list << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3); - - QVector<T> myvec; - myvec = QVector<T>::fromList(list); - - // test it worked ok - QCOMPARE(myvec, QVector<T>() << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3)); - QCOMPARE(list, QList<T>() << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3)); -} - -void tst_QVector::fromListInt() const -{ - fromList<int>(); -} - -void tst_QVector::fromListMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - fromList<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::fromListCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - fromList<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -void tst_QVector::fromStdVector() const -{ - // stl = :( - std::vector<QString> svec; - svec.push_back(QLatin1String("aaa")); - svec.push_back(QLatin1String("bbb")); - svec.push_back(QLatin1String("ninjas")); - svec.push_back(QLatin1String("pirates")); - QVector<QString> myvec = QVector<QString>::fromStdVector(svec); - - // test it converts ok - QCOMPARE(myvec, QVector<QString>() << "aaa" << "bbb" << "ninjas" << "pirates"); -} -#endif - -void tst_QVector::indexOf() const -{ - QVector<QString> myvec; - myvec << "A" << "B" << "C" << "B" << "A"; - - QVERIFY(myvec.indexOf("B") == 1); - QVERIFY(myvec.indexOf("B", 1) == 1); - QVERIFY(myvec.indexOf("B", 2) == 3); - QVERIFY(myvec.indexOf("X") == -1); - QVERIFY(myvec.indexOf("X", 2) == -1); - - // add an X - myvec << "X"; - QVERIFY(myvec.indexOf("X") == 5); - QVERIFY(myvec.indexOf("X", 5) == 5); - QVERIFY(myvec.indexOf("X", 6) == -1); - - // remove first A - myvec.remove(0); - QVERIFY(myvec.indexOf("A") == 3); - QVERIFY(myvec.indexOf("A", 3) == 3); - QVERIFY(myvec.indexOf("A", 4) == -1); -} - -template <typename T> -void tst_QVector::insert() const -{ - QVector<T> myvec; - const T - tA = SimpleValue<T>::at(0), - tB = SimpleValue<T>::at(1), - tC = SimpleValue<T>::at(2), - tX = SimpleValue<T>::at(3), - tZ = SimpleValue<T>::at(4), - tT = SimpleValue<T>::at(5), - ti = SimpleValue<T>::at(6); - myvec << tA << tB << tC; - QVector<T> myvec2 = myvec; - - // first position - QCOMPARE(myvec.at(0), tA); - myvec.insert(0, tX); - QCOMPARE(myvec.at(0), tX); - QCOMPARE(myvec.at(1), tA); - - QCOMPARE(myvec2.at(0), tA); - myvec2.insert(myvec2.begin(), tX); - QCOMPARE(myvec2.at(0), tX); - QCOMPARE(myvec2.at(1), tA); - - // middle - myvec.insert(1, tZ); - QCOMPARE(myvec.at(0), tX); - QCOMPARE(myvec.at(1), tZ); - QCOMPARE(myvec.at(2), tA); - - myvec2.insert(myvec2.begin() + 1, tZ); - QCOMPARE(myvec2.at(0), tX); - QCOMPARE(myvec2.at(1), tZ); - QCOMPARE(myvec2.at(2), tA); - - // end - myvec.insert(5, tT); - QCOMPARE(myvec.at(5), tT); - QCOMPARE(myvec.at(4), tC); - - myvec2.insert(myvec2.end(), tT); - QCOMPARE(myvec2.at(5), tT); - QCOMPARE(myvec2.at(4), tC); - - // insert a lot of garbage in the middle - myvec.insert(2, 2, ti); - QCOMPARE(myvec, QVector<T>() << tX << tZ << ti << ti - << tA << tB << tC << tT); - - myvec2.insert(myvec2.begin() + 2, 2, ti); - QCOMPARE(myvec2, myvec); - - // insert from references to the same container: - myvec.insert(0, 1, myvec[5]); // inserts tB - myvec2.insert(0, 1, myvec2[5]); // inserts tB - QCOMPARE(myvec, QVector<T>() << tB << tX << tZ << ti << ti - << tA << tB << tC << tT); - QCOMPARE(myvec2, myvec); - - myvec.insert(0, 1, const_cast<const QVector<T>&>(myvec)[0]); // inserts tB - myvec2.insert(0, 1, const_cast<const QVector<T>&>(myvec2)[0]); // inserts tB - QCOMPARE(myvec, QVector<T>() << tB << tB << tX << tZ << ti << ti - << tA << tB << tC << tT); - QCOMPARE(myvec2, myvec); -} - -void tst_QVector::insertInt() const -{ - insert<int>(); -} - -void tst_QVector::insertMovable() const -{ - insert<Movable>(); -} - -void tst_QVector::insertCustom() const -{ - insert<Custom>(); -} - -void tst_QVector::isEmpty() const -{ - QVector<QString> myvec; - - // starts ok - QVERIFY(myvec.isEmpty()); - - // not empty now - myvec.append(QLatin1String("hello there")); - QVERIFY(!myvec.isEmpty()); - - // empty again - myvec.remove(0); - QVERIFY(myvec.isEmpty()); -} - -void tst_QVector::last() const -{ - QVector<QString> myvec; - myvec << "A" << "B" << "C"; - - // test starts ok - QCOMPARE(myvec.last(), QLatin1String("C")); - QCOMPARE(myvec.constLast(), QLatin1String("C")); - - // test it changes ok - myvec.append(QLatin1String("X")); - QCOMPARE(myvec.last(), QLatin1String("X")); - QCOMPARE(myvec.constLast(), QLatin1String("X")); - - // and remove again - myvec.remove(3); - QCOMPARE(myvec.last(), QLatin1String("C")); - QCOMPARE(myvec.constLast(), QLatin1String("C")); -} - -void tst_QVector::constLast() const -{ - QVector<int> myvec; - myvec << 69 << 42 << 3; - - // test it starts ok - QCOMPARE(myvec.constLast(), 3); - QVERIFY(myvec.isDetached()); - - QVector<int> myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constLast(), 3); - QCOMPARE(myvecCopy.constLast(), 3); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test removal changes - myvec.removeLast(); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constLast(), 42); - QCOMPARE(myvecCopy.constLast(), 3); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constLast(), 42); - QCOMPARE(myvecCopy.constLast(), 42); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test prepend changes - myvec.append(23); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constLast(), 23); - QCOMPARE(myvecCopy.constLast(), 42); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constLast(), 23); - QCOMPARE(myvecCopy.constLast(), 23); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); -} - -void tst_QVector::lastIndexOf() const -{ - QVector<QString> myvec; - myvec << "A" << "B" << "C" << "B" << "A"; - - QVERIFY(myvec.lastIndexOf("B") == 3); - QVERIFY(myvec.lastIndexOf("B", 2) == 1); - QVERIFY(myvec.lastIndexOf("X") == -1); - QVERIFY(myvec.lastIndexOf("X", 2) == -1); - - // add an X - myvec << "X"; - QVERIFY(myvec.lastIndexOf("X") == 5); - QVERIFY(myvec.lastIndexOf("X", 5) == 5); - QVERIFY(myvec.lastIndexOf("X", 3) == -1); - - // remove first A - myvec.remove(0); - QVERIFY(myvec.lastIndexOf("A") == 3); - QVERIFY(myvec.lastIndexOf("A", 3) == 3); - QVERIFY(myvec.lastIndexOf("A", 2) == -1); -} - -void tst_QVector::mid() const -{ - QVector<QString> list; - list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty"; - - QCOMPARE(list.mid(3, 3), QVector<QString>() << "bak" << "buck" << "hello"); - QCOMPARE(list.mid(6, 10), QVector<QString>() << "kitty"); - QCOMPARE(list.mid(-1, 20), list); - QCOMPARE(list.mid(4), QVector<QString>() << "buck" << "hello" << "kitty"); -} - -template <typename T> -void tst_QVector::qhash() const -{ - QVector<T> l1, l2; - QCOMPARE(qHash(l1), qHash(l2)); - l1 << SimpleValue<T>::at(0); - l2 << SimpleValue<T>::at(0); - QCOMPARE(qHash(l1), qHash(l2)); -} - -template <typename T> -void tst_QVector::move() const -{ - QVector<T> list; - list << T_FOO << T_BAR << T_BAZ; - - // move an item - list.move(0, list.count() - 1); - QCOMPARE(list, QVector<T>() << T_BAR << T_BAZ << T_FOO); - - // move it back - list.move(list.count() - 1, 0); - QCOMPARE(list, QVector<T>() << T_FOO << T_BAR << T_BAZ); - - // move an item in the middle - list.move(1, 0); - QCOMPARE(list, QVector<T>() << T_BAR << T_FOO << T_BAZ); -} - -void tst_QVector::moveInt() const -{ - move<int>(); -} - -void tst_QVector::moveMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - move<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::moveCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - move<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template<typename T> -void tst_QVector::prepend() const -{ - QVector<T> myvec; - T val1 = SimpleValue<T>::at(0); - T val2 = SimpleValue<T>::at(1); - T val3 = SimpleValue<T>::at(2); - T val4 = SimpleValue<T>::at(3); - T val5 = SimpleValue<T>::at(4); - myvec << val1 << val2 << val3; - - // starts ok - QVERIFY(myvec.size() == 3); - QCOMPARE(myvec.at(0), val1); - - // add something - myvec.prepend(val4); - QCOMPARE(myvec.at(0), val4); - QCOMPARE(myvec.at(1), val1); - QVERIFY(myvec.size() == 4); - - // something else - myvec.prepend(val5); - QCOMPARE(myvec.at(0), val5); - QCOMPARE(myvec.at(1), val4); - QCOMPARE(myvec.at(2), val1); - QVERIFY(myvec.size() == 5); - - // clear and prepend to an empty vector - myvec.clear(); - QVERIFY(myvec.size() == 0); - myvec.prepend(val5); - QVERIFY(myvec.size() == 1); - QCOMPARE(myvec.at(0), val5); -} - -void tst_QVector::prependInt() const -{ - prepend<int>(); -} - -void tst_QVector::prependMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - prepend<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::prependCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - prepend<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::removeAllWithAlias() const -{ - QVector<QString> strings; - strings << "One" << "Two" << "Three" << "One" /* must be distinct, but equal */; - QCOMPARE(strings.removeAll(strings.front()), 2); // will trigger asan/ubsan -} - -template<typename T> -void tst_QVector::remove() const -{ - QVector<T> myvec; - T val1 = SimpleValue<T>::at(1); - T val2 = SimpleValue<T>::at(2); - T val3 = SimpleValue<T>::at(3); - T val4 = SimpleValue<T>::at(4); - myvec << val1 << val2 << val3; - myvec << val1 << val2 << val3; - myvec << val1 << val2 << val3; - // remove middle - myvec.remove(1); - QCOMPARE(myvec, QVector<T>() << val1 << val3 << val1 << val2 << val3 << val1 << val2 << val3); - - // removeOne() - QVERIFY(!myvec.removeOne(val4)); - QVERIFY(myvec.removeOne(val2)); - QCOMPARE(myvec, QVector<T>() << val1 << val3 << val1 << val3 << val1 << val2 << val3); - - QVector<T> myvecCopy = myvec; - QVERIFY(myvecCopy.isSharedWith(myvec)); - // removeAll() - QCOMPARE(myvec.removeAll(val4), 0); - QVERIFY(myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec.removeAll(val1), 3); - QVERIFY(!myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec, QVector<T>() << val3 << val3 << val2 << val3); - myvecCopy = myvec; - QVERIFY(myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec.removeAll(val2), 1); - QVERIFY(!myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec, QVector<T>() << val3 << val3 << val3); - - // remove rest - myvec.remove(0, 3); - QCOMPARE(myvec, QVector<T>()); -} - -void tst_QVector::removeInt() const -{ - remove<int>(); -} - -void tst_QVector::removeMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - remove<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::removeCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - remove<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -struct RemoveLastTestClass -{ - RemoveLastTestClass() { other = 0; deleted = false; } - RemoveLastTestClass *other; - bool deleted; - ~RemoveLastTestClass() - { - deleted = true; - if (other) - other->other = 0; - } -}; - -void tst_QVector::removeFirstLast() const -{ - // pop_pack - pop_front - QVector<int> t, t2; - t.append(1); - t.append(2); - t.append(3); - t.append(4); - t2 = t; - t.pop_front(); - QCOMPARE(t.size(), 3); - QCOMPARE(t.at(0), 2); - t.pop_back(); - QCOMPARE(t.size(), 2); - QCOMPARE(t.at(0), 2); - QCOMPARE(t.at(1), 3); - - // takefirst - takeLast - int n1 = t2.takeLast(); - QCOMPARE(t2.size(), 3); - QCOMPARE(n1, 4); - QCOMPARE(t2.at(0), 1); - QCOMPARE(t2.at(2), 3); - n1 = t2.takeFirst(); - QCOMPARE(t2.size(), 2); - QCOMPARE(n1, 1); - QCOMPARE(t2.at(0), 2); - QCOMPARE(t2.at(1), 3); - - // remove first - QVector<int> x, y; - x.append(1); - x.append(2); - y = x; - x.removeFirst(); - QCOMPARE(x.size(), 1); - QCOMPARE(y.size(), 2); - QCOMPARE(x.at(0), 2); - - // remove Last - QVector<RemoveLastTestClass> v; - v.resize(2); - v[0].other = &(v[1]); - v[1].other = &(v[0]); - // Check dtor - complex type - QVERIFY(v.at(0).other != 0); - v.removeLast(); - QVERIFY(v.at(0).other == 0); - QCOMPARE(v.at(0).deleted, false); - // check iterator - int count = 0; - for (QVector<RemoveLastTestClass>::const_iterator i = v.constBegin(); i != v.constEnd(); ++i) { - ++count; - QVERIFY(i->other == 0); - QCOMPARE(i->deleted, false); - } - // Check size - QCOMPARE(count, 1); - QCOMPARE(v.size(), 1); - v.removeLast(); - QCOMPARE(v.size(), 0); - // Check if we do correct realloc - QVector<int> v2, v3; - v2.append(1); - v2.append(2); - v3 = v2; // shared - v2.removeLast(); - QCOMPARE(v2.size(), 1); - QCOMPARE(v3.size(), 2); - QCOMPARE(v2.at(0), 1); - QCOMPARE(v3.at(0), 1); - QCOMPARE(v3.at(1), 2); - - // Remove last with shared - QVector<int> z1, z2; - z1.append(9); - z2 = z1; - z1.removeLast(); - QCOMPARE(z1.size(), 0); - QCOMPARE(z2.size(), 1); - QCOMPARE(z2.at(0), 9); -} - - -void tst_QVector::resizePOD_data() const -{ - QTest::addColumn<QVector<int> >("vector"); - QTest::addColumn<int>("size"); - - QVERIFY(!QTypeInfo<int>::isComplex); - QVERIFY(!QTypeInfo<int>::isStatic); - - QVector<int> null; - QVector<int> empty(0, 5); - QVector<int> emptyReserved; - QVector<int> nonEmpty; - QVector<int> nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << 0 << 1 << 2 << 3 << 4; - nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - QTest::newRow("null") << null << 10; - QTest::newRow("empty") << empty << 10; - QTest::newRow("emptyReserved") << emptyReserved << 10; - QTest::newRow("nonEmpty") << nonEmpty << 10; - QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -} - -void tst_QVector::resizePOD() const -{ - QFETCH(QVector<int>, vector); - QFETCH(int, size); - - const int oldSize = vector.size(); - - vector.resize(size); - QCOMPARE(vector.size(), size); - QVERIFY(vector.capacity() >= size); - for (int i = oldSize; i < size; ++i) - QVERIFY(vector[i] == 0); // check initialization - - const int capacity = vector.capacity(); - - vector.clear(); - QCOMPARE(vector.size(), 0); - QVERIFY(vector.capacity() <= capacity); -} - -void tst_QVector::resizeComplexMovable_data() const -{ - QTest::addColumn<QVector<Movable> >("vector"); - QTest::addColumn<int>("size"); - - QVERIFY(QTypeInfo<Movable>::isComplex); - QVERIFY(!QTypeInfo<Movable>::isStatic); - - QVector<Movable> null; - QVector<Movable> empty(0, 'Q'); - QVector<Movable> emptyReserved; - QVector<Movable> nonEmpty; - QVector<Movable> nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << '0' << '1' << '2' << '3' << '4'; - nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - QTest::newRow("null") << null << 10; - QTest::newRow("empty") << empty << 10; - QTest::newRow("emptyReserved") << emptyReserved << 10; - QTest::newRow("nonEmpty") << nonEmpty << 10; - QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -} - -void tst_QVector::resizeComplexMovable() const -{ - const int items = Movable::counter.loadAcquire(); - { - QFETCH(QVector<Movable>, vector); - QFETCH(int, size); - - const int oldSize = vector.size(); - - vector.resize(size); - QCOMPARE(vector.size(), size); - QVERIFY(vector.capacity() >= size); - for (int i = oldSize; i < size; ++i) - QVERIFY(vector[i] == 'j'); // check initialization - - const int capacity = vector.capacity(); - - vector.resize(0); - QCOMPARE(vector.size(), 0); - QVERIFY(vector.capacity() <= capacity); - } - QCOMPARE(items, Movable::counter.loadAcquire()); -} - -void tst_QVector::resizeComplex_data() const -{ - QTest::addColumn<QVector<Custom> >("vector"); - QTest::addColumn<int>("size"); - - QVERIFY(QTypeInfo<Custom>::isComplex); - QVERIFY(QTypeInfo<Custom>::isStatic); - - QVector<Custom> null; - QVector<Custom> empty(0, '0'); - QVector<Custom> emptyReserved; - QVector<Custom> nonEmpty; - QVector<Custom> nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << '0' << '1' << '2' << '3' << '4'; - nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - QTest::newRow("null") << null << 10; - QTest::newRow("empty") << empty << 10; - QTest::newRow("emptyReserved") << emptyReserved << 10; - QTest::newRow("nonEmpty") << nonEmpty << 10; - QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -} - -void tst_QVector::resizeComplex() const -{ - const int items = Custom::counter.loadAcquire(); - { - QFETCH(QVector<Custom>, vector); - QFETCH(int, size); - - int oldSize = vector.size(); - vector.resize(size); - QCOMPARE(vector.size(), size); - QVERIFY(vector.capacity() >= size); - for (int i = oldSize; i < size; ++i) - QVERIFY(vector[i].i == 'j'); // check default initialization - - const int capacity = vector.capacity(); - - vector.resize(0); - QCOMPARE(vector.size(), 0); - QVERIFY(vector.isEmpty()); - QVERIFY(vector.capacity() <= capacity); - } - QCOMPARE(Custom::counter.loadAcquire(), items); -} - -void tst_QVector::resizeCtorAndDtor() const -{ - const int items = Custom::counter.loadAcquire(); - { - QVector<Custom> null; - QVector<Custom> empty(0, '0'); - QVector<Custom> emptyReserved; - QVector<Custom> nonEmpty; - QVector<Custom> nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << '0' << '1' << '2' << '3' << '4'; - nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - // start playing with vectors - null.resize(21); - nonEmpty.resize(2); - emptyReserved.resize(0); - nonEmpty.resize(0); - nonEmptyReserved.resize(2); - } - QCOMPARE(Custom::counter.loadAcquire(), items); -} - -void tst_QVector::reverseIterators() const -{ - QVector<int> v; - v << 1 << 2 << 3 << 4; - QVector<int> vr = v; - std::reverse(vr.begin(), vr.end()); - const QVector<int> &cvr = vr; - QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin())); - QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin())); - QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin())); - QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin())); - QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin())); - QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin())); -} - -template<typename T> -void tst_QVector::size() const -{ - // zero size - QVector<T> myvec; - QVERIFY(myvec.size() == 0); - - // grow - myvec.append(SimpleValue<T>::at(0)); - QVERIFY(myvec.size() == 1); - myvec.append(SimpleValue<T>::at(1)); - QVERIFY(myvec.size() == 2); - - // shrink - myvec.remove(0); - QVERIFY(myvec.size() == 1); - myvec.remove(0); - QVERIFY(myvec.size() == 0); -} - -void tst_QVector::sizeInt() const -{ - size<int>(); -} - -void tst_QVector::sizeMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - size<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::sizeCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - size<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -// ::squeeze() is tested in ::capacity(). - -void tst_QVector::startsWith() const -{ - QVector<int> myvec; - - // empty vector - QVERIFY(!myvec.startsWith(1)); - - // add the one, should work - myvec.prepend(1); - QVERIFY(myvec.startsWith(1)); - - // add something else, fails now - myvec.prepend(3); - QVERIFY(!myvec.startsWith(1)); - - // remove it again :) - myvec.remove(0); - QVERIFY(myvec.startsWith(1)); -} - -template<typename T> -void tst_QVector::swap() const -{ - QVector<T> v1, v2; - T val1 = SimpleValue<T>::at(0); - T val2 = SimpleValue<T>::at(1); - T val3 = SimpleValue<T>::at(2); - T val4 = SimpleValue<T>::at(3); - T val5 = SimpleValue<T>::at(4); - T val6 = SimpleValue<T>::at(5); - v1 << val1 << val2 << val3; - v2 << val4 << val5 << val6; - - v1.swap(v2); - QCOMPARE(v1,QVector<T>() << val4 << val5 << val6); - QCOMPARE(v2,QVector<T>() << val1 << val2 << val3); -} - -void tst_QVector::swapInt() const -{ - swap<int>(); -} - -void tst_QVector::swapMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - swap<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::swapCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - swap<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::toList() const -{ - QVector<QString> myvec; - myvec << "A" << "B" << "C"; - - // make sure it converts and doesn't modify the original vector - QCOMPARE(myvec.toList(), QList<QString>() << "A" << "B" << "C"); - QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C"); -} - -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -void tst_QVector::toStdVector() const -{ - QVector<QString> myvec; - myvec << "A" << "B" << "C"; - - std::vector<QString> svec = myvec.toStdVector(); - QCOMPARE(svec.at(0), QLatin1String("A")); - QCOMPARE(svec.at(1), QLatin1String("B")); - QCOMPARE(svec.at(2), QLatin1String("C")); - - QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C"); -} -#endif - -void tst_QVector::value() const -{ - QVector<QString> myvec; - myvec << "A" << "B" << "C"; - - // valid calls - QCOMPARE(myvec.value(0), QLatin1String("A")); - QCOMPARE(myvec.value(1), QLatin1String("B")); - QCOMPARE(myvec.value(2), QLatin1String("C")); - - // default calls - QCOMPARE(myvec.value(-1), QString()); - QCOMPARE(myvec.value(3), QString()); - - // test calls with a provided default, valid calls - QCOMPARE(myvec.value(0, QLatin1String("default")), QLatin1String("A")); - QCOMPARE(myvec.value(1, QLatin1String("default")), QLatin1String("B")); - QCOMPARE(myvec.value(2, QLatin1String("default")), QLatin1String("C")); - - // test calls with a provided default that will return the default - QCOMPARE(myvec.value(-1, QLatin1String("default")), QLatin1String("default")); - QCOMPARE(myvec.value(3, QLatin1String("default")), QLatin1String("default")); -} - -void tst_QVector::testOperators() const -{ - QVector<QString> myvec; - myvec << "A" << "B" << "C"; - QVector<QString> myvectwo; - myvectwo << "D" << "E" << "F"; - QVector<QString> combined; - combined << "A" << "B" << "C" << "D" << "E" << "F"; - - // != - QVERIFY(myvec != myvectwo); - - // + - QCOMPARE(myvec + myvectwo, combined); - QCOMPARE(myvec, QVector<QString>() << "A" << "B" << "C"); - QCOMPARE(myvectwo, QVector<QString>() << "D" << "E" << "F"); - - // += - myvec += myvectwo; - QCOMPARE(myvec, combined); - - // == - QVERIFY(myvec == combined); - - // <, >, <=, >= - QVERIFY(!(myvec < combined)); - QVERIFY(!(myvec > combined)); - QVERIFY( myvec <= combined); - QVERIFY( myvec >= combined); - combined.push_back("G"); - QVERIFY( myvec < combined); - QVERIFY(!(myvec > combined)); - QVERIFY( myvec <= combined); - QVERIFY(!(myvec >= combined)); - QVERIFY(combined > myvec); - QVERIFY(combined >= myvec); - - // [] - QCOMPARE(myvec[0], QLatin1String("A")); - QCOMPARE(myvec[1], QLatin1String("B")); - QCOMPARE(myvec[2], QLatin1String("C")); - QCOMPARE(myvec[3], QLatin1String("D")); - QCOMPARE(myvec[4], QLatin1String("E")); - QCOMPARE(myvec[5], QLatin1String("F")); -} - - -int fooCtor; -int fooDtor; - -struct Foo -{ - int *p; - - Foo() { p = new int; ++fooCtor; } - Foo(const Foo &other) { Q_UNUSED(other); p = new int; ++fooCtor; } - - void operator=(const Foo & /* other */) { } - - ~Foo() { delete p; ++fooDtor; } -}; - -void tst_QVector::reserve() -{ - fooCtor = 0; - fooDtor = 0; - { - QVector<Foo> a; - a.resize(2); - QCOMPARE(fooCtor, 2); - QVector<Foo> b(a); - b.reserve(1); - QCOMPARE(b.size(), a.size()); - QCOMPARE(fooDtor, 0); - } - QCOMPARE(fooCtor, fooDtor); -} - -// This is a regression test for QTBUG-51758 -void tst_QVector::reserveZero() -{ - QVector<int> vec; - vec.detach(); - vec.reserve(0); // should not crash - QCOMPARE(vec.size(), 0); - QCOMPARE(vec.capacity(), 0); - vec.squeeze(); - QCOMPARE(vec.size(), 0); - QCOMPARE(vec.capacity(), 0); - vec.reserve(-1); - QCOMPARE(vec.size(), 0); - QCOMPARE(vec.capacity(), 0); - vec.append(42); - QCOMPARE(vec.size(), 1); - QVERIFY(vec.capacity() >= 1); -} - -template<typename T> -void tst_QVector::initializeList() -{ - T val1(SimpleValue<T>::at(1)); - T val2(SimpleValue<T>::at(2)); - T val3(SimpleValue<T>::at(3)); - T val4(SimpleValue<T>::at(4)); - - QVector<T> v1 {val1, val2, val3}; - QCOMPARE(v1, QVector<T>() << val1 << val2 << val3); - QCOMPARE(v1, (QVector<T> {val1, val2, val3})); - - QVector<QVector<T>> v2{ v1, {val4}, QVector<T>(), {val1, val2, val3} }; - QVector<QVector<T>> v3; - v3 << v1 << (QVector<T>() << val4) << QVector<T>() << v1; - QCOMPARE(v3, v2); - - QVector<T> v4({}); - QCOMPARE(v4.size(), 0); -} - -void tst_QVector::initializeListInt() -{ - initializeList<int>(); -} - -void tst_QVector::initializeListMovable() -{ - const int instancesCount = Movable::counter.loadAcquire(); - initializeList<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::initializeListCustom() -{ - const int instancesCount = Custom::counter.loadAcquire(); - initializeList<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::const_shared_null() -{ - QVector<int> v2; - QVERIFY(!v2.isDetached()); -} - -template<typename T> -void tst_QVector::detach() const -{ - { - // detach an empty vector - QVector<T> v; - v.detach(); - QVERIFY(!v.isDetached()); - QCOMPARE(v.size(), 0); - QCOMPARE(v.capacity(), 0); - } - { - // detach an empty referenced vector - QVector<T> v; - QVector<T> ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(!v.isDetached()); - QCOMPARE(v.size(), 0); - QCOMPARE(v.capacity(), 0); - } - { - // detach a not empty referenced vector - QVector<T> v(31); - QVector<T> ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 31); - QCOMPARE(v.capacity(), 31); - } - { - // detach a not empty vector - QVector<T> v(31); - QVERIFY(v.isDetached()); - v.detach(); // detaching a detached vector - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 31); - QCOMPARE(v.capacity(), 31); - } - { - // detach a not empty vector with preallocated space - QVector<T> v(3); - v.reserve(8); - QVector<T> ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 3); - QCOMPARE(v.capacity(), 8); - } - { - // detach a not empty vector with preallocated space - QVector<T> v(3); - v.reserve(8); - QVERIFY(v.isDetached()); - v.detach(); // detaching a detached vector - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 3); - QCOMPARE(v.capacity(), 8); - } - { - // detach a not empty, initialized vector - QVector<T> v(7, SimpleValue<T>::at(1)); - QVector<T> ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 7); - for (int i = 0; i < v.size(); ++i) - QCOMPARE(v[i], SimpleValue<T>::at(1)); - } - { - // detach a not empty, initialized vector - QVector<T> v(7, SimpleValue<T>::at(2)); - QVERIFY(v.isDetached()); - v.detach(); // detaching a detached vector - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 7); - for (int i = 0; i < v.size(); ++i) - QCOMPARE(v[i], SimpleValue<T>::at(2)); - } - { - // detach a not empty, initialized vector with preallocated space - QVector<T> v(7, SimpleValue<T>::at(3)); - v.reserve(31); - QVector<T> ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 7); - QCOMPARE(v.capacity(), 31); - for (int i = 0; i < v.size(); ++i) - QCOMPARE(v[i], SimpleValue<T>::at(3)); - } -} - -void tst_QVector::detachInt() const -{ - detach<int>(); -} - -void tst_QVector::detachMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - detach<Movable>(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::detachCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - detach<Custom>(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -static QAtomicPointer<QVector<int> > detachThreadSafetyDataInt; -static QAtomicPointer<QVector<Movable> > detachThreadSafetyDataMovable; -static QAtomicPointer<QVector<Custom> > detachThreadSafetyDataCustom; - -template<typename T> QAtomicPointer<QVector<T> > *detachThreadSafetyData(); -template<> QAtomicPointer<QVector<int> > *detachThreadSafetyData() { return &detachThreadSafetyDataInt; } -template<> QAtomicPointer<QVector<Movable> > *detachThreadSafetyData() { return &detachThreadSafetyDataMovable; } -template<> QAtomicPointer<QVector<Custom> > *detachThreadSafetyData() { return &detachThreadSafetyDataCustom; } - -static QSemaphore detachThreadSafetyLock; - -template<typename T> -void tst_QVector::detachThreadSafety() const -{ - delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(new QVector<T>(SimpleValue<T>::vector(400))); - - static const uint threadsCount = 5; - - struct : QThread { - void run() override - { - QVector<T> copy(*detachThreadSafetyData<T>()->loadRelaxed()); - QVERIFY(!copy.isDetached()); - detachThreadSafetyLock.release(); - detachThreadSafetyLock.acquire(100); - copy.detach(); - } - } threads[threadsCount]; - - for (uint i = 0; i < threadsCount; ++i) - threads[i].start(); - QThread::yieldCurrentThread(); - detachThreadSafetyLock.acquire(threadsCount); - - // destroy static original data - delete detachThreadSafetyData<T>()->fetchAndStoreOrdered(0); - - QVERIFY(threadsCount < 100); - detachThreadSafetyLock.release(threadsCount * 100); - QThread::yieldCurrentThread(); - - for (uint i = 0; i < threadsCount; ++i) - threads[i].wait(); -} - -void tst_QVector::detachThreadSafetyInt() const -{ - for (uint i = 0; i < 128; ++i) - detachThreadSafety<int>(); -} - -void tst_QVector::detachThreadSafetyMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - for (uint i = 0; i < 128; ++i) { - detachThreadSafety<Movable>(); - QCOMPARE(Movable::counter.loadAcquire(), instancesCount); - } -} - -void tst_QVector::detachThreadSafetyCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - for (uint i = 0; i < 128; ++i) { - detachThreadSafety<Custom>(); - QCOMPARE(Custom::counter.loadAcquire(), instancesCount); - } -} - -void tst_QVector::insertMove() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - { - QVector<Movable> vec; - vec.reserve(7); - Movable m0; - Movable m1; - Movable m2; - Movable m3; - Movable m4; - Movable m5; - Movable m6; - - vec.append(std::move(m3)); - QVERIFY(m3.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m3)); - vec.push_back(std::move(m4)); - QVERIFY(m4.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m3)); - QVERIFY(vec.at(1).wasConstructedAt(&m4)); - vec.prepend(std::move(m1)); - QVERIFY(m1.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m3)); - QVERIFY(vec.at(2).wasConstructedAt(&m4)); - vec.insert(1, std::move(m2)); - QVERIFY(m2.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m2)); - QVERIFY(vec.at(2).wasConstructedAt(&m3)); - QVERIFY(vec.at(3).wasConstructedAt(&m4)); - vec += std::move(m5); - QVERIFY(m5.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m2)); - QVERIFY(vec.at(2).wasConstructedAt(&m3)); - QVERIFY(vec.at(3).wasConstructedAt(&m4)); - QVERIFY(vec.at(4).wasConstructedAt(&m5)); - vec << std::move(m6); - QVERIFY(m6.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m2)); - QVERIFY(vec.at(2).wasConstructedAt(&m3)); - QVERIFY(vec.at(3).wasConstructedAt(&m4)); - QVERIFY(vec.at(4).wasConstructedAt(&m5)); - QVERIFY(vec.at(5).wasConstructedAt(&m6)); - vec.push_front(std::move(m0)); - QVERIFY(m0.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m0)); - QVERIFY(vec.at(1).wasConstructedAt(&m1)); - QVERIFY(vec.at(2).wasConstructedAt(&m2)); - QVERIFY(vec.at(3).wasConstructedAt(&m3)); - QVERIFY(vec.at(4).wasConstructedAt(&m4)); - QVERIFY(vec.at(5).wasConstructedAt(&m5)); - QVERIFY(vec.at(6).wasConstructedAt(&m6)); - - QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14); - } - QCOMPARE(Movable::counter.loadAcquire(), instancesCount); -} - -void tst_QVector::swapItemsAt() const -{ - QVector<int> v; - v << 0 << 1 << 2 << 3; - - v.swapItemsAt(0, 2); - QCOMPARE(v.at(0), 2); - QCOMPARE(v.at(2), 0); - - auto copy = v; - copy.swapItemsAt(0, 2); - QCOMPARE(v.at(0), 2); - QCOMPARE(v.at(2), 0); - QCOMPARE(copy.at(0), 0); - QCOMPARE(copy.at(2), 2); -} - -void tst_QVector::emplaceInt() -{ - emplaceImpl<int>(); -} - -void tst_QVector::emplaceCustom() -{ - emplaceImpl<Custom>(); -} - -void tst_QVector::emplaceMovable() -{ - emplaceImpl<Movable>(); -} - -void tst_QVector::emplaceConsistentWithStdVectorInt() -{ - emplaceConsistentWithStdVectorImpl<int>(); -} - -void tst_QVector::emplaceConsistentWithStdVectorCustom() -{ - emplaceConsistentWithStdVectorImpl<Custom>(); -} - -void tst_QVector::emplaceConsistentWithStdVectorMovable() -{ - emplaceConsistentWithStdVectorImpl<Movable>(); -} - -void tst_QVector::emplaceReturnsIterator() -{ - QVector<Movable> vec; - - vec.emplace(0, 'k')->i = 'p'; - - QCOMPARE(vec[0].i, 'p'); -} - -void tst_QVector::emplaceBack() -{ - QScopedValueRollback<QAtomicInt> rollback(Movable::counter, 0); - - QVector<Movable> vec; - - vec.emplaceBack('k'); - - QCOMPARE(Movable::counter, 1); -} - -void tst_QVector::emplaceBackReturnsRef() -{ - QVector<Movable> vec; - - vec.emplaceBack('k').i = 'p'; - - QCOMPARE(vec.at(0).i, 'p'); -} - -void tst_QVector::emplaceWithElementFromTheSameContainer() -{ - QFETCH(int, elementPos); - QFETCH(int, insertPos); - QFETCH(bool, doCopy); - - QVector<QString> vec {"a", "b", "c", "d", "e"}; - const QString e = vec[elementPos]; - - if (doCopy) - vec.emplace(insertPos, vec[elementPos]); - else - vec.emplace(insertPos, std::move(vec[elementPos])); - - QCOMPARE(vec[insertPos], e); -} - -void tst_QVector::emplaceWithElementFromTheSameContainer_data() -{ - QTest::addColumn<int>("elementPos"); - QTest::addColumn<int>("insertPos"); - QTest::addColumn<bool>("doCopy"); - - for (int i = 0; i < 2; ++i) { - const bool doCopy = i == 0; - const char *opName = doCopy ? "copy" : "move"; - - QTest::addRow("%s: begin -> end" , opName) << 0 << 5 << doCopy; - QTest::addRow("%s: begin -> middle", opName) << 0 << 2 << doCopy; - QTest::addRow("%s: middle -> begin" , opName) << 2 << 0 << doCopy; - QTest::addRow("%s: middle -> end" , opName) << 2 << 5 << doCopy; - QTest::addRow("%s: end -> middle", opName) << 4 << 2 << doCopy; - QTest::addRow("%s: end -> begin" , opName) << 4 << 0 << doCopy; - } -} - -template<typename T> -void tst_QVector::emplaceImpl() const -{ - QVector<T> vec {'a', 'b', 'c', 'd'}; - - vec.emplace(2, 'k'); - - QCOMPARE(vec[2], T('k')); -} - -template <class T> -static void vecEq(const QVector<T> &qVec, const std::vector<T> &stdVec) -{ - QCOMPARE(std::size_t(qVec.size()), stdVec.size()); - QVERIFY(std::equal(qVec.begin(), qVec.end(), stdVec.begin(), stdVec.end())); -} - -template <class T> -static void squeezeVec(QVector<T> &qVec, std::vector<T> &stdVec) -{ - qVec.squeeze(); - stdVec.shrink_to_fit(); -} - -template<typename T> -void tst_QVector::emplaceConsistentWithStdVectorImpl() const -{ - QVector<T> qVec {'a', 'b', 'c', 'd', 'e'}; - std::vector<T> stdVec {'a', 'b', 'c', 'd', 'e'}; - vecEq(qVec, stdVec); - - qVec.emplaceBack('f'); - stdVec.emplace_back('f'); - vecEq(qVec, stdVec); - - qVec.emplace(3, 'g'); - stdVec.emplace(stdVec.begin() + 3, 'g'); - vecEq(qVec, stdVec); - - T t; - // while QVector is safe with regards to emplacing elements moved form itself, it's UB - // for std::vector, so do the moving in two steps there. - qVec.emplaceBack(std::move(qVec[0])); - stdVec.emplace_back(std::move(t = std::move(stdVec[0]))); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplaceBack(std::move(qVec[1])); - stdVec.emplace_back(std::move(t = std::move(stdVec[1]))); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplace(3, std::move(qVec[5])); - stdVec.emplace(stdVec.begin() + 3, std::move(t = std::move(stdVec[5]))); - - vecEq(qVec, stdVec); - - qVec.emplaceBack(qVec[3]); - stdVec.emplace_back((t = stdVec[3])); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplaceBack(qVec[4]); - stdVec.emplace_back((t = stdVec[4])); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplace(5, qVec[7]); - stdVec.emplace(stdVec.begin() + 5, (t = stdVec[7])); - vecEq(qVec, stdVec); -} - -QTEST_MAIN(tst_QVector) -#include "tst_qvector.moc" |