summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp153
-rw-r--r--tests/benchmarks/corelib/tools/qlist/main.cpp100
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"