diff options
author | Jędrzej Nowacki <jedrzej.nowacki@nokia.com> | 2012-04-26 12:06:17 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-05-30 17:07:27 +0200 |
commit | d17cf14185eb84863549e0119c8b7bd20db78580 (patch) | |
tree | 843efdf2b591293fabf8c5a7cf448d9514f35495 /tests | |
parent | 5131aefc1f0c04936e3ef19c9870d884775471e5 (diff) |
Implement QVector with QArrayData interface.
Change-Id: I109f46892aed2f6024459812d24922b12358814d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/tools/qvector/tst_qvector.cpp | 1486 | ||||
-rw-r--r-- | tests/benchmarks/corelib/tools/qvector/outofline.cpp | 33 | ||||
-rw-r--r-- | tests/benchmarks/corelib/tools/qvector/qrawvector.h | 26 | ||||
-rw-r--r-- | tests/benchmarks/corelib/tools/qvector/qvector.pro | 2 |
4 files changed, 1422 insertions, 125 deletions
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 67ca547736..56570b8e53 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -42,24 +42,181 @@ #include <QtTest/QtTest> #include <qvector.h> +struct Movable { + Movable(char input = 'j') + : i(input) + , state(Constructed) + { + ++counter; + } + Movable(const Movable &other) + : i(other.i) + , state(Constructed) + { + check(other.state, Constructed); + ++counter; + } + + ~Movable() + { + check(state, Constructed); + i = 0; + --counter; + 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; + return *this; + } + char i; + static int counter; +private: + enum State { Constructed = 106, Destructed = 110 }; + State state; + + static void check(const State state1, const State state2) + { + QCOMPARE(state1, state2); + } +}; + +int 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; + } + Custom(const Custom &other) + : that(this) + , state(Constructed) + { + check(&other); + ++counter; + this->i = other.i; + } + ~Custom() + { + check(this); + i = 0; + --counter; + state = Destructed; + } + + 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 int 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(c->state, Constructed); + } +}; +int Custom::counter = 0; + +Q_DECLARE_METATYPE(Custom); + +// tests depends on the fact that: +Q_STATIC_ASSERT(!QTypeInfo<int>::isStatic); +Q_STATIC_ASSERT(!QTypeInfo<int>::isComplex); +Q_STATIC_ASSERT(!QTypeInfo<Movable>::isStatic); +Q_STATIC_ASSERT(QTypeInfo<Movable>::isComplex); +Q_STATIC_ASSERT(QTypeInfo<Custom>::isStatic); +Q_STATIC_ASSERT(QTypeInfo<Custom>::isComplex); + + class tst_QVector : public QObject { Q_OBJECT private slots: - void constructors() const; - void append() const; + 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 addInt() const; + void addMovable() const; + void addCustom() const; + void appendInt() const; + void appendMovable() const; + void appendCustom() const; void at() const; - void capacity() const; - void clear() const; + void capacityInt() const; + void capacityMovable() const; + void capacityCustom() const; + void clearInt() const; + void clearMovable() const; + void clearCustom() const; void constData() const; void contains() const; - void count() const; + void countInt() const; + void countMovable() const; + void countCustom() const; void data() const; - void empty() const; + void emptyInt() const; + void emptyMovable() const; + void emptyCustom() const; void endsWith() const; - void fill() const; + void eraseEmptyInt() const; + void eraseEmptyMovable() const; + void eraseEmptyCustom() const; + void eraseEmptyReservedInt() const; + void eraseEmptyReservedMovable() const; + void eraseEmptyReservedCustom() const; + void eraseInt() const; + void eraseMovable() const; + void eraseCustom() const; + void eraseReservedInt() const; + void eraseReservedMovable() const; + void eraseReservedCustom() const; + void fillInt() const; + void fillMovable() const; + void fillCustom() const; void first() const; - void fromList() const; + void fromListInt() const; + void fromListMovable() const; + void fromListCustom() const; void fromStdVector() const; void indexOf() const; void insert() const; @@ -67,11 +224,26 @@ private slots: void last() const; void lastIndexOf() const; void mid() const; - void prepend() const; - void remove() const; - void size() const; + void prependInt() const; + void prependMovable() const; + void prependCustom() const; + void removeInt() const; + void removeMovable() const; + void removeCustom() 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 sizeInt() const; + void sizeMovable() const; + void sizeCustom() const; void startsWith() const; - void swap() const; + void swapInt() const; + void swapMovable() const; + void swapCustom() const; void toList() const; void toStdVector() const; void value() const; @@ -82,44 +254,272 @@ private slots: void reserve(); void reallocAfterCopy_data(); void reallocAfterCopy(); - void initializeList(); + void initializeListInt(); + void initializeListMovable(); + void initializeListCustom(); void const_shared_null(); - void setSharable_data(); - void setSharable(); + void setSharableInt_data(); + void setSharableInt(); + void setSharableMovable_data(); + void setSharableMovable(); + void setSharableCustom_data(); + void setSharableCustom(); + + void detachInt() const; + void detachMovable() const; + void detachCustom() const; +private: + template<typename T> void copyConstructor() const; + template<typename T> void add() const; + template<typename T> void append() 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() const; + template<typename T> void eraseReserved() const; + template<typename T> void fill() const; + template<typename T> void fromList() 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 setSharable_data() const; + template<typename T> void setSharable() const; + template<typename T> void detach() const; }; -void tst_QVector::constructors() const +template<typename T> struct SimpleValue { - // pre-reserve capacity + static T at(int index) { - QVector<int> myvec(5); - - QVERIFY(myvec.capacity() == 5); + return Values[index % MaxIndex]; } + 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 }; + +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<int> myvec(5, 42); + QVector<T> v1; + QVector<T> v2(v1); + QCOMPARE(v1, v2); + } + { + QVector<T> v1; + v1.setSharable(false); + QVector<T> v2(v1); + QVERIFY(!v1.isSharedWith(v2)); + QCOMPARE(v1, v2); + } + { + QVector<T> v1; + v1 << value1 << value2 << value3 << value4; + QVector<T> v2(v1); + QCOMPARE(v1, v2); + } + { + QVector<T> v1; + v1 << value1 << value2 << value3 << value4; + v1.setSharable(false); + QVector<T> v2(v1); + QVERIFY(!v1.isSharedWith(v2)); + QCOMPARE(v1, v2); + } +} - QVERIFY(myvec.capacity() == 5); +void tst_QVector::copyConstructorInt() const +{ + copyConstructor<int>(); +} - // make sure all items are initialised ok - foreach (int meaningoflife, myvec) { - QCOMPARE(meaningoflife, 42); - } +void tst_QVector::copyConstructorMovable() const +{ + const int instancesCount = Movable::counter; + copyConstructor<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::copyConstructorCustom() const +{ + const int instancesCount = Custom::counter; + copyConstructor<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +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; + add<Movable>(); + QCOMPARE(instancesCount, Movable::counter); } +void tst_QVector::addCustom() const +{ + const int instancesCount = Custom::counter; + add<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +template<typename T> void tst_QVector::append() const { - QVector<int> myvec; - myvec.append(42); - myvec.append(43); - myvec.append(44); + { + 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); - QVERIFY(myvec.size() == 3); - QCOMPARE(myvec, QVector<int>() << 42 << 43 << 44); + 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<T> v(2); + v.reserve(12); + v.setSharable(false); + v.append(SimpleValue<T>::at(0)); + QVERIFY(v.size() == 3); + QCOMPARE(v.last(), SimpleValue<T>::at(0)); + } +} + +void tst_QVector::appendInt() const +{ + append<int>(); +} + +void tst_QVector::appendMovable() const +{ + const int instancesCount = Movable::counter; + append<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::appendCustom() const +{ + const int instancesCount = Custom::counter; + append<Custom>(); + QCOMPARE(instancesCount, Custom::counter); } void tst_QVector::at() const @@ -148,20 +548,21 @@ void tst_QVector::at() const QCOMPARE(myvec.at(2), QLatin1String("hello")); } +template<typename T> void tst_QVector::capacity() const { - QVector<QString> myvec; + 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 << "aaa" << "bbb" << "ccc"; + myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); QVERIFY(myvec.capacity() >= 3); // make sure it grows ok - myvec << "aaa" << "bbb" << "ccc"; + myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); QVERIFY(myvec.capacity() >= 6); // let's try squeeze a bit @@ -182,10 +583,30 @@ void tst_QVector::capacity() const QVERIFY(myvec.capacity() == 0); } +void tst_QVector::capacityInt() const +{ + capacity<int>(); +} + +void tst_QVector::capacityMovable() const +{ + const int instancesCount = Movable::counter; + capacity<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::capacityCustom() const +{ + const int instancesCount = Custom::counter; + capacity<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +template<typename T> void tst_QVector::clear() const { - QVector<QString> myvec; - myvec << "aaa" << "bbb" << "ccc"; + QVector<T> myvec; + myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); QVERIFY(myvec.size() == 3); myvec.clear(); @@ -193,6 +614,25 @@ void tst_QVector::clear() const QVERIFY(myvec.capacity() == 0); } +void tst_QVector::clearInt() const +{ + clear<int>(); +} + +void tst_QVector::clearMovable() const +{ + const int instancesCount = Movable::counter; + clear<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::clearCustom() const +{ + const int instancesCount = Custom::counter; + clear<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + void tst_QVector::constData() const { int arr[] = { 42, 43, 44 }; @@ -217,18 +657,19 @@ void tst_QVector::contains() const QVERIFY(myvec.contains(QLatin1String("I don't exist"))); } +template<typename T> void tst_QVector::count() const { // total size { // zero size - QVector<int> myvec; + QVector<T> myvec; QVERIFY(myvec.count() == 0); // grow - myvec.append(42); + myvec.append(SimpleValue<T>::at(0)); QVERIFY(myvec.count() == 1); - myvec.append(42); + myvec.append(SimpleValue<T>::at(1)); QVERIFY(myvec.count() == 2); // shrink @@ -240,23 +681,42 @@ void tst_QVector::count() const // count of items { - QVector<QString> myvec; - myvec << "aaa" << "bbb" << "ccc"; + QVector<T> myvec; + myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2); // initial tests - QVERIFY(myvec.count(QLatin1String("aaa")) == 1); - QVERIFY(myvec.count(QLatin1String("pirates")) == 0); + QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 1); + QVERIFY(myvec.count(SimpleValue<T>::at(3)) == 0); // grow - myvec.append(QLatin1String("aaa")); - QVERIFY(myvec.count(QLatin1String("aaa")) == 2); + myvec.append(SimpleValue<T>::at(0)); + QVERIFY(myvec.count(SimpleValue<T>::at(0)) == 2); // shrink myvec.remove(0); - QVERIFY(myvec.count(QLatin1String("aaa")) == 1); + 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; + count<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::countCustom() const +{ + const int instancesCount = Custom::counter; + count<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + void tst_QVector::data() const { QVector<int> myvec; @@ -275,15 +735,16 @@ void tst_QVector::data() const QVERIFY(memcmp(myvec.data(), reinterpret_cast<int *>(&arr), sizeof(int) * 3) == 0); } +template<typename T> void tst_QVector::empty() const { - QVector<int> myvec; + QVector<T> myvec; // starts empty QVERIFY(myvec.empty()); // not empty - myvec.append(1); + myvec.append(SimpleValue<T>::at(2)); QVERIFY(!myvec.empty()); // empty again @@ -291,6 +752,25 @@ void tst_QVector::empty() const QVERIFY(myvec.empty()); } +void tst_QVector::emptyInt() const +{ + empty<int>(); +} + +void tst_QVector::emptyMovable() const +{ + const int instancesCount = Movable::counter; + empty<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::emptyCustom() const +{ + const int instancesCount = Custom::counter; + empty<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + void tst_QVector::endsWith() const { QVector<int> myvec; @@ -311,18 +791,244 @@ void tst_QVector::endsWith() const QVERIFY(myvec.endsWith(1)); } +template<typename T> +void tst_QVector::eraseEmpty() const +{ + { + QVector<T> v; + v.erase(v.begin()); + QCOMPARE(v.size(), 0); + v.erase(v.begin(), v.end()); + QCOMPARE(v.size(), 0); + } + { + QVector<T> v; + v.setSharable(false); + v.erase(v.begin()); + QCOMPARE(v.size(), 0); + 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; + eraseEmpty<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::eraseEmptyCustom() const +{ + const int instancesCount = Custom::counter; + eraseEmpty<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +template<typename T> +void tst_QVector::eraseEmptyReserved() const +{ + { + QVector<T> v; + v.reserve(10); + v.erase(v.begin()); + QCOMPARE(v.size(), 0); + v.erase(v.begin(), v.end()); + QCOMPARE(v.size(), 0); + } + { + QVector<T> v; + v.reserve(10); + v.setSharable(false); + v.erase(v.begin()); + QCOMPARE(v.size(), 0); + 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; + eraseEmptyReserved<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::eraseEmptyReservedCustom() const +{ + const int instancesCount = Custom::counter; + eraseEmptyReserved<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +template<typename T> +void tst_QVector::erase() const +{ + { + QVector<T> v(12); + v.erase(v.begin()); + QCOMPARE(v.size(), 11); + v.erase(v.begin(), v.end()); + QCOMPARE(v.size(), 0); + } + { + QVector<T> v(12); + 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.erase(v.begin(), v.end() - 1); + QCOMPARE(v.size(), 1); + } + { + QVector<T> v(12); + v.erase(v.begin() + 5); + QCOMPARE(v.size(), 11); + v.erase(v.begin() + 1, v.end() - 1); + QCOMPARE(v.size(), 2); + } + { + QVector<T> v(10); + v.setSharable(false); + v.erase(v.begin() + 3); + QCOMPARE(v.size(), 9); + v.erase(v.begin(), v.end() - 1); + QCOMPARE(v.size(), 1); + } +} + +void tst_QVector::eraseInt() const +{ + erase<int>(); +} + +void tst_QVector::eraseMovable() const +{ + const int instancesCount = Movable::counter; + erase<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::eraseCustom() const +{ + const int instancesCount = Custom::counter; + erase<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +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); + } + { + QVector<T> v(10); + v.reserve(16); + v.setSharable(false); + v.erase(v.begin() + 3); + QCOMPARE(v.size(), 9); + v.erase(v.begin(), v.end() - 1); + QCOMPARE(v.size(), 1); + } +} + +void tst_QVector::eraseReservedInt() const +{ + eraseReserved<int>(); +} + +void tst_QVector::eraseReservedMovable() const +{ + const int instancesCount = Movable::counter; + eraseReserved<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::eraseReservedCustom() const +{ + const int instancesCount = Custom::counter; + eraseReserved<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +template<typename T> void tst_QVector::fill() const { - QVector<int> myvec; + QVector<T> myvec; // resize myvec.resize(5); - myvec.fill(69); - QCOMPARE(myvec, QVector<int>() << 69 << 69 << 69 << 69 << 69); + 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(42, 10); - QCOMPARE(myvec, QVector<int>() << 42 << 42 << 42 << 42 << 42 << 42 << 42 << 42 << 42 << 42); + 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; + fill<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::fillCustom() const +{ + const int instancesCount = Custom::counter; + fill<Custom>(); + QCOMPARE(instancesCount, Custom::counter); } void tst_QVector::first() const @@ -342,17 +1048,37 @@ void tst_QVector::first() const QCOMPARE(myvec.first(), 23); } +template<typename T> void tst_QVector::fromList() const { - QList<QString> list; - list << "aaa" << "bbb" << "ninjas" << "pirates"; + QList<T> list; + list << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3); - QVector<QString> myvec; - myvec = QVector<QString>::fromList(list); + QVector<T> myvec; + myvec = QVector<T>::fromList(list); // test it worked ok - QCOMPARE(myvec, QVector<QString>() << "aaa" << "bbb" << "ninjas" << "pirates"); - QCOMPARE(list, QList<QString>() << "aaa" << "bbb" << "ninjas" << "pirates"); + 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; + fromList<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::fromListCustom() const +{ + const int instancesCount = Custom::counter; + fromList<Custom>(); + QCOMPARE(instancesCount, Custom::counter); } void tst_QVector::fromStdVector() const @@ -486,73 +1212,382 @@ void tst_QVector::mid() const QCOMPARE(list.mid(4), QVector<QString>() << "buck" << "hello" << "kitty"); } +template<typename T> void tst_QVector::prepend() const { - QVector<QString> myvec; - myvec << "A" << "B" << "C"; + 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), QLatin1String("A")); + QCOMPARE(myvec.at(0), val1); // add something - myvec.prepend(QLatin1String("X")); - QCOMPARE(myvec.at(0), QLatin1String("X")); - QCOMPARE(myvec.at(1), QLatin1String("A")); + myvec.prepend(val4); + QCOMPARE(myvec.at(0), val4); + QCOMPARE(myvec.at(1), val1); QVERIFY(myvec.size() == 4); // something else - myvec.prepend(QLatin1String("Z")); - QCOMPARE(myvec.at(0), QLatin1String("Z")); - QCOMPARE(myvec.at(1), QLatin1String("X")); - QCOMPARE(myvec.at(2), QLatin1String("A")); + myvec.prepend(val5); + QCOMPARE(myvec.at(0), val5); + QCOMPARE(myvec.at(1), val4); + QCOMPARE(myvec.at(2), val1); QVERIFY(myvec.size() == 5); - // clear and append to an empty vector + // clear and prepend to an empty vector myvec.clear(); QVERIFY(myvec.size() == 0); - myvec.prepend(QLatin1String("ninjas")); + myvec.prepend(val5); QVERIFY(myvec.size() == 1); - QCOMPARE(myvec.at(0), QLatin1String("ninjas")); + QCOMPARE(myvec.at(0), val5); } -void tst_QVector::remove() const +void tst_QVector::prependInt() const { - QVector<QString> myvec; - myvec << "A" << "B" << "C"; + prepend<int>(); +} + +void tst_QVector::prependMovable() const +{ + const int instancesCount = Movable::counter; + prepend<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::prependCustom() const +{ + const int instancesCount = Custom::counter; + prepend<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} +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); + myvec << val1 << val2 << val3; // remove middle myvec.remove(1); - QCOMPARE(myvec, QVector<QString>() << "A" << "C"); + QCOMPARE(myvec, QVector<T>() << val1 << val3); // remove rest myvec.remove(0, 2); - QCOMPARE(myvec, QVector<QString>()); + QCOMPARE(myvec, QVector<T>()); } -// ::reserve() is really hard to think of tests for, so not doing it. -// ::resize() is tested in ::capacity(). +void tst_QVector::removeInt() const +{ + remove<int>(); +} -void tst_QVector::size() const +void tst_QVector::removeMovable() const { - // total size + const int instancesCount = Movable::counter; + remove<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::removeCustom() const +{ + const int instancesCount = Custom::counter; + remove<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +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); + + QVector<int> nullNotShared; + QVector<int> emptyNotShared(0, 5); + QVector<int> emptyReservedNotShared; + QVector<int> nonEmptyNotShared; + QVector<int> nonEmptyReservedNotShared; + + emptyReservedNotShared.reserve(10); + nonEmptyReservedNotShared.reserve(15); + nonEmptyNotShared << 0 << 1 << 2 << 3 << 4; + nonEmptyReservedNotShared << 0 << 1 << 2 << 3 << 4 << 5 << 6; + QVERIFY(emptyReservedNotShared.capacity() >= 10); + QVERIFY(nonEmptyReservedNotShared.capacity() >= 15); + + emptyNotShared.setSharable(false); + emptyReservedNotShared.setSharable(false); + nonEmptyNotShared.setSharable(false); + nonEmptyReservedNotShared.setSharable(false); + + 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; + QTest::newRow("nullNotShared") << nullNotShared << 10; + QTest::newRow("emptyNotShared") << emptyNotShared << 10; + QTest::newRow("emptyReservedNotShared") << emptyReservedNotShared << 10; + QTest::newRow("nonEmptyNotShared") << nonEmptyNotShared << 10; + QTest::newRow("nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 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.resize(0); + 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); + + QVector<Movable> nullNotShared; + QVector<Movable> emptyNotShared(0, 'Q'); + QVector<Movable> emptyReservedNotShared; + QVector<Movable> nonEmptyNotShared; + QVector<Movable> nonEmptyReservedNotShared; + + emptyReservedNotShared.reserve(10); + nonEmptyReservedNotShared.reserve(15); + nonEmptyNotShared << '0' << '1' << '2' << '3' << '4'; + nonEmptyReservedNotShared << '0' << '1' << '2' << '3' << '4' << '5' << '6'; + QVERIFY(emptyReservedNotShared.capacity() >= 10); + QVERIFY(nonEmptyReservedNotShared.capacity() >= 15); + + emptyNotShared.setSharable(false); + emptyReservedNotShared.setSharable(false); + nonEmptyNotShared.setSharable(false); + nonEmptyReservedNotShared.setSharable(false); + + 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; + QTest::newRow("nullNotShared") << nullNotShared << 10; + QTest::newRow("emptyNotShared") << emptyNotShared << 10; + QTest::newRow("emptyReservedNotShared") << emptyReservedNotShared << 10; + QTest::newRow("nonEmptyNotShared") << nonEmptyNotShared << 10; + QTest::newRow("nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10; +} + +void tst_QVector::resizeComplexMovable() const +{ + const int items = Movable::counter; { - // zero size - QVector<int> myvec; - QVERIFY(myvec.size() == 0); + QFETCH(QVector<Movable>, vector); + QFETCH(int, size); - // grow - myvec.append(42); - QVERIFY(myvec.size() == 1); - myvec.append(42); - QVERIFY(myvec.size() == 2); + const int oldSize = vector.size(); - // shrink - myvec.remove(0); - QVERIFY(myvec.size() == 1); - myvec.remove(0); - QVERIFY(myvec.size() == 0); + 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); +} + +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); + + QVector<Custom> nullNotShared; + QVector<Custom> emptyNotShared(0, '0'); + QVector<Custom> emptyReservedNotShared; + QVector<Custom> nonEmptyNotShared; + QVector<Custom> nonEmptyReservedNotShared; + + emptyReservedNotShared.reserve(10); + nonEmptyReservedNotShared.reserve(15); + nonEmptyNotShared << '0' << '1' << '2' << '3' << '4'; + nonEmptyReservedNotShared << '0' << '1' << '2' << '3' << '4' << '5' << '6'; + QVERIFY(emptyReservedNotShared.capacity() >= 10); + QVERIFY(nonEmptyReservedNotShared.capacity() >= 15); + + emptyNotShared.setSharable(false); + emptyReservedNotShared.setSharable(false); + nonEmptyNotShared.setSharable(false); + nonEmptyReservedNotShared.setSharable(false); + + 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; + QTest::newRow("nullNotShared") << nullNotShared << 10; + QTest::newRow("emptyNotShared") << emptyNotShared << 10; + QTest::newRow("emptyReservedNotShared") << emptyReservedNotShared << 10; + QTest::newRow("nonEmptyNotShared") << nonEmptyNotShared << 10; + QTest::newRow("nonEmptyReservedNotShared") << nonEmptyReservedNotShared << 10; +} + +void tst_QVector::resizeComplex() const +{ + const int items = Custom::counter; + { + 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, items); +} + +void tst_QVector::resizeCtorAndDtor() const +{ + const int items = Custom::counter; + { + 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, items); +} + +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; + size<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::sizeCustom() const +{ + const int instancesCount = Custom::counter; + size<Custom>(); + QCOMPARE(instancesCount, Custom::counter); } // ::squeeze() is tested in ::capacity(). @@ -577,15 +1612,41 @@ void tst_QVector::startsWith() const QVERIFY(myvec.startsWith(1)); } +template<typename T> void tst_QVector::swap() const { - QVector<int> v1, v2; - v1 << 1 << 2 << 3; - v2 << 4 << 5 << 6; + 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<int>() << 4 << 5 << 6); - QCOMPARE(v2,QVector<int>() << 1 << 2 << 3); + 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; + swap<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::swapCustom() const +{ + const int instancesCount = Custom::counter; + swap<Custom>(); + QCOMPARE(instancesCount, Custom::counter); } void tst_QVector::toList() const @@ -923,20 +1984,45 @@ void tst_QVector::reallocAfterCopy() QCOMPARE(v2.size(), result4); } +template<typename T> void tst_QVector::initializeList() { #ifdef Q_COMPILER_INITIALIZER_LISTS - QVector<int> v1{2,3,4}; - QCOMPARE(v1, QVector<int>() << 2 << 3 << 4); - QCOMPARE(v1, (QVector<int>{2,3,4})); - - QVector<QVector<int>> v2{ v1, {1}, QVector<int>(), {2,3,4} }; - QVector<QVector<int>> v3; - v3 << v1 << (QVector<int>() << 1) << QVector<int>() << v1; + 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); #endif } +void tst_QVector::initializeListInt() +{ + initializeList<int>(); +} + +void tst_QVector::initializeListMovable() +{ + const int instancesCount = Movable::counter; + initializeList<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::initializeListCustom() +{ + const int instancesCount = Custom::counter; + initializeList<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + void tst_QVector::const_shared_null() { QVector<int> v1; @@ -950,24 +2036,25 @@ void tst_QVector::const_shared_null() Q_DECLARE_METATYPE(QVector<int>); -void tst_QVector::setSharable_data() +template<typename T> +void tst_QVector::setSharable_data() const { - QTest::addColumn<QVector<int> >("vector"); + QTest::addColumn<QVector<T> >("vector"); QTest::addColumn<int>("size"); QTest::addColumn<int>("capacity"); QTest::addColumn<bool>("isCapacityReserved"); - QVector<int> null; - QVector<int> empty(0, 5); - QVector<int> emptyReserved; - QVector<int> nonEmpty; - QVector<int> nonEmptyReserved; + QVector<T> null; + QVector<T> empty(0, SimpleValue<T>::at(1)); + QVector<T> emptyReserved; + QVector<T> nonEmpty; + QVector<T> nonEmptyReserved; emptyReserved.reserve(10); nonEmptyReserved.reserve(15); - nonEmpty << 0 << 1 << 2 << 3 << 4; - nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6; + nonEmpty << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3) << SimpleValue<T>::at(4); + nonEmptyReserved << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2) << SimpleValue<T>::at(3) << SimpleValue<T>::at(4) << SimpleValue<T>::at(5) << SimpleValue<T>::at(6); QVERIFY(emptyReserved.capacity() >= 10); QVERIFY(nonEmptyReserved.capacity() >= 15); @@ -979,9 +2066,25 @@ void tst_QVector::setSharable_data() QTest::newRow("non-empty, Reserved") << nonEmptyReserved << 7 << 15 << true; } -void tst_QVector::setSharable() +void tst_QVector::setSharableInt_data() { - QFETCH(QVector<int>, vector); + setSharable_data<int>(); +} + +void tst_QVector::setSharableMovable_data() +{ + setSharable_data<Movable>(); +} + +void tst_QVector::setSharableCustom_data() +{ + setSharable_data<Custom>(); +} + +template<typename T> +void tst_QVector::setSharable() const +{ + QFETCH(QVector<T>, vector); QFETCH(int, size); QFETCH(int, capacity); QFETCH(bool, isCapacityReserved); @@ -998,19 +2101,19 @@ void tst_QVector::setSharable() .arg(capacity))); { - QVector<int> copy(vector); + QVector<T> copy(vector); QVERIFY(!copy.isDetached()); QVERIFY(copy.isSharedWith(vector)); } vector.setSharable(false); - QVERIFY(vector.isDetached() || vector.isSharedWith(QVector<int>())); + QVERIFY(vector.isDetached() || vector.isSharedWith(QVector<T>())); { - QVector<int> copy(vector); + QVector<T> copy(vector); - QVERIFY(copy.isDetached() || copy.isSharedWith(QVector<int>())); + QVERIFY(copy.isDetached() || copy.isEmpty() || copy.isSharedWith(QVector<T>())); QCOMPARE(copy.size(), size); if (isCapacityReserved) QVERIFY2(copy.capacity() >= capacity, @@ -1023,14 +2126,14 @@ void tst_QVector::setSharable() vector.setSharable(true); { - QVector<int> copy(vector); + QVector<T> copy(vector); QVERIFY(!copy.isDetached()); QVERIFY(copy.isSharedWith(vector)); } for (int i = 0; i < vector.size(); ++i) - QCOMPARE(vector[i], i); + QCOMPARE(vector[i], SimpleValue<T>::at(i)); QCOMPARE(vector.size(), size); if (isCapacityReserved) @@ -1040,5 +2143,140 @@ void tst_QVector::setSharable() .arg(capacity))); } +void tst_QVector::setSharableInt() +{ + setSharable<int>(); +} + +void tst_QVector::setSharableMovable() +{ + const int instancesCount = Movable::counter; + setSharable<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::setSharableCustom() +{ + const int instancesCount = Custom::counter; + setSharable<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + +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; + detach<Movable>(); + QCOMPARE(instancesCount, Movable::counter); +} + +void tst_QVector::detachCustom() const +{ + const int instancesCount = Custom::counter; + detach<Custom>(); + QCOMPARE(instancesCount, Custom::counter); +} + QTEST_APPLESS_MAIN(tst_QVector) #include "tst_qvector.moc" diff --git a/tests/benchmarks/corelib/tools/qvector/outofline.cpp b/tests/benchmarks/corelib/tools/qvector/outofline.cpp index bf929780a5..138812833f 100644 --- a/tests/benchmarks/corelib/tools/qvector/outofline.cpp +++ b/tests/benchmarks/corelib/tools/qvector/outofline.cpp @@ -79,3 +79,36 @@ std::vector<double> stdvector_fill_and_return_helper() return v; } +const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 }; + +static inline int alignmentThreshold() +{ + // malloc on 32-bit platforms should return pointers that are 8-byte aligned or more + // while on 64-bit platforms they should be 16-byte aligned or more + return 2 * sizeof(void*); +} + +QVectorData *QVectorData::allocate(int size, int alignment) +{ + return static_cast<QVectorData *>(alignment > alignmentThreshold() ? qMallocAligned(size, alignment) : ::malloc(size)); +} + +QVectorData *QVectorData::reallocate(QVectorData *x, int newsize, int oldsize, int alignment) +{ + if (alignment > alignmentThreshold()) + return static_cast<QVectorData *>(qReallocAligned(x, newsize, oldsize, alignment)); + return static_cast<QVectorData *>(realloc(x, newsize)); +} + +void QVectorData::free(QVectorData *x, int alignment) +{ + if (alignment > alignmentThreshold()) + qFreeAligned(x); + else + ::free(x); +} + +int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT) +{ + return qAllocMore(size * sizeOfT, sizeOfHeader) / sizeOfT; +} diff --git a/tests/benchmarks/corelib/tools/qvector/qrawvector.h b/tests/benchmarks/corelib/tools/qvector/qrawvector.h index 18d9847c95..7d80c125ea 100644 --- a/tests/benchmarks/corelib/tools/qvector/qrawvector.h +++ b/tests/benchmarks/corelib/tools/qvector/qrawvector.h @@ -47,6 +47,7 @@ #include <QtCore/qatomic.h> #include <QtCore/qalgorithms.h> #include <QtCore/qlist.h> +#include <QtCore/private/qtools_p.h> #include <iterator> #include <vector> @@ -59,7 +60,32 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +struct QVectorData +{ + QtPrivate::RefCount ref; + int size; + uint alloc : 31; + uint capacityReserved : 1; + + qptrdiff offset; + + void* data() { return reinterpret_cast<char *>(this) + this->offset; } + + static const QVectorData shared_null; + static QVectorData *allocate(int size, int alignment); + static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment); + static void free(QVectorData *data, int alignment); + static int grow(int sizeOfHeader, int size, int sizeOfT); +}; +template <typename T> +struct QVectorTypedData : QVectorData +{ + T* begin() { return reinterpret_cast<T *>(this->data()); } + T* end() { return begin() + this->size; } + + static QVectorTypedData *sharedNull() { return static_cast<QVectorTypedData *>(const_cast<QVectorData *>(&QVectorData::shared_null)); } +}; template <typename T> class QRawVector diff --git a/tests/benchmarks/corelib/tools/qvector/qvector.pro b/tests/benchmarks/corelib/tools/qvector/qvector.pro index e24b16230a..24a65d8ee8 100644 --- a/tests/benchmarks/corelib/tools/qvector/qvector.pro +++ b/tests/benchmarks/corelib/tools/qvector/qvector.pro @@ -1,5 +1,5 @@ TARGET = tst_bench_vector -QT = core testlib +QT = core testlib core-private INCLUDEPATH += . SOURCES += main.cpp outofline.cpp CONFIG += release |