Unit-test the additional QBasicAtomicXXX expansions

Test that they do expand properly and don't produce errors. This is
templated code, so it doesn't get tested fully unless we instantiate
them.

Also check that the alignments are correct.

Change-Id: I2a8ee2165167f54b652b4227411e209850974b8e
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
Thiago Macieira 2011-07-31 19:41:18 -03:00 committed by Qt by Nokia
parent dc6a1d186e
commit 2cf466312b
2 changed files with 128 additions and 20 deletions

View File

@ -52,6 +52,7 @@ class tst_QAtomicInt : public QObject
private slots:
void warningFree();
void alignment();
// QAtomicInt members
void constructor_data();
@ -92,33 +93,101 @@ private:
static void warningFreeHelper();
};
template <int I>
static inline void assemblyMarker(void *ptr = 0)
{
puts((char *)ptr + I);
}
QT_BEGIN_NAMESPACE
template <typename T> class QBasicAtomicInteger; // even if it this class isn't supported
QT_END_NAMESPACE
template <typename T, typename Atomic>
static void warningFreeHelperTemplate()
{
T expectedValue = 0;
T newValue = 0;
T valueToAdd = 0;
// the marker calls are here only to provide a divider for
// those reading the assembly output
assemblyMarker<0>();
Atomic i = Q_BASIC_ATOMIC_INITIALIZER(0);
printf("%d\n", int(i.loadAcquire()));
assemblyMarker<1>(&i);
// the loads sometimes generate no assembly output
i.load();
assemblyMarker<11>(&i);
i.loadAcquire();
assemblyMarker<12>(&i);
i.store(newValue);
assemblyMarker<21>(&i);
i.storeRelease(newValue);
assemblyMarker<22>(&i);
i.ref();
assemblyMarker<31>(&i);
i.deref();
assemblyMarker<32>(&i);
i.testAndSetRelaxed(expectedValue, newValue);
assemblyMarker<41>(&i);
i.testAndSetAcquire(expectedValue, newValue);
assemblyMarker<42>(&i);
i.testAndSetRelease(expectedValue, newValue);
assemblyMarker<43>(&i);
i.testAndSetOrdered(expectedValue, newValue);
assemblyMarker<44>(&i);
i.fetchAndStoreRelaxed(newValue);
assemblyMarker<51>(&i);
i.fetchAndStoreAcquire(newValue);
assemblyMarker<52>(&i);
i.fetchAndStoreRelease(newValue);
assemblyMarker<53>(&i);
i.fetchAndStoreOrdered(newValue);
assemblyMarker<54>(&i);
i.fetchAndAddRelaxed(valueToAdd);
assemblyMarker<61>(&i);
i.fetchAndAddAcquire(valueToAdd);
assemblyMarker<62>(&i);
i.fetchAndAddRelease(valueToAdd);
assemblyMarker<63>(&i);
i.fetchAndAddOrdered(valueToAdd);
assemblyMarker<64>(&i);
}
void tst_QAtomicInt::warningFreeHelper()
{
qFatal("This code is bogus, and shouldn't be run. We're looking for compiler warnings only.");
warningFreeHelperTemplate<int, QBasicAtomicInt>();
QBasicAtomicInt i = Q_BASIC_ATOMIC_INITIALIZER(0);
#ifdef Q_ATOMIC_INT32_IS_SUPPORTED
warningFreeHelperTemplate<int, QBasicAtomicInteger<int> >();
warningFreeHelperTemplate<unsigned int, QBasicAtomicInteger<unsigned int> >();
#endif
int expectedValue = 0;
int newValue = 0;
int valueToAdd = 0;
#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
warningFreeHelperTemplate<qint16, QBasicAtomicInteger<qint16> >();
warningFreeHelperTemplate<quint16, QBasicAtomicInteger<quint16> >();
#endif
i.ref();
i.deref();
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
warningFreeHelperTemplate<char, QBasicAtomicInteger<char> >();
warningFreeHelperTemplate<signed char, QBasicAtomicInteger<signed char> >();
warningFreeHelperTemplate<unsigned char, QBasicAtomicInteger<unsigned char> >();
#endif
i.testAndSetRelaxed(expectedValue, newValue);
i.testAndSetAcquire(expectedValue, newValue);
i.testAndSetRelease(expectedValue, newValue);
i.testAndSetOrdered(expectedValue, newValue);
i.fetchAndStoreRelaxed(newValue);
i.fetchAndStoreAcquire(newValue);
i.fetchAndStoreRelease(newValue);
i.fetchAndStoreOrdered(newValue);
i.fetchAndAddRelaxed(valueToAdd);
i.fetchAndAddAcquire(valueToAdd);
i.fetchAndAddRelease(valueToAdd);
i.fetchAndAddOrdered(valueToAdd);
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
#if !defined(__i386__) || (defined(Q_CC_GNU) && defined(__OPTIMIZE__))
warningFreeHelperTemplate<qlonglong, QBasicAtomicInteger<qlonglong> >();
warningFreeHelperTemplate<qulonglong, QBasicAtomicInteger<qulonglong> >();
#endif
#endif
}
void tst_QAtomicInt::warningFree()
@ -130,6 +199,35 @@ void tst_QAtomicInt::warningFree()
(void)foo;
}
template <typename T> struct TypeInStruct { T type; };
void tst_QAtomicInt::alignment()
{
#ifdef Q_ALIGNOF
// this will cause a build error if the alignment isn't the same
char dummy1[Q_ALIGNOF(QBasicAtomicInt) == Q_ALIGNOF(TypeInStruct<int>) ? 1 : -1];
char dummy2[Q_ALIGNOF(QAtomicInt) == Q_ALIGNOF(TypeInStruct<int>) ? 1 : -1];
(void)dummy1; (void)dummy2;
#ifdef Q_ATOMIC_INT32_IS_SUPPORTED
QCOMPARE(Q_ALIGNOF(QBasicAtomicInteger<int>), Q_ALIGNOF(TypeInStruct<int>));
#endif
#ifdef Q_ATOMIC_INT16_IS_SUPPORTED
QCOMPARE(Q_ALIGNOF(QBasicAtomicInteger<short>), Q_ALIGNOF(TypeInStruct<short>));
#endif
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
QCOMPARE(Q_ALIGNOF(QBasicAtomicInteger<char>), Q_ALIGNOF(TypeInStruct<char>));
#endif
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
QCOMPARE(Q_ALIGNOF(QBasicAtomicInteger<qlonglong>), Q_ALIGNOF(TypeInStruct<qlonglong>));
#endif
#endif
}
void tst_QAtomicInt::constructor_data()
{
QTest::addColumn<int>("value");

View File

@ -49,6 +49,7 @@ class tst_QAtomicPointer : public QObject
Q_OBJECT
private slots:
void warningFree();
void alignment();
void constructor();
void copy_constructor();
@ -114,6 +115,15 @@ void tst_QAtomicPointer::warningFree()
(void)foo;
}
void tst_QAtomicPointer::alignment()
{
#ifdef Q_ALIGNOF
// this will cause a build error if the alignment isn't the same
char dummy[Q_ALIGNOF(QBasicAtomicPointer<void>) == Q_ALIGNOF(void*) ? 1 : -1];
(void)dummy;
#endif
}
void tst_QAtomicPointer::constructor()
{
void *one = this;