diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp | 153 | ||||
-rw-r--r-- | tests/benchmarks/corelib/tools/qlist/main.cpp | 100 |
2 files changed, 233 insertions, 20 deletions
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index f676307730..bb76caed3e 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -82,6 +82,8 @@ private slots: void freeSpace(); void dataPointerAllocate_data(); void dataPointerAllocate(); + void selfEmplaceBackwards(); + void selfEmplaceForward(); #ifndef QT_NO_EXCEPTIONS void exceptionSafetyPrimitives_constructor(); void exceptionSafetyPrimitives_destructor(); @@ -2128,6 +2130,157 @@ void tst_QArrayData::dataPointerAllocate() } } +struct MyQStringWrapper : public QString +{ + bool movedTo = false; + bool movedFrom = false; + MyQStringWrapper() = default; + MyQStringWrapper(QChar c) : QString(c) { } + MyQStringWrapper(MyQStringWrapper &&other) : QString(std::move(static_cast<QString>(other))) + { + movedTo = true; + movedFrom = other.movedFrom; + other.movedFrom = true; + } + MyQStringWrapper &operator=(MyQStringWrapper &&other) + { + QString::operator=(std::move(static_cast<QString>(other))); + movedTo = true; + movedFrom = other.movedFrom; + other.movedFrom = true; + return *this; + } + MyQStringWrapper(const MyQStringWrapper &) = default; + MyQStringWrapper &operator=(const MyQStringWrapper &) = default; + ~MyQStringWrapper() = default; +}; + +struct MyMovableQString : public MyQStringWrapper +{ + MyMovableQString() = default; + MyMovableQString(QChar c) : MyQStringWrapper(c) { } + +private: + friend bool operator==(const MyMovableQString &a, QChar c) + { + return static_cast<QString>(a) == QString(c); + } + + friend bool operator==(const MyMovableQString &a, const MyMovableQString &b) + { + return static_cast<QString>(a) == static_cast<QString>(b); + } +}; + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(MyMovableQString, Q_RELOCATABLE_TYPE); +QT_END_NAMESPACE +static_assert(QTypeInfo<MyMovableQString>::isComplex); +static_assert(QTypeInfo<MyMovableQString>::isRelocatable); + +struct MyComplexQString : public MyQStringWrapper +{ + MyComplexQString() = default; + MyComplexQString(QChar c) : MyQStringWrapper(c) { } + +private: + friend bool operator==(const MyComplexQString &a, QChar c) + { + return static_cast<QString>(a) == QString(c); + } + + friend bool operator==(const MyComplexQString &a, const MyComplexQString &b) + { + return static_cast<QString>(a) == static_cast<QString>(b); + } +}; +static_assert(QTypeInfo<MyComplexQString>::isComplex); +static_assert(!QTypeInfo<MyComplexQString>::isRelocatable); + +void tst_QArrayData::selfEmplaceBackwards() +{ + const auto createDataPointer = [](qsizetype capacity, int spaceAtEnd, auto dummy) { + using Type = std::decay_t<decltype(dummy)>; + Q_UNUSED(dummy); + auto [header, ptr] = QTypedArrayData<Type>::allocate(capacity, QArrayData::Grow); + // do custom adjustments to make sure there's free space at end + ptr += header->alloc - spaceAtEnd; + return QArrayDataPointer(header, ptr); + }; + + const auto testSelfEmplace = [&](auto dummy, int spaceAtEnd, auto initValues) { + auto adp = createDataPointer(100, spaceAtEnd, dummy); + for (auto v : initValues) { + adp->emplaceBack(v); + } + QVERIFY(!adp.freeSpaceAtEnd()); + QVERIFY(adp.freeSpaceAtBegin()); + + adp->emplace(adp.end(), adp.data()[0]); + for (qsizetype i = 0; i < adp.size - 1; ++i) { + QCOMPARE(adp.data()[i], initValues[i]); + } + QCOMPARE(adp.data()[adp.size - 1], initValues[0]); + + adp->emplace(adp.end(), std::move(adp.data()[0])); + for (qsizetype i = 1; i < adp.size - 2; ++i) { + QCOMPARE(adp.data()[i], initValues[i]); + } + QCOMPARE(adp.data()[adp.size - 2], initValues[0]); + QCOMPARE(adp.data()[0].movedFrom, true); + QCOMPARE(adp.data()[adp.size - 1], initValues[0]); + QCOMPARE(adp.data()[adp.size - 1].movedTo, true); + }; + + QList<QChar> movableObjs { u'a', u'b', u'c', u'd' }; + RUN_TEST_FUNC(testSelfEmplace, MyMovableQString(), 4, movableObjs); + QList<QChar> complexObjs { u'a', u'b', u'c', u'd' }; + RUN_TEST_FUNC(testSelfEmplace, MyComplexQString(), 4, complexObjs); +} + +void tst_QArrayData::selfEmplaceForward() +{ + const auto createDataPointer = [](qsizetype capacity, int spaceAtBegin, auto dummy) { + using Type = std::decay_t<decltype(dummy)>; + Q_UNUSED(dummy); + auto [header, ptr] = QTypedArrayData<Type>::allocate(capacity, QArrayData::Grow); + // do custom adjustments to make sure there's free space at end + ptr += spaceAtBegin; + return QArrayDataPointer(header, ptr); + }; + + const auto testSelfEmplace = [&](auto dummy, int spaceAtBegin, auto initValues) { + auto adp = createDataPointer(100, spaceAtBegin, dummy); + auto reversedInitValues = initValues; + std::reverse(reversedInitValues.begin(), reversedInitValues.end()); + for (auto v : reversedInitValues) { + adp->emplaceFront(v); + } + QVERIFY(!adp.freeSpaceAtBegin()); + QVERIFY(adp.freeSpaceAtEnd()); + + adp->emplace(adp.begin(), adp.data()[adp.size - 1]); + for (qsizetype i = 1; i < adp.size; ++i) { + QCOMPARE(adp.data()[i], initValues[i - 1]); + } + QCOMPARE(adp.data()[0], initValues[spaceAtBegin - 1]); + + adp->emplace(adp.begin(), std::move(adp.data()[adp.size - 1])); + for (qsizetype i = 2; i < adp.size; ++i) { + QCOMPARE(adp.data()[i], initValues[i - 2]); + } + QCOMPARE(adp.data()[1], initValues[spaceAtBegin - 1]); + QCOMPARE(adp.data()[adp.size - 1].movedFrom, true); + QCOMPARE(adp.data()[0], initValues[spaceAtBegin - 1]); + QCOMPARE(adp.data()[0].movedTo, true); + }; + + QList<QChar> movableObjs { u'a', u'b', u'c', u'd' }; + RUN_TEST_FUNC(testSelfEmplace, MyMovableQString(), 4, movableObjs); + QList<QChar> complexObjs { u'a', u'b', u'c', u'd' }; + RUN_TEST_FUNC(testSelfEmplace, MyComplexQString(), 4, complexObjs); +} + #ifndef QT_NO_EXCEPTIONS struct ThrowingTypeWatcher { diff --git a/tests/benchmarks/corelib/tools/qlist/main.cpp b/tests/benchmarks/corelib/tools/qlist/main.cpp index 716a3061ae..223e1603e1 100644 --- a/tests/benchmarks/corelib/tools/qlist/main.cpp +++ b/tests/benchmarks/corelib/tools/qlist/main.cpp @@ -184,11 +184,11 @@ private Q_SLOTS: void appendPrependOne_complex_data() const { commonBenchmark_data<MyComplex>(); } void appendPrependOne_QString_data() const { commonBenchmark_data<QString>(); } - void appendPrependOne_int() const { midInsertOne_impl<QList, int>(); } - void appendPrependOne_primitive() const { midInsertOne_impl<QList, MyPrimitive>(); } - void appendPrependOne_movable() const { midInsertOne_impl<QList, MyMovable>(); } - void appendPrependOne_complex() const { midInsertOne_impl<QList, MyComplex>(); } - void appendPrependOne_QString() const { midInsertOne_impl<QList, QString>(); } + void appendPrependOne_int() const { appendPrependOne_impl<QList, int>(); } + void appendPrependOne_primitive() const { appendPrependOne_impl<QList, MyPrimitive>(); } + void appendPrependOne_movable() const { appendPrependOne_impl<QList, MyMovable>(); } + void appendPrependOne_complex() const { appendPrependOne_impl<QList, MyComplex>(); } + void appendPrependOne_QString() const { appendPrependOne_impl<QList, QString>(); } // prepend half elements, then appen another half: void prependAppendHalvesOne_int_data() const { commonBenchmark_data<int>(); } @@ -197,11 +197,27 @@ private Q_SLOTS: void prependAppendHalvesOne_complex_data() const { commonBenchmark_data<MyComplex>(); } void prependAppendHalvesOne_QString_data() const { commonBenchmark_data<QString>(); } - void prependAppendHalvesOne_int() const { midInsertOne_impl<QList, int>(); } - void prependAppendHalvesOne_primitive() const { midInsertOne_impl<QList, MyPrimitive>(); } - void prependAppendHalvesOne_movable() const { midInsertOne_impl<QList, MyMovable>(); } - void prependAppendHalvesOne_complex() const { midInsertOne_impl<QList, MyComplex>(); } - void prependAppendHalvesOne_QString() const { midInsertOne_impl<QList, QString>(); } + void prependAppendHalvesOne_int() const { prependAppendHalvesOne_impl<QList, int>(); } + void prependAppendHalvesOne_primitive() const + { + prependAppendHalvesOne_impl<QList, MyPrimitive>(); + } + void prependAppendHalvesOne_movable() const { prependAppendHalvesOne_impl<QList, MyMovable>(); } + void prependAppendHalvesOne_complex() const { prependAppendHalvesOne_impl<QList, MyComplex>(); } + void prependAppendHalvesOne_QString() const { prependAppendHalvesOne_impl<QList, QString>(); } + + // emplace in middle 1 element: + void midEmplaceOne_int_data() const { commonBenchmark_data<int>(); } + void midEmplaceOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(); } + void midEmplaceOne_movable_data() const { commonBenchmark_data<MyMovable>(); } + void midEmplaceOne_complex_data() const { commonBenchmark_data<MyComplex>(); } + void midEmplaceOne_QString_data() const { commonBenchmark_data<QString>(); } + + void midEmplaceOne_int() const { midEmplaceOne_impl<QList, int>(); } + void midEmplaceOne_primitive() const { midEmplaceOne_impl<QList, MyPrimitive>(); } + void midEmplaceOne_movable() const { midEmplaceOne_impl<QList, MyMovable>(); } + void midEmplaceOne_complex() const { midEmplaceOne_impl<QList, MyComplex>(); } + void midEmplaceOne_QString() const { midEmplaceOne_impl<QList, QString>(); } // For 5.15 we also want to compare against QVector #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -251,11 +267,14 @@ private Q_SLOTS: void qvector_appendPrependOne_complex_data() const { commonBenchmark_data<MyComplex>(); } void qvector_appendPrependOne_QString_data() const { commonBenchmark_data<QString>(); } - void qvector_appendPrependOne_int() const { midInsertOne_impl<QVector, int>(); } - void qvector_appendPrependOne_primitive() const { midInsertOne_impl<QVector, MyPrimitive>(); } - void qvector_appendPrependOne_movable() const { midInsertOne_impl<QVector, MyMovable>(); } - void qvector_appendPrependOne_complex() const { midInsertOne_impl<QVector, MyComplex>(); } - void qvector_appendPrependOne_QString() const { midInsertOne_impl<QVector, QString>(); } + void qvector_appendPrependOne_int() const { appendPrependOne_impl<QVector, int>(); } + void qvector_appendPrependOne_primitive() const + { + appendPrependOne_impl<QVector, MyPrimitive>(); + } + void qvector_appendPrependOne_movable() const { appendPrependOne_impl<QVector, MyMovable>(); } + void qvector_appendPrependOne_complex() const { appendPrependOne_impl<QVector, MyComplex>(); } + void qvector_appendPrependOne_QString() const { appendPrependOne_impl<QVector, QString>(); } // prepend half elements, then appen another half: void qvector_prependAppendHalvesOne_int_data() const { commonBenchmark_data<int>(); } @@ -267,14 +286,36 @@ private Q_SLOTS: void qvector_prependAppendHalvesOne_complex_data() const { commonBenchmark_data<MyComplex>(); } void qvector_prependAppendHalvesOne_QString_data() const { commonBenchmark_data<QString>(); } - void qvector_prependAppendHalvesOne_int() const { midInsertOne_impl<QVector, int>(); } + void qvector_prependAppendHalvesOne_int() const { prependAppendHalvesOne_impl<QVector, int>(); } void qvector_prependAppendHalvesOne_primitive() const { - midInsertOne_impl<QVector, MyPrimitive>(); + prependAppendHalvesOne_impl<QVector, MyPrimitive>(); + } + void qvector_prependAppendHalvesOne_movable() const + { + prependAppendHalvesOne_impl<QVector, MyMovable>(); + } + void qvector_prependAppendHalvesOne_complex() const + { + prependAppendHalvesOne_impl<QVector, MyComplex>(); + } + void qvector_prependAppendHalvesOne_QString() const + { + prependAppendHalvesOne_impl<QVector, QString>(); } - void qvector_prependAppendHalvesOne_movable() const { midInsertOne_impl<QVector, MyMovable>(); } - void qvector_prependAppendHalvesOne_complex() const { midInsertOne_impl<QVector, MyComplex>(); } - void qvector_prependAppendHalvesOne_QString() const { midInsertOne_impl<QVector, QString>(); } + + // emplace in middle 1 element: + void qvector_midEmplaceOne_int_data() const { commonBenchmark_data<int>(); } + void qvector_midEmplaceOne_primitive_data() const { commonBenchmark_data<MyPrimitive>(); } + void qvector_midEmplaceOne_movable_data() const { commonBenchmark_data<MyMovable>(); } + void qvector_midEmplaceOne_complex_data() const { commonBenchmark_data<MyComplex>(); } + void qvector_midEmplaceOne_QString_data() const { commonBenchmark_data<QString>(); } + + void qvector_midEmplaceOne_int() const { midEmplaceOne_impl<QVector, int>(); } + void qvector_midEmplaceOne_primitive() const { midEmplaceOne_impl<QVector, MyPrimitive>(); } + void qvector_midEmplaceOne_movable() const { midEmplaceOne_impl<QVector, MyMovable>(); } + void qvector_midEmplaceOne_complex() const { midEmplaceOne_impl<QVector, MyComplex>(); } + void qvector_midEmplaceOne_QString() const { midEmplaceOne_impl<QVector, QString>(); } #endif private: @@ -295,6 +336,9 @@ private: template<template<typename> typename, typename> void prependAppendHalvesOne_impl() const; + + template<template<typename> typename, typename> + void midEmplaceOne_impl() const; }; template <class T> @@ -495,6 +539,22 @@ void tst_QList::prependAppendHalvesOne_impl() const } } +template<template<typename> typename Container, typename T> +void tst_QList::midEmplaceOne_impl() const +{ + QFETCH(int, elemCount); + constexpr auto getValue = []() { return T {}; }; + + QBENCHMARK { + Container<T> container; + auto lvalue = getValue(); + + for (int i = 0; i < elemCount; ++i) { + container.emplace(container.size() / 2, lvalue); + } + } +} + QTEST_APPLESS_MAIN(tst_QList) #include "main.moc" |