blob: cc9a3a16d1dd3009f4b9ead7e63c22f441c017c3 [file] [log] [blame]
/****************************************************************************
**
** 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 <QList>
template <typename T, class MemoryLayout>
class is_qlist_array_memory_layout {
struct No { char c; };
struct Yes { No n[2]; };
Q_STATIC_ASSERT(sizeof(No) != sizeof(Yes));
static No check(...);
static Yes check(MemoryLayout);
public:
enum { value = sizeof(check(typename QList<T>::MemoryLayout())) == sizeof(Yes) };
};
struct Movable {
Movable(char input = 'j')
: i(input)
, state(Constructed)
{
++liveCount;
}
Movable(const Movable &other)
: i(other.i)
, state(Constructed)
{
check(other.state, Constructed);
++liveCount;
}
~Movable()
{
check(state, Constructed);
i = 0;
--liveCount;
state = Destructed;
}
bool operator ==(const Movable &other) const
{
check(state, Constructed);
check(other.state, Constructed);
return i == other.i;
}
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 getLiveCount() { return liveCount; }
private:
static int liveCount;
enum State { Constructed = 106, Destructed = 110 };
uchar state;
static void check(const uchar state1, const uchar state2)
{
QCOMPARE(state1, state2);
}
};
Q_STATIC_ASSERT(sizeof(Movable) < sizeof(void*));
int Movable::liveCount = 0;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Movable);
int qHash(const Movable& movable)
{
return qHash(movable.i);
}
struct Optimal
{
Optimal(char input = 'j')
: i(input),
state(Constructed)
{
++liveCount;
}
Optimal(const Optimal &other)
: i(other.i),
state(Constructed)
{
check(other.state, Constructed);
++liveCount;
}
~Optimal()
{
check(state, Constructed);
i = 0;
--liveCount;
state = Destructed;
}
bool operator ==(const Optimal &other) const
{
check(state, Constructed);
check(other.state, Constructed);
return i == other.i;
}
bool operator<(const Optimal &other) const
{
check(state, Constructed);
check(other.state, Constructed);
return i < other.i;
}
Optimal &operator=(const Optimal &other)
{
check(state, Constructed);
check(other.state, Constructed);
i = other.i;
return *this;
}
char i;
static int getLiveCount() { return liveCount; }
private:
static int liveCount;
enum State { Constructed = 106, Destructed = 110 };
uchar state;
char padding[sizeof(void*) - 2];
static void check(const uchar state1, const uchar state2)
{
QCOMPARE(state1, state2);
}
};
Q_STATIC_ASSERT(sizeof(Optimal) == sizeof(void*));
int Optimal::liveCount = 0;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(Optimal, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Optimal);
int qHash(const Optimal& key)
{
return qHash(key.i);
}
struct Complex
{
Complex(int val = 0)
: value(val)
, checkSum(this)
{
++liveCount;
}
Complex(Complex const &other)
: value(other.value)
, checkSum(this)
{
++liveCount;
}
Complex &operator=(Complex const &other)
{
check(); other.check();
value = other.value;
return *this;
}
~Complex()
{
--liveCount;
check();
}
operator int() const { return value; }
bool operator==(Complex const &other) const
{
check(); other.check();
return value == other.value;
}
bool operator<(Complex const &other) const
{
check(); other.check();
return value < other.value;
}
void check() const
{
QVERIFY(this == checkSum);
}
static int getLiveCount() { return liveCount; }
private:
static int liveCount;
int value;
void *checkSum;
};
int Complex::liveCount = 0;
Q_DECLARE_METATYPE(Complex);
// Tests depend 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<Optimal>::isStatic);
Q_STATIC_ASSERT(QTypeInfo<Optimal>::isComplex);
Q_STATIC_ASSERT(QTypeInfo<Complex>::isStatic);
Q_STATIC_ASSERT(QTypeInfo<Complex>::isComplex);
// iow:
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<int, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<int, QListData::IndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::InlineWithPaddingLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::NotArrayCompatibleLayout>::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Optimal, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Optimal, QListData::ArrayCompatibleLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Optimal, QListData::IndirectLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::InlineWithPaddingLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::NotArrayCompatibleLayout>::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Movable, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Movable, QListData::ArrayCompatibleLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Movable, QListData::IndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::InlineWithPaddingLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Complex, QListData::NotArrayCompatibleLayout>::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::NotIndirectLayout> ::value));
Q_STATIC_ASSERT((!is_qlist_array_memory_layout<Complex, QListData::ArrayCompatibleLayout> ::value));
Q_STATIC_ASSERT(( is_qlist_array_memory_layout<Complex, QListData::IndirectLayout> ::value));
class tst_QList : public QObject
{
Q_OBJECT
private slots:
void lengthOptimal() const;
void lengthMovable() const;
void lengthComplex() const;
void lengthSignature() const;
void appendOptimal() const;
void appendMovable() const;
void appendComplex() const;
void prepend() const;
void midOptimal() const;
void midMovable() const;
void midComplex() const;
void atOptimal() const;
void atMovable() const;
void atComplex() const;
void firstOptimal() const;
void firstMovable() const;
void firstComplex() const;
void lastOptimal() const;
void lastMovable() const;
void lastComplex() const;
void constFirst() const;
void constLast() const;
void cpp17ctad() const;
void beginOptimal() const;
void beginMovable() const;
void beginComplex() const;
void endOptimal() const;
void endMovable() const;
void endComplex() const;
void containsOptimal() const;
void containsMovable() const;
void containsComplex() const;
void countOptimal() const;
void countMovable() const;
void countComplex() const;
void emptyOptimal() const;
void emptyMovable() const;
void emptyComplex() const;
void endsWithOptimal() const;
void endsWithMovable() const;
void endsWithComplex() const;
void lastIndexOfOptimal() const;
void lastIndexOfMovable() const;
void lastIndexOfComplex() const;
void moveOptimal() const;
void moveMovable() const;
void moveComplex() const;
void removeAllOptimal() const;
void removeAllMovable() const;
void removeAllComplex() const;
void removeAtOptimal() const;
void removeAtMovable() const;
void removeAtComplex() const;
void removeOneOptimal() const;
void removeOneMovable() const;
void removeOneComplex() const;
void replaceOptimal() const;
void replaceMovable() const;
void replaceComplex() const;
void reverseIteratorsOptimal() const;
void reverseIteratorsMovable() const;
void reverseIteratorsComplex() const;
void startsWithOptimal() const;
void startsWithMovable() const;
void startsWithComplex() const;
void swapOptimal() const;
void swapMovable() const;
void swapComplex() const;
void takeAtOptimal() const;
void takeAtMovable() const;
void takeAtComplex() const;
void takeFirstOptimal() const;
void takeFirstMovable() const;
void takeFirstComplex() const;
void takeLastOptimal() const;
void takeLastMovable() const;
void takeLastComplex() const;
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void toSetOptimal() const;
void toSetMovable() const;
void toSetComplex() const;
void toStdListOptimal() const;
void toStdListMovable() const;
void toStdListComplex() const;
#endif
void toVectorOptimal() const;
void toVectorMovable() const;
void toVectorComplex() const;
void valueOptimal() const;
void valueMovable() const;
void valueComplex() const;
void testOperatorsOptimal() const;
void testOperatorsMovable() const;
void testOperatorsComplex() const;
void testSTLIteratorsOptimal() const;
void testSTLIteratorsMovable() const;
void testSTLIteratorsComplex() const;
void initializeList() const;
void constSharedNullOptimal() const;
void constSharedNullMovable() const;
void constSharedNullComplex() const;
void setSharableInt_data() const;
void setSharableInt() const;
void setSharableComplex_data() const;
void setSharableComplex() const;
void eraseValidIteratorsOnSharedList() const;
void insertWithValidIteratorsOnSharedList() const;
void qhashOptimal() const { qhash<Optimal>(); }
void qhashMovable() const { qhash<Movable>(); }
void qhashComplex() const { qhash<Complex>(); }
void reserve() const;
private:
template<typename T> void length() const;
template<typename T> void append() const;
template<typename T> void mid() const;
template<typename T> void at() const;
template<typename T> void first() const;
template<typename T> void last() const;
template<typename T> void begin() const;
template<typename T> void end() const;
template<typename T> void contains() const;
template<typename T> void count() const;
template<typename T> void empty() const;
template<typename T> void endsWith() const;
template<typename T> void lastIndexOf() const;
template<typename T> void move() const;
template<typename T> void qhash() const;
template<typename T> void removeAll() const;
template<typename T> void removeAt() const;
template<typename T> void removeOne() const;
template<typename T> void replace() const;
template<typename T> void reverseIterators() const;
template<typename T> void startsWith() const;
template<typename T> void swap() const;
template<typename T> void takeAt() const;
template<typename T> void takeFirst() const;
template<typename T> void takeLast() const;
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
template<typename T> void toSet() const;
template<typename T> void toStdList() const;
#endif
template<typename T> void toVector() const;
template<typename T> void value() const;
template<typename T> void testOperators() const;
template<typename T> void testSTLIterators() const;
template<typename T> void constSharedNull() const;
int dummyForGuard;
};
template<typename T> struct SimpleValue
{
static T at(int index)
{
return values[index % maxSize];
}
static const uint maxSize = 7;
static const T values[maxSize];
};
template<>
const Optimal SimpleValue<Optimal>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
template<>
const Movable SimpleValue<Movable>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
template<>
const Complex SimpleValue<Complex>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
// 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)
#define T_WEEE SimpleValue<T>::at(6)
template<typename T>
void tst_QList::length() const
{
/* Empty list. */
{
const QList<T> list;
QCOMPARE(list.length(), 0);
}
/* One entry. */
{
QList<T> list;
list.append(T_FOO);
QCOMPARE(list.length(), 1);
}
/* Two entries. */
{
QList<T> list;
list.append(T_FOO);
list.append(T_BAR);
QCOMPARE(list.length(), 2);
}
/* Three entries. */
{
QList<T> list;
list.append(T_FOO);
list.append(T_BAR);
list.append(T_BAZ);
QCOMPARE(list.length(), 3);
}
}
void tst_QList::lengthOptimal() const
{
const int liveCount = Optimal::getLiveCount();
length<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::lengthMovable() const
{
const int liveCount = Movable::getLiveCount();
length<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::lengthComplex() const
{
const int liveCount = Complex::getLiveCount();
length<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
void tst_QList::lengthSignature() const
{
/* Constness. */
{
const QList<int> list;
/* The function should be const. */
list.length();
}
}
template<typename T>
void tst_QList::append() const
{
/* test append(const QList<T> &) function */
T one(T_FOO);
T two(T_BAR);
T three(T_BAZ);
T four(T_CAT);
QList<T> list1;
QList<T> list2;
QList<T> listTotal;
list1.append(one);
list1.append(two);
list2.append(three);
list2.append(four);
list1.append(list2);
listTotal.append(one);
listTotal.append(two);
listTotal.append(three);
listTotal.append(four);
QCOMPARE(list1, listTotal);
}
void tst_QList::appendOptimal() const
{
const int liveCount = Optimal::getLiveCount();
append<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::appendMovable() const
{
const int liveCount = Movable::getLiveCount();
append<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::appendComplex() const
{
const int liveCount = Complex::getLiveCount();
append<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
void tst_QList::prepend() const
{
QList<int *> list;
int *t1 = new int(0);
list.prepend(t1);
QVERIFY(list.size() == 1);
QVERIFY(list.at(0) == t1);
int *t2 = new int(0);
list.prepend(t2);
QVERIFY(list.size() == 2);
QVERIFY(list.at(0) == t2);
QVERIFY(list.at(1) == t1);
int *t3 = new int(0);
list.prepend(t3);
QVERIFY(list.size() == 3);
QVERIFY(list.at(0) == t3);
QVERIFY(list.at(1) == t2);
QVERIFY(list.at(2) == t1);
list.removeAll(t2);
delete t2;
QVERIFY(list.size() == 2);
QVERIFY(list.at(0) == t3);
QVERIFY(list.at(1) == t1);
int *t4 = new int(0);
list.prepend(t4);
QVERIFY(list.size() == 3);
QVERIFY(list.at(0) == t4);
QVERIFY(list.at(1) == t3);
QVERIFY(list.at(2) == t1);
qDeleteAll(list);
list.clear();
}
template<typename T>
void tst_QList::mid() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ << T_CAT << T_DOG << T_BLAH << T_WEEE;
QCOMPARE(list.mid(3, 3),
QList<T>() << T_CAT << T_DOG << T_BLAH);
QList<T> list1;
QCOMPARE(list1.mid(1, 1).length(), 0);
}
void tst_QList::midOptimal() const
{
const int liveCount = Optimal::getLiveCount();
mid<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::midMovable() const
{
const int liveCount = Movable::getLiveCount();
mid<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::midComplex() const
{
const int liveCount = Complex::getLiveCount();
mid<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::at() const
{
// test at() and make sure it functions correctly with some simple list manipulation.
QList<T> list;
// create a list
list << T_FOO << T_BAR << T_BAZ;
QVERIFY(list.size() == 3);
QCOMPARE(list.at(0), T_FOO);
QCOMPARE(list.at(1), T_BAR);
QCOMPARE(list.at(2), T_BAZ);
// append an item
list << T_CAT;
QVERIFY(list.size() == 4);
QCOMPARE(list.at(0), T_FOO);
QCOMPARE(list.at(1), T_BAR);
QCOMPARE(list.at(2), T_BAZ);
QCOMPARE(list.at(3), T_CAT);
// remove an item
list.removeAt(1);
QVERIFY(list.size() == 3);
QCOMPARE(list.at(0), T_FOO);
QCOMPARE(list.at(1), T_BAZ);
QCOMPARE(list.at(2), T_CAT);
}
void tst_QList::atOptimal() const
{
const int liveCount = Optimal::getLiveCount();
at<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::atMovable() const
{
const int liveCount = Movable::getLiveCount();
at<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::atComplex() const
{
const int liveCount = Complex::getLiveCount();
at<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::first() const
{
QList<T> list;
list << T_FOO << T_BAR;
QCOMPARE(list.first(), T_FOO);
// remove an item, make sure it still works
list.pop_front();
QVERIFY(list.size() == 1);
QCOMPARE(list.first(), T_BAR);
}
void tst_QList::firstOptimal() const
{
const int liveCount = Optimal::getLiveCount();
first<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::firstMovable() const
{
const int liveCount = Movable::getLiveCount();
first<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::firstComplex() const
{
const int liveCount = Complex::getLiveCount();
first<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
void tst_QList::constFirst() const
{
// Based on tst_QVector::constFirst()
QList<int> list;
list << 69 << 42 << 3;
// test it starts ok
QCOMPARE(list.constFirst(), 69);
QVERIFY(list.isDetached());
QList<int> listCopy = list;
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
QCOMPARE(list.constFirst(), 69);
QCOMPARE(listCopy.constFirst(), 69);
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
// test removal changes
list.removeAt(0);
QVERIFY(list.isDetached());
QVERIFY(!list.isSharedWith(listCopy));
QCOMPARE(list.constFirst(), 42);
QCOMPARE(listCopy.constFirst(), 69);
listCopy = list;
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
QCOMPARE(list.constFirst(), 42);
QCOMPARE(listCopy.constFirst(), 42);
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
// test prepend changes
list.prepend(23);
QVERIFY(list.isDetached());
QVERIFY(!list.isSharedWith(listCopy));
QCOMPARE(list.constFirst(), 23);
QCOMPARE(listCopy.constFirst(), 42);
listCopy = list;
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
QCOMPARE(list.constFirst(), 23);
QCOMPARE(listCopy.constFirst(), 23);
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
}
void tst_QList::constLast() const
{
// Based on tst_QVector::constLast()
QList<int> list;
list << 69 << 42 << 3;
// test it starts ok
QCOMPARE(list.constLast(), 3);
QVERIFY(list.isDetached());
QList<int> listCopy = list;
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
QCOMPARE(list.constLast(), 3);
QCOMPARE(listCopy.constLast(), 3);
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
// test removal changes
list.removeLast();
QVERIFY(list.isDetached());
QVERIFY(!list.isSharedWith(listCopy));
QCOMPARE(list.constLast(), 42);
QCOMPARE(listCopy.constLast(), 3);
listCopy = list;
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
QCOMPARE(list.constLast(), 42);
QCOMPARE(listCopy.constLast(), 42);
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
// test prepend changes
list.append(23);
QVERIFY(list.isDetached());
QVERIFY(!list.isSharedWith(listCopy));
QCOMPARE(list.constLast(), 23);
QCOMPARE(listCopy.constLast(), 42);
listCopy = list;
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
QCOMPARE(list.constLast(), 23);
QCOMPARE(listCopy.constLast(), 23);
QVERIFY(!list.isDetached());
QVERIFY(!listCopy.isDetached());
QVERIFY(list.isSharedWith(listCopy));
QVERIFY(listCopy.isSharedWith(list));
}
void tst_QList::cpp17ctad() const
{
#ifdef __cpp_deduction_guides
#define QVERIFY_IS_LIST_OF(obj, Type) \
QVERIFY2((std::is_same<decltype(obj), QList<Type>>::value), \
QMetaType::typeName(qMetaTypeId<decltype(obj)::value_type>()))
#define CHECK(Type, One, Two, Three) \
do { \
const Type v[] = {One, Two, Three}; \
QList v1 = {One, Two, Three}; \
QVERIFY_IS_LIST_OF(v1, Type); \
QList v2(v1.begin(), v1.end()); \
QVERIFY_IS_LIST_OF(v2, Type); \
QList v3(std::begin(v), std::end(v)); \
QVERIFY_IS_LIST_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_LIST_OF
#undef CHECK
#else
QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler.");
#endif
}
template<typename T>
void tst_QList::last() const
{
QList<T> list;
list << T_FOO << T_BAR;
QCOMPARE(list.last(), T_BAR);
// remove an item, make sure it still works
list.pop_back();
QVERIFY(list.size() == 1);
QCOMPARE(list.last(), T_FOO);
}
void tst_QList::lastOptimal() const
{
const int liveCount = Optimal::getLiveCount();
last<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::lastMovable() const
{
const int liveCount = Movable::getLiveCount();
last<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::lastComplex() const
{
const int liveCount = Complex::getLiveCount();
last<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::begin() const
{
QList<T> list;
list << T_FOO << T_BAR;
QCOMPARE(*list.begin(), T_FOO);
// remove an item, make sure it still works
list.pop_front();
QVERIFY(list.size() == 1);
QCOMPARE(*list.begin(), T_BAR);
}
void tst_QList::beginOptimal() const
{
const int liveCount = Optimal::getLiveCount();
begin<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::beginMovable() const
{
const int liveCount = Movable::getLiveCount();
begin<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::beginComplex() const
{
const int liveCount = Complex::getLiveCount();
begin<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::end() const
{
QList<T> list;
list << T_FOO << T_BAR;
QCOMPARE(*--list.end(), T_BAR);
// remove an item, make sure it still works
list.pop_back();
QVERIFY(list.size() == 1);
QCOMPARE(*--list.end(), T_FOO);
}
void tst_QList::endOptimal() const
{
const int liveCount = Optimal::getLiveCount();
end<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::endMovable() const
{
const int liveCount = Movable::getLiveCount();
end<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::endComplex() const
{
const int liveCount = Complex::getLiveCount();
end<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::contains() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
QVERIFY(list.contains(T_FOO));
QVERIFY(list.contains(T_BLAH) != true);
// add it and make sure it matches
list.append(T_BLAH);
QVERIFY(list.contains(T_BLAH));
}
void tst_QList::containsOptimal() const
{
const int liveCount = Optimal::getLiveCount();
contains<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::containsMovable() const
{
const int liveCount = Movable::getLiveCount();
contains<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::containsComplex() const
{
const int liveCount = Complex::getLiveCount();
contains<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::count() const
{
QList<T> list;
// starts empty
QVERIFY(list.count() == 0);
// goes up
list.append(T_FOO);
QVERIFY(list.count() == 1);
// and up
list.append(T_BAR);
QVERIFY(list.count() == 2);
// and down
list.pop_back();
QVERIFY(list.count() == 1);
// and empty. :)
list.pop_back();
QVERIFY(list.count() == 0);
}
void tst_QList::countOptimal() const
{
const int liveCount = Optimal::getLiveCount();
count<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::countMovable() const
{
const int liveCount = Movable::getLiveCount();
count<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::countComplex() const
{
const int liveCount = Complex::getLiveCount();
count<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::empty() const
{
QList<T> list;
// make sure it starts empty
QVERIFY(list.empty());
// and doesn't stay empty
list.append(T_FOO);
QVERIFY(!list.empty());
// and goes back to being empty
list.pop_back();
QVERIFY(list.empty());
}
void tst_QList::emptyOptimal() const
{
const int liveCount = Optimal::getLiveCount();
empty<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::emptyMovable() const
{
const int liveCount = Movable::getLiveCount();
empty<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::emptyComplex() const
{
const int liveCount = Complex::getLiveCount();
empty<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::endsWith() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// test it returns correctly in both cases
QVERIFY(list.endsWith(T_BAZ));
QVERIFY(!list.endsWith(T_BAR));
// remove an item and make sure the end item changes
list.pop_back();
QVERIFY(list.endsWith(T_BAR));
}
void tst_QList::endsWithOptimal() const
{
const int liveCount = Optimal::getLiveCount();
endsWith<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::endsWithMovable() const
{
const int liveCount = Movable::getLiveCount();
endsWith<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::endsWithComplex() const
{
const int liveCount = Complex::getLiveCount();
endsWith<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::lastIndexOf() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// one instance of the target item
QVERIFY(list.lastIndexOf(T_BAZ) == 2);
// shouldn't find this
QVERIFY(list.lastIndexOf(T_WEEE) == -1);
// multiple instances
list.append(T_BAZ);
list.append(T_BAZ);
QVERIFY(list.lastIndexOf(T_BAZ) == 4);
// search from the middle to find the last one
QVERIFY(list.lastIndexOf(T_BAZ, 3) == 3);
// try to find none
QVERIFY(list.lastIndexOf(T_BAZ, 1) == -1);
}
void tst_QList::lastIndexOfOptimal() const
{
const int liveCount = Optimal::getLiveCount();
lastIndexOf<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::lastIndexOfMovable() const
{
const int liveCount = Movable::getLiveCount();
lastIndexOf<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::lastIndexOfComplex() const
{
const int liveCount = Complex::getLiveCount();
lastIndexOf<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::move() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// move an item
list.move(0, list.count() - 1);
QCOMPARE(list, QList<T>() << T_BAR << T_BAZ << T_FOO);
// move it back
list.move(list.count() - 1, 0);
QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
// move an item in the middle
list.move(1, 0);
QCOMPARE(list, QList<T>() << T_BAR << T_FOO << T_BAZ);
}
void tst_QList::moveOptimal() const
{
const int liveCount = Optimal::getLiveCount();
move<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::moveMovable() const
{
const int liveCount = Movable::getLiveCount();
move<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::moveComplex() const
{
const int liveCount = Complex::getLiveCount();
move<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::removeAll() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// remove one instance
list.removeAll(T_BAR);
QCOMPARE(list, QList<T>() << T_FOO << T_BAZ);
// many instances
list << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ << T_FOO << T_BAR << T_BAZ;
list.removeAll(T_BAR);
QCOMPARE(list, QList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ);
// try remove something that doesn't exist
list.removeAll(T_WEEE);
QCOMPARE(list, QList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ);
}
void tst_QList::removeAllOptimal() const
{
const int liveCount = Optimal::getLiveCount();
removeAll<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::removeAllMovable() const
{
const int liveCount = Movable::getLiveCount();
removeAll<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::removeAllComplex() const
{
const int liveCount = Complex::getLiveCount();
removeAll<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::removeAt() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// middle
list.removeAt(1);
QCOMPARE(list, QList<T>() << T_FOO << T_BAZ);
// start
list.removeAt(0);
QCOMPARE(list, QList<T>() << T_BAZ);
// final
list.removeAt(0);
QCOMPARE(list, QList<T>());
}
void tst_QList::removeAtOptimal() const
{
const int liveCount = Optimal::getLiveCount();
removeAt<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::removeAtMovable() const
{
const int liveCount = Movable::getLiveCount();
removeAt<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::removeAtComplex() const
{
const int liveCount = Complex::getLiveCount();
removeAt<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::removeOne() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// middle
list.removeOne(T_BAR);
QCOMPARE(list, QList<T>() << T_FOO << T_BAZ);
// start
list.removeOne(T_FOO);
QCOMPARE(list, QList<T>() << T_BAZ);
// last
list.removeOne(T_BAZ);
QCOMPARE(list, QList<T>());
// make sure it really only removes one :)
list << T_FOO << T_FOO;
list.removeOne(T_FOO);
QCOMPARE(list, QList<T>() << T_FOO);
// try remove something that doesn't exist
list.removeOne(T_WEEE);
QCOMPARE(list, QList<T>() << T_FOO);
}
void tst_QList::removeOneOptimal() const
{
const int liveCount = Optimal::getLiveCount();
removeOne<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::removeOneMovable() const
{
const int liveCount = Movable::getLiveCount();
removeOne<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::removeOneComplex() const
{
const int liveCount = Complex::getLiveCount();
removeOne<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::replace() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// start
list.replace(0, T_CAT);
QCOMPARE(list, QList<T>() << T_CAT
<< T_BAR << T_BAZ);
// middle
list.replace(1, T_DOG);
QCOMPARE(list, QList<T>() << T_CAT
<< T_DOG << T_BAZ);
// end
list.replace(2, T_BLAH);
QCOMPARE(list, QList<T>() << T_CAT
<< T_DOG << T_BLAH);
}
void tst_QList::replaceOptimal() const
{
const int liveCount = Optimal::getLiveCount();
replace<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::replaceMovable() const
{
const int liveCount = Movable::getLiveCount();
replace<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::replaceComplex() const
{
const int liveCount = Complex::getLiveCount();
replace<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::reverseIterators() const
{
QList<T> v;
v << T_CAT << T_DOG << T_BLAH << T_BAZ;
QList<T> vr = v;
std::reverse(vr.begin(), vr.end());
const QList<T> &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()));
}
void tst_QList::reverseIteratorsOptimal() const
{
const int liveCount = Optimal::getLiveCount();
reverseIterators<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::reverseIteratorsMovable() const
{
const int liveCount = Movable::getLiveCount();
reverseIterators<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::reverseIteratorsComplex() const
{
const int liveCount = Complex::getLiveCount();
reverseIterators<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::startsWith() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// make sure it starts ok
QVERIFY(list.startsWith(T_FOO));
// remove an item
list.removeFirst();
QVERIFY(list.startsWith(T_BAR));
}
void tst_QList::startsWithOptimal() const
{
const int liveCount = Optimal::getLiveCount();
startsWith<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::startsWithMovable() const
{
const int liveCount = Movable::getLiveCount();
startsWith<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::startsWithComplex() const
{
const int liveCount = Complex::getLiveCount();
startsWith<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::swap() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// swap
list.swapItemsAt(0, 2);
QCOMPARE(list, QList<T>() << T_BAZ << T_BAR << T_FOO);
// swap again
list.swapItemsAt(1, 2);
QCOMPARE(list, QList<T>() << T_BAZ << T_FOO << T_BAR);
QList<T> list2;
list2 << T_DOG << T_BLAH;
list.swap(list2);
QCOMPARE(list, QList<T>() << T_DOG << T_BLAH);
QCOMPARE(list2, QList<T>() << T_BAZ << T_FOO << T_BAR);
}
void tst_QList::swapOptimal() const
{
const int liveCount = Optimal::getLiveCount();
swap<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::swapMovable() const
{
const int liveCount = Movable::getLiveCount();
swap<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::swapComplex() const
{
const int liveCount = Complex::getLiveCount();
swap<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::takeAt() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
QCOMPARE(list.takeAt(0), T_FOO);
QVERIFY(list.size() == 2);
QCOMPARE(list.takeAt(1), T_BAZ);
QVERIFY(list.size() == 1);
QCOMPARE(list.takeAt(0), T_BAR);
QVERIFY(list.size() == 0);
}
void tst_QList::takeAtOptimal() const
{
const int liveCount = Optimal::getLiveCount();
takeAt<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::takeAtMovable() const
{
const int liveCount = Movable::getLiveCount();
takeAt<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::takeAtComplex() const
{
const int liveCount = Complex::getLiveCount();
takeAt<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::takeFirst() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
QCOMPARE(list.takeFirst(), T_FOO);
QVERIFY(list.size() == 2);
QCOMPARE(list.takeFirst(), T_BAR);
QVERIFY(list.size() == 1);
QCOMPARE(list.takeFirst(), T_BAZ);
QVERIFY(list.size() == 0);
}
void tst_QList::takeFirstOptimal() const
{
const int liveCount = Optimal::getLiveCount();
takeFirst<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::takeFirstMovable() const
{
const int liveCount = Movable::getLiveCount();
takeFirst<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::takeFirstComplex() const
{
const int liveCount = Complex::getLiveCount();
takeFirst<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::takeLast() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
QCOMPARE(list.takeLast(), T_BAZ);
QCOMPARE(list.takeLast(), T_BAR);
QCOMPARE(list.takeLast(), T_FOO);
}
void tst_QList::takeLastOptimal() const
{
const int liveCount = Optimal::getLiveCount();
takeLast<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::takeLastMovable() const
{
const int liveCount = Movable::getLiveCount();
takeLast<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::takeLastComplex() const
{
const int liveCount = Complex::getLiveCount();
takeLast<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
template<typename T>
void tst_QList::toSet() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// no duplicates
QCOMPARE(list.toSet(), QSet<T>() << T_FOO << T_BAR << T_BAZ);
QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
// duplicates (is this more of a QSet test?)
list << T_FOO << T_BAR << T_BAZ;
QCOMPARE(list.toSet(), QSet<T>() << T_FOO << T_BAR << T_BAZ);
QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ
<< T_FOO << T_BAR << T_BAZ);
}
void tst_QList::toSetOptimal() const
{
const int liveCount = Optimal::getLiveCount();
toSet<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::toSetMovable() const
{
const int liveCount = Movable::getLiveCount();
toSet<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::toSetComplex() const
{
const int liveCount = Complex::getLiveCount();
toSet<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::toStdList() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// yuck.
std::list<T> slist;
slist.push_back(T_FOO);
slist.push_back(T_BAR);
slist.push_back(T_BAZ);
QCOMPARE(list.toStdList(), slist);
QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
}
void tst_QList::toStdListOptimal() const
{
const int liveCount = Optimal::getLiveCount();
toStdList<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::toStdListMovable() const
{
const int liveCount = Movable::getLiveCount();
toStdList<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::toStdListComplex() const
{
const int liveCount = Complex::getLiveCount();
toStdList<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
#endif
template<typename T>
void tst_QList::toVector() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
QCOMPARE(list.toVector(), QVector<T>() << T_FOO << T_BAR << T_BAZ);
}
void tst_QList::toVectorOptimal() const
{
const int liveCount = Optimal::getLiveCount();
toVector<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::toVectorMovable() const
{
const int liveCount = Movable::getLiveCount();
toVector<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::toVectorComplex() const
{
const int liveCount = Complex::getLiveCount();
toVector<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::value() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
// test real values
QCOMPARE(list.value(0), T_FOO);
QCOMPARE(list.value(2), T_BAZ);
// test empty default
QCOMPARE(list.value(3), T());
QCOMPARE(list.value(-1), T());
// test defaults
T defaultT(T_WEEE);
QCOMPARE(list.value(-1, defaultT), defaultT);
QCOMPARE(list.value(3, defaultT), defaultT);
}
void tst_QList::valueOptimal() const
{
const int liveCount = Optimal::getLiveCount();
value<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::valueMovable() const
{
const int liveCount = Movable::getLiveCount();
value<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::valueComplex() const
{
const int liveCount = Complex::getLiveCount();
value<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::testOperators() const
{
QList<T> list;
list << T_FOO << T_BAR << T_BAZ;
QList<T> listtwo;
listtwo << T_FOO << T_BAR << T_BAZ;
// test equal
QVERIFY(list == listtwo);
// not equal
listtwo.append(T_CAT);
QVERIFY(list != listtwo);
// +=
list += listtwo;
QVERIFY(list.size() == 7);
QVERIFY(listtwo.size() == 4);
QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ
<< T_FOO << T_BAR << T_BAZ << T_CAT);
// =
list = listtwo;
QCOMPARE(list, listtwo);
QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ << T_CAT);
// []
QCOMPARE(list[0], T_FOO);
QCOMPARE(list[list.size() - 1], T_CAT);
// <, >, <=, >=
QVERIFY(!(list < listtwo));
QVERIFY(!(list > listtwo));
QVERIFY( list <= listtwo);
QVERIFY( list >= listtwo);
listtwo.push_back(T_CAT);
QVERIFY( list < listtwo);
QVERIFY(!(list > listtwo));
QVERIFY( list <= listtwo);
QVERIFY(!(list >= listtwo));
QVERIFY(listtwo > list);
QVERIFY(listtwo >= list);
}
void tst_QList::testOperatorsOptimal() const
{
const int liveCount = Optimal::getLiveCount();
testOperators<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::testOperatorsMovable() const
{
const int liveCount = Movable::getLiveCount();
testOperators<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::testOperatorsComplex() const
{
const int liveCount = Complex::getLiveCount();
testOperators<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template<typename T>
void tst_QList::testSTLIterators() const
{
QList<T> list;
// create a list
list << T_FOO << T_BAR << T_BAZ;
typename QList<T>::iterator it = list.begin();
QCOMPARE(*it, T_FOO); it++;
QCOMPARE(*it, T_BAR); it++;
QCOMPARE(*it, T_BAZ); it++;
QCOMPARE(it, list.end()); it--;
// walk backwards
QCOMPARE(*it, T_BAZ); it--;
QCOMPARE(*it, T_BAR); it--;
QCOMPARE(*it, T_FOO);
// test erase
it = list.erase(it);
QVERIFY(list.size() == 2);
QCOMPARE(*it, T_BAR);
// test multiple erase
it = list.erase(it, it + 2);
QVERIFY(list.size() == 0);
QCOMPARE(it, list.end());
// insert again
it = list.insert(it, T_FOO);
QVERIFY(list.size() == 1);
QCOMPARE(*it, T_FOO);
// insert again
it = list.insert(it, T_BAR);
QVERIFY(list.size() == 2);
QCOMPARE(*it++, T_BAR);
QCOMPARE(*it, T_FOO);
}
void tst_QList::testSTLIteratorsOptimal() const
{
const int liveCount = Optimal::getLiveCount();
testSTLIterators<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::testSTLIteratorsMovable() const
{
const int liveCount = Movable::getLiveCount();
testSTLIterators<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::testSTLIteratorsComplex() const
{
const int liveCount = Complex::getLiveCount();
testSTLIterators<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
void tst_QList::initializeList() const
{
QList<int> v1{2,3,4};
QCOMPARE(v1, QList<int>() << 2 << 3 << 4);
QCOMPARE(v1, (QList<int>{2,3,4}));
QList<QList<int>> v2{ v1, {1}, QList<int>(), {2,3,4} };
QList<QList<int>> v3;
v3 << v1 << (QList<int>() << 1) << QList<int>() << v1;
QCOMPARE(v3, v2);
}
template<typename T>
void tst_QList::constSharedNull() const
{
QList<T> list2;
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
QList<T> list1;
list1.setSharable(false);
QVERIFY(list1.isDetached());
list2.setSharable(true);
#endif
QVERIFY(!list2.isDetached());
}
void tst_QList::constSharedNullOptimal() const
{
const int liveCount = Optimal::getLiveCount();
constSharedNull<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::constSharedNullMovable() const
{
const int liveCount = Movable::getLiveCount();
constSharedNull<Movable>();
QCOMPARE(liveCount, Movable::getLiveCount());
}
void tst_QList::constSharedNullComplex() const
{
const int liveCount = Complex::getLiveCount();
constSharedNull<Complex>();
QCOMPARE(liveCount, Complex::getLiveCount());
}
template <class T>
void generateSetSharableData()
{
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
QTest::addColumn<QList<T> >("list");
QTest::addColumn<int>("size");
QTest::newRow("null") << QList<T>() << 0;
QTest::newRow("non-empty") << (QList<T>() << T(0) << T(1) << T(2) << T(3) << T(4)) << 5;
#endif
}
template <class T>
void runSetSharableTest()
{
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
QFETCH(QList<T>, list);
QFETCH(int, size);
QVERIFY(!list.isDetached()); // Shared with QTest
list.setSharable(true);
QCOMPARE(list.size(), size);
{
QList<T> copy(list);
QVERIFY(!copy.isDetached());
QVERIFY(copy.isSharedWith(list));
}
list.setSharable(false);
QVERIFY(list.isDetached() || list.isSharedWith(QList<T>()));
{
QList<T> copy(list);
QVERIFY(copy.isDetached() || copy.isSharedWith(QList<T>()));
QCOMPARE(copy.size(), size);
QCOMPARE(copy, list);
}
list.setSharable(true);
{
QList<T> copy(list);
QVERIFY(!copy.isDetached());
QVERIFY(copy.isSharedWith(list));
}
for (int i = 0; i < list.size(); ++i)
QCOMPARE(int(list[i]), i);
QCOMPARE(list.size(), size);
#endif
}
void tst_QList::setSharableInt_data() const
{
generateSetSharableData<int>();
}
void tst_QList::setSharableComplex_data() const
{
generateSetSharableData<Complex>();
}
void tst_QList::setSharableInt() const
{
runSetSharableTest<int>();
}
void tst_QList::setSharableComplex() const
{
runSetSharableTest<Complex>();
}
void tst_QList::eraseValidIteratorsOnSharedList() const
{
QList<int> a, b;
a.push_back(10);
a.push_back(20);
a.push_back(30);
QList<int>::iterator i = a.begin();
++i;
b = a;
a.erase(i);
QCOMPARE(b.size(), 3);
QCOMPARE(a.size(), 2);
QCOMPARE(a.at(0), 10);
QCOMPARE(a.at(1), 30);
a.push_back(40);
a.push_back(50);
a.push_back(60);
QCOMPARE(a.size(), 5);
i = a.begin();
b = a;
++i;
QList<int>::iterator j = i;
++j;
++j;
a.erase(i, j); // remove 3 elements
QCOMPARE(b.size(), 5);
QCOMPARE(a.size(), 3);
QCOMPARE(a.at(0), 10);
QCOMPARE(a.at(1), 50);
}
void tst_QList::insertWithValidIteratorsOnSharedList() const
{
QList<int> a, b;
a.push_back(10);
a.push_back(20);
a.push_back(30);
QList<int>::iterator i = a.begin();
++i;
b = a;
a.insert(i, 15);
QCOMPARE(a.size(), b.size() + 1);
QCOMPARE(b.at(1), 20);
QCOMPARE(a.at(1), 15);
}
template <typename T>
void tst_QList::qhash() const
{
QList<T> l1, l2;
QCOMPARE(qHash(l1), qHash(l2));
l1 << T_BAR;
l2 << T_BAR;
QCOMPARE(qHash(l1), qHash(l2));
}
void tst_QList::reserve() const
{
// Note:
// This test depends on QList's current behavior that ints are stored in the array itself.
// This test would not work for QList<Complex>.
int capacity = 100;
QList<int> list;
list.reserve(capacity);
list << 0;
int *data = &list[0];
for (int i = 1; i < capacity; i++) {
list << i;
QCOMPARE(&list.at(0), data);
}
QList<int> copy = list;
list.reserve(capacity / 2);
QCOMPARE(list.size(), capacity); // we didn't shrink the size!
copy = list;
list.reserve(capacity * 2);
QCOMPARE(list.size(), capacity);
QVERIFY(&list.at(0) != data);
}
QTEST_APPLESS_MAIN(tst_QList)
#include "tst_qlist.moc"