tst_QList: test all memory layouts

The Movable type, surprisingly, was as large as sizeof(void*), so on
32-bit platforms, we were not testing the QList memory layout where
items are placed directly into the void*-slots, but are too small,
leaving gaps.

Fixed by making sure that Movable is smaller than void* and adding
a variant of Movable, Optimal, that is guaranteed to be the same
size as void*, and replacing the int tests with tests of Optimal.

Had to demote the State variable to uchar, since MSVC will apparently
not make a collection of bit-fields smaller than the largest type used
in any of the consituent bitfields, so State s : 8 wouldn't work.

Change-Id: I4f0e24bd6928f076b4ce60e8d977d5d98a724161
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Marc Mutz 2014-10-01 12:03:59 +02:00
parent 647ad3fe25
commit 4c4940a744
1 changed files with 226 additions and 93 deletions

View File

@ -79,14 +79,16 @@ private:
static int liveCount;
enum State { Constructed = 106, Destructed = 110 };
State state;
uchar state;
static void check(const State state1, const State state2)
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
@ -100,6 +102,75 @@ 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;
}
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)
@ -160,6 +231,8 @@ 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);
@ -168,100 +241,100 @@ class tst_QList : public QObject
Q_OBJECT
private slots:
void lengthInt() const;
void lengthOptimal() const;
void lengthMovable() const;
void lengthComplex() const;
void lengthSignature() const;
void appendInt() const;
void appendOptimal() const;
void appendMovable() const;
void appendComplex() const;
void prepend() const;
void midInt() const;
void midOptimal() const;
void midMovable() const;
void midComplex() const;
void atInt() const;
void atOptimal() const;
void atMovable() const;
void atComplex() const;
void firstInt() const;
void firstOptimal() const;
void firstMovable() const;
void firstComplex() const;
void lastInt() const;
void lastOptimal() const;
void lastMovable() const;
void lastComplex() const;
void beginInt() const;
void beginOptimal() const;
void beginMovable() const;
void beginComplex() const;
void endInt() const;
void endOptimal() const;
void endMovable() const;
void endComplex() const;
void containsInt() const;
void containsOptimal() const;
void containsMovable() const;
void containsComplex() const;
void countInt() const;
void countOptimal() const;
void countMovable() const;
void countComplex() const;
void emptyInt() const;
void emptyOptimal() const;
void emptyMovable() const;
void emptyComplex() const;
void endsWithInt() const;
void endsWithOptimal() const;
void endsWithMovable() const;
void endsWithComplex() const;
void lastIndexOfInt() const;
void lastIndexOfOptimal() const;
void lastIndexOfMovable() const;
void lastIndexOfComplex() const;
void moveInt() const;
void moveOptimal() const;
void moveMovable() const;
void moveComplex() const;
void removeAllInt() const;
void removeAllOptimal() const;
void removeAllMovable() const;
void removeAllComplex() const;
void removeAtInt() const;
void removeAtOptimal() const;
void removeAtMovable() const;
void removeAtComplex() const;
void removeOneInt() const;
void removeOneOptimal() const;
void removeOneMovable() const;
void removeOneComplex() const;
void replaceInt() const;
void replaceOptimal() const;
void replaceMovable() const;
void replaceComplex() const;
void startsWithInt() const;
void startsWithOptimal() const;
void startsWithMovable() const;
void startsWithComplex() const;
void swapInt() const;
void swapOptimal() const;
void swapMovable() const;
void swapComplex() const;
void takeAtInt() const;
void takeAtOptimal() const;
void takeAtMovable() const;
void takeAtComplex() const;
void takeFirstInt() const;
void takeFirstOptimal() const;
void takeFirstMovable() const;
void takeFirstComplex() const;
void takeLastInt() const;
void takeLastOptimal() const;
void takeLastMovable() const;
void takeLastComplex() const;
void toSetInt() const;
void toSetOptimal() const;
void toSetMovable() const;
void toSetComplex() const;
void toStdListInt() const;
void toStdListOptimal() const;
void toStdListMovable() const;
void toStdListComplex() const;
void toVectorInt() const;
void toVectorOptimal() const;
void toVectorMovable() const;
void toVectorComplex() const;
void valueInt() const;
void valueOptimal() const;
void valueMovable() const;
void valueComplex() const;
void testOperatorsInt() const;
void testOperatorsOptimal() const;
void testOperatorsMovable() const;
void testOperatorsComplex() const;
void testSTLIteratorsInt() const;
void testSTLIteratorsOptimal() const;
void testSTLIteratorsMovable() const;
void testSTLIteratorsComplex() const;
void initializeList() const;
void constSharedNullInt() const;
void constSharedNullOptimal() const;
void constSharedNullMovable() const;
void constSharedNullComplex() const;
void setSharableInt_data() const;
@ -320,7 +393,7 @@ template<typename T> struct SimpleValue
};
template<>
const int SimpleValue<int>::values[] = { 10, 20, 30, 40, 100, 101, 102 };
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<>
@ -369,9 +442,11 @@ void tst_QList::length() const
}
}
void tst_QList::lengthInt() const
void tst_QList::lengthOptimal() const
{
length<int>();
const int liveCount = Optimal::getLiveCount();
length<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::lengthMovable() const
@ -421,9 +496,11 @@ void tst_QList::append() const
QCOMPARE(list1, listTotal);
}
void tst_QList::appendInt() const
void tst_QList::appendOptimal() const
{
append<int>();
const int liveCount = Optimal::getLiveCount();
append<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::appendMovable() const
@ -486,9 +563,11 @@ void tst_QList::mid() const
QCOMPARE(list1.mid(1, 1).length(), 0);
}
void tst_QList::midInt() const
void tst_QList::midOptimal() const
{
mid<int>();
const int liveCount = Optimal::getLiveCount();
mid<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::midMovable() const
@ -534,9 +613,11 @@ void tst_QList::at() const
QCOMPARE(list.at(2), T_CAT);
}
void tst_QList::atInt() const
void tst_QList::atOptimal() const
{
at<int>();
const int liveCount = Optimal::getLiveCount();
at<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::atMovable() const
@ -567,9 +648,11 @@ void tst_QList::first() const
QCOMPARE(list.first(), T_BAR);
}
void tst_QList::firstInt() const
void tst_QList::firstOptimal() const
{
first<int>();
const int liveCount = Optimal::getLiveCount();
first<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::firstMovable() const
@ -600,9 +683,11 @@ void tst_QList::last() const
QCOMPARE(list.last(), T_FOO);
}
void tst_QList::lastInt() const
void tst_QList::lastOptimal() const
{
last<int>();
const int liveCount = Optimal::getLiveCount();
last<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::lastMovable() const
@ -633,9 +718,11 @@ void tst_QList::begin() const
QCOMPARE(*list.begin(), T_BAR);
}
void tst_QList::beginInt() const
void tst_QList::beginOptimal() const
{
begin<int>();
const int liveCount = Optimal::getLiveCount();
begin<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::beginMovable() const
@ -666,9 +753,11 @@ void tst_QList::end() const
QCOMPARE(*--list.end(), T_FOO);
}
void tst_QList::endInt() const
void tst_QList::endOptimal() const
{
end<int>();
const int liveCount = Optimal::getLiveCount();
end<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::endMovable() const
@ -699,9 +788,11 @@ void tst_QList::contains() const
QVERIFY(list.contains(T_BLAH) == true);
}
void tst_QList::containsInt() const
void tst_QList::containsOptimal() const
{
contains<int>();
const int liveCount = Optimal::getLiveCount();
contains<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::containsMovable() const
@ -743,9 +834,11 @@ void tst_QList::count() const
QVERIFY(list.count() == 0);
}
void tst_QList::countInt() const
void tst_QList::countOptimal() const
{
count<int>();
const int liveCount = Optimal::getLiveCount();
count<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::countMovable() const
@ -779,9 +872,11 @@ void tst_QList::empty() const
QVERIFY(list.empty());
}
void tst_QList::emptyInt() const
void tst_QList::emptyOptimal() const
{
empty<int>();
const int liveCount = Optimal::getLiveCount();
empty<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::emptyMovable() const
@ -813,9 +908,11 @@ void tst_QList::endsWith() const
QVERIFY(list.endsWith(T_BAR));
}
void tst_QList::endsWithInt() const
void tst_QList::endsWithOptimal() const
{
endsWith<int>();
const int liveCount = Optimal::getLiveCount();
endsWith<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::endsWithMovable() const
@ -856,9 +953,11 @@ void tst_QList::lastIndexOf() const
QVERIFY(list.lastIndexOf(T_BAZ, 1) == -1);
}
void tst_QList::lastIndexOfInt() const
void tst_QList::lastIndexOfOptimal() const
{
lastIndexOf<int>();
const int liveCount = Optimal::getLiveCount();
lastIndexOf<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::lastIndexOfMovable() const
@ -894,9 +993,11 @@ void tst_QList::move() const
QCOMPARE(list, QList<T>() << T_BAR << T_FOO << T_BAZ);
}
void tst_QList::moveInt() const
void tst_QList::moveOptimal() const
{
move<int>();
const int liveCount = Optimal::getLiveCount();
move<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::moveMovable() const
@ -933,9 +1034,11 @@ void tst_QList::removeAll() const
QCOMPARE(list, QList<T>() << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ << T_FOO << T_BAZ);
}
void tst_QList::removeAllInt() const
void tst_QList::removeAllOptimal() const
{
removeAll<int>();
const int liveCount = Optimal::getLiveCount();
removeAll<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::removeAllMovable() const
@ -971,9 +1074,11 @@ void tst_QList::removeAt() const
QCOMPARE(list, QList<T>());
}
void tst_QList::removeAtInt() const
void tst_QList::removeAtOptimal() const
{
removeAt<int>();
const int liveCount = Optimal::getLiveCount();
removeAt<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::removeAtMovable() const
@ -1018,9 +1123,11 @@ void tst_QList::removeOne() const
QCOMPARE(list, QList<T>() << T_FOO);
}
void tst_QList::removeOneInt() const
void tst_QList::removeOneOptimal() const
{
removeOne<int>();
const int liveCount = Optimal::getLiveCount();
removeOne<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::removeOneMovable() const
@ -1059,9 +1166,11 @@ void tst_QList::replace() const
<< T_DOG << T_BLAH);
}
void tst_QList::replaceInt() const
void tst_QList::replaceOptimal() const
{
replace<int>();
const int liveCount = Optimal::getLiveCount();
replace<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::replaceMovable() const
@ -1092,9 +1201,11 @@ void tst_QList::startsWith() const
QVERIFY(list.startsWith(T_BAR));
}
void tst_QList::startsWithInt() const
void tst_QList::startsWithOptimal() const
{
startsWith<int>();
const int liveCount = Optimal::getLiveCount();
startsWith<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::startsWithMovable() const
@ -1133,9 +1244,11 @@ void tst_QList::swap() const
QCOMPARE(list2, QList<T>() << T_BAZ << T_FOO << T_BAR);
}
void tst_QList::swapInt() const
void tst_QList::swapOptimal() const
{
swap<int>();
const int liveCount = Optimal::getLiveCount();
swap<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::swapMovable() const
@ -1166,9 +1279,11 @@ void tst_QList::takeAt() const
QVERIFY(list.size() == 0);
}
void tst_QList::takeAtInt() const
void tst_QList::takeAtOptimal() const
{
takeAt<int>();
const int liveCount = Optimal::getLiveCount();
takeAt<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::takeAtMovable() const
@ -1199,9 +1314,11 @@ void tst_QList::takeFirst() const
QVERIFY(list.size() == 0);
}
void tst_QList::takeFirstInt() const
void tst_QList::takeFirstOptimal() const
{
takeFirst<int>();
const int liveCount = Optimal::getLiveCount();
takeFirst<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::takeFirstMovable() const
@ -1229,9 +1346,11 @@ void tst_QList::takeLast() const
QCOMPARE(list.takeLast(), T_FOO);
}
void tst_QList::takeLastInt() const
void tst_QList::takeLastOptimal() const
{
takeLast<int>();
const int liveCount = Optimal::getLiveCount();
takeLast<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::takeLastMovable() const
@ -1265,9 +1384,11 @@ void tst_QList::toSet() const
<< T_FOO << T_BAR << T_BAZ);
}
void tst_QList::toSetInt() const
void tst_QList::toSetOptimal() const
{
toSet<int>();
const int liveCount = Optimal::getLiveCount();
toSet<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::toSetMovable() const
@ -1300,9 +1421,11 @@ void tst_QList::toStdList() const
QCOMPARE(list, QList<T>() << T_FOO << T_BAR << T_BAZ);
}
void tst_QList::toStdListInt() const
void tst_QList::toStdListOptimal() const
{
toStdList<int>();
const int liveCount = Optimal::getLiveCount();
toStdList<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::toStdListMovable() const
@ -1328,9 +1451,11 @@ void tst_QList::toVector() const
QCOMPARE(list.toVector(), QVector<T>() << T_FOO << T_BAR << T_BAZ);
}
void tst_QList::toVectorInt() const
void tst_QList::toVectorOptimal() const
{
toVector<int>();
const int liveCount = Optimal::getLiveCount();
toVector<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::toVectorMovable() const
@ -1367,9 +1492,11 @@ void tst_QList::value() const
QCOMPARE(list.value(3, defaultT), defaultT);
}
void tst_QList::valueInt() const
void tst_QList::valueOptimal() const
{
value<int>();
const int liveCount = Optimal::getLiveCount();
value<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::valueMovable() const
@ -1419,9 +1546,11 @@ void tst_QList::testOperators() const
QCOMPARE(list[list.size() - 1], T_CAT);
}
void tst_QList::testOperatorsInt() const
void tst_QList::testOperatorsOptimal() const
{
testOperators<int>();
const int liveCount = Optimal::getLiveCount();
testOperators<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::testOperatorsMovable() const
@ -1478,9 +1607,11 @@ void tst_QList::testSTLIterators() const
QCOMPARE(*it, T_FOO);
}
void tst_QList::testSTLIteratorsInt() const
void tst_QList::testSTLIteratorsOptimal() const
{
testSTLIterators<int>();
const int liveCount = Optimal::getLiveCount();
testSTLIterators<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::testSTLIteratorsMovable() const
@ -1525,9 +1656,11 @@ void tst_QList::constSharedNull() const
QVERIFY(!list2.isDetached());
}
void tst_QList::constSharedNullInt() const
void tst_QList::constSharedNullOptimal() const
{
constSharedNull<int>();
const int liveCount = Optimal::getLiveCount();
constSharedNull<Optimal>();
QCOMPARE(liveCount, Optimal::getLiveCount());
}
void tst_QList::constSharedNullMovable() const