/**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #ifdef Q_OS_LINUX # include #endif Q_DECLARE_METATYPE(QMetaType::Type) class tst_QMetaType: public QObject { Q_OBJECT Q_PROPERTY(QList prop READ prop WRITE setProp) public: tst_QMetaType() { propList << 42 << "Hello"; } QList prop() const { return propList; } void setProp(const QList &list) { propList = list; } private: QList propList; private slots: void defined(); void threadSafety(); void namespaces(); void qMetaTypeId(); void properties(); void normalizedTypes(); void typeName_data(); void typeName(); void create_data(); void create(); void createCopy_data(); void createCopy(); void sizeOf_data(); void sizeOf(); void sizeOfStaticLess_data(); void sizeOfStaticLess(); void flags_data(); void flags(); void flagsStaticLess_data(); void flagsStaticLess(); void construct_data(); void construct(); void constructCopy_data(); void constructCopy(); void typedefs(); void registerType(); void isRegistered_data(); void isRegistered(); void isRegisteredStaticLess_data(); void isRegisteredStaticLess(); void registerStreamBuiltin(); void automaticTemplateRegistration(); }; struct Foo { int i; }; void tst_QMetaType::defined() { QCOMPARE(int(QMetaTypeId2::Defined), 1); QCOMPARE(int(QMetaTypeId2::Defined), 0); QCOMPARE(int(QMetaTypeId2::Defined), 1); QCOMPARE(int(QMetaTypeId2::Defined), 0); } struct Bar { Bar() { // check re-entrancy if (!QMetaType::isRegistered(qRegisterMetaType("Foo"))) { qWarning("%s: re-entrancy test failed", Q_FUNC_INFO); ++failureCount; } } public: static int failureCount; }; int Bar::failureCount = 0; class MetaTypeTorturer: public QThread { Q_OBJECT protected: void run() { Bar space[1]; space[0].~Bar(); for (int i = 0; i < 1000; ++i) { const QByteArray name = QString("Bar%1_%2").arg(i).arg((size_t)QThread::currentThreadId()).toLatin1(); const char *nm = name.constData(); int tp = qRegisterMetaType(nm); #ifdef Q_OS_LINUX pthread_yield(); #endif QMetaType info(tp); if (!info.isValid()) { ++failureCount; qWarning() << "Wrong typeInfo returned for" << tp; } if (!info.isRegistered()) { ++failureCount; qWarning() << name << "is not a registered metatype"; } if (QMetaType::typeFlags(tp) != (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction)) { ++failureCount; qWarning() << "Wrong typeInfo returned for" << tp; } if (!QMetaType::isRegistered(tp)) { ++failureCount; qWarning() << name << "is not a registered metatype"; } if (QMetaType::type(nm) != tp) { ++failureCount; qWarning() << "Wrong metatype returned for" << name; } if (QMetaType::typeName(tp) != name) { ++failureCount; qWarning() << "Wrong typeName returned for" << tp; } void *buf1 = QMetaType::create(tp, 0); void *buf2 = QMetaType::create(tp, buf1); void *buf3 = info.create(tp, 0); void *buf4 = info.create(tp, buf1); QMetaType::construct(tp, space, 0); QMetaType::destruct(tp, space); QMetaType::construct(tp, space, buf1); QMetaType::destruct(tp, space); info.construct(space, 0); info.destruct(space); info.construct(space, buf1); info.destruct(space); if (!buf1) { ++failureCount; qWarning() << "Null buffer returned by QMetaType::create(tp, 0)"; } if (!buf2) { ++failureCount; qWarning() << "Null buffer returned by QMetaType::create(tp, buf)"; } if (!buf3) { ++failureCount; qWarning() << "Null buffer returned by info.create(tp, 0)"; } if (!buf4) { ++failureCount; qWarning() << "Null buffer returned by infocreate(tp, buf)"; } QMetaType::destroy(tp, buf1); QMetaType::destroy(tp, buf2); info.destroy(buf3); info.destroy(buf4); } new (space) Bar; } public: MetaTypeTorturer() : failureCount(0) { } int failureCount; }; void tst_QMetaType::threadSafety() { MetaTypeTorturer t1; MetaTypeTorturer t2; MetaTypeTorturer t3; t1.start(); t2.start(); t3.start(); QVERIFY(t1.wait()); QVERIFY(t2.wait()); QVERIFY(t3.wait()); QCOMPARE(t1.failureCount, 0); QCOMPARE(t2.failureCount, 0); QCOMPARE(t3.failureCount, 0); QCOMPARE(Bar::failureCount, 0); } namespace TestSpace { struct Foo { double d; }; } Q_DECLARE_METATYPE(TestSpace::Foo) void tst_QMetaType::namespaces() { TestSpace::Foo nf = { 11.12 }; QVariant v = qVariantFromValue(nf); QCOMPARE(qvariant_cast(v).d, 11.12); } void tst_QMetaType::qMetaTypeId() { QCOMPARE(::qMetaTypeId(), int(QMetaType::QString)); QCOMPARE(::qMetaTypeId(), int(QMetaType::Int)); QCOMPARE(::qMetaTypeId(), QMetaType::type("TestSpace::Foo")); QCOMPARE(::qMetaTypeId(), QMetaType::type("char")); QCOMPARE(::qMetaTypeId(), QMetaType::type("unsigned char")); QCOMPARE(::qMetaTypeId(), QMetaType::type("signed char")); QCOMPARE(::qMetaTypeId(), QMetaType::type("qint8")); } void tst_QMetaType::properties() { qRegisterMetaType >("QList"); QVariant v = property("prop"); QCOMPARE(v.typeName(), "QVariantList"); QList values = v.toList(); QCOMPARE(values.count(), 2); QCOMPARE(values.at(0).toInt(), 42); values << 43 << "world"; QVERIFY(setProperty("prop", values)); v = property("prop"); QCOMPARE(v.toList().count(), 4); } template struct Whity { T t; }; Q_DECLARE_METATYPE( Whity < int > ) Q_DECLARE_METATYPE(Whity) void tst_QMetaType::normalizedTypes() { int WhityIntId = ::qMetaTypeId >(); int WhityDoubleId = ::qMetaTypeId >(); QCOMPARE(QMetaType::type("Whity"), WhityIntId); QCOMPARE(QMetaType::type(" Whity < int > "), WhityIntId); QCOMPARE(QMetaType::type("Whity"), WhityIntId); QCOMPARE(QMetaType::type("Whity"), WhityDoubleId); QCOMPARE(QMetaType::type(" Whity< double > "), WhityDoubleId); QCOMPARE(QMetaType::type("Whity"), WhityDoubleId); QCOMPARE(qRegisterMetaType >(" Whity < int > "), WhityIntId); QCOMPARE(qRegisterMetaType >("Whity"), WhityIntId); QCOMPARE(qRegisterMetaType >("Whity "), WhityIntId); QCOMPARE(qRegisterMetaType >(" Whity < double > "), WhityDoubleId); QCOMPARE(qRegisterMetaType >("Whity"), WhityDoubleId); QCOMPARE(qRegisterMetaType >("Whity "), WhityDoubleId); } #define TYPENAME_DATA(MetaTypeName, MetaTypeId, RealType)\ QTest::newRow(#RealType) << QMetaType::MetaTypeName << #RealType; #define TYPENAME_DATA_ALIAS(MetaTypeName, MetaTypeId, AliasType, RealTypeString)\ QTest::newRow(RealTypeString) << QMetaType::MetaTypeName << #AliasType; void tst_QMetaType::typeName_data() { QTest::addColumn("aType"); QTest::addColumn("aTypeName"); QT_FOR_EACH_STATIC_TYPE(TYPENAME_DATA) QT_FOR_EACH_STATIC_ALIAS_TYPE(TYPENAME_DATA_ALIAS) } void tst_QMetaType::typeName() { QFETCH(QMetaType::Type, aType); QFETCH(QString, aTypeName); QCOMPARE(QString::fromLatin1(QMetaType::typeName(aType)), aTypeName); } #define FOR_EACH_PRIMITIVE_METATYPE(F) \ QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \ QT_FOR_EACH_STATIC_CORE_POINTER(F) \ #define FOR_EACH_COMPLEX_CORE_METATYPE(F) \ QT_FOR_EACH_STATIC_CORE_CLASS(F) #define FOR_EACH_CORE_METATYPE(F) \ FOR_EACH_PRIMITIVE_METATYPE(F) \ FOR_EACH_COMPLEX_CORE_METATYPE(F) \ template struct MetaEnumToType {}; #define DEFINE_META_ENUM_TO_TYPE(MetaTypeName, MetaTypeId, RealType) \ template<> \ struct MetaEnumToType { \ typedef RealType Type; \ }; FOR_EACH_CORE_METATYPE(DEFINE_META_ENUM_TO_TYPE) #undef DEFINE_META_ENUM_TO_TYPE template struct DefaultValueFactory { typedef typename MetaEnumToType::Type Type; static Type *create() { return new Type; } }; template <> struct DefaultValueFactory { typedef MetaEnumToType::Type Type; static Type *create() { return 0; } }; template struct DefaultValueTraits { // By default we assume that a default-constructed value (new T) is // initialized; e.g. QCOMPARE(*(new T), *(new T)) should succeed enum { IsInitialized = true }; }; #define DEFINE_NON_INITIALIZED_DEFAULT_VALUE_TRAITS(MetaTypeName, MetaTypeId, RealType) \ template<> struct DefaultValueTraits { \ enum { IsInitialized = false }; \ }; // Primitive types (int et al) aren't initialized FOR_EACH_PRIMITIVE_METATYPE(DEFINE_NON_INITIALIZED_DEFAULT_VALUE_TRAITS) #undef DEFINE_NON_INITIALIZED_DEFAULT_VALUE_TRAITS template struct TestValueFactory {}; template<> struct TestValueFactory { static void *create() { return 0; } }; template<> struct TestValueFactory { static QString *create() { return new QString(QString::fromLatin1("QString")); } }; template<> struct TestValueFactory { static int *create() { return new int(0x12345678); } }; template<> struct TestValueFactory { static uint *create() { return new uint(0x12345678); } }; template<> struct TestValueFactory { static bool *create() { return new bool(true); } }; template<> struct TestValueFactory { static double *create() { return new double(3.14); } }; template<> struct TestValueFactory { static QByteArray *create() { return new QByteArray(QByteArray("QByteArray")); } }; template<> struct TestValueFactory { static QChar *create() { return new QChar(QChar('q')); } }; template<> struct TestValueFactory { static long *create() { return new long(0x12345678); } }; template<> struct TestValueFactory { static short *create() { return new short(0x1234); } }; template<> struct TestValueFactory { static char *create() { return new char('c'); } }; template<> struct TestValueFactory { static ulong *create() { return new ulong(0x12345678); } }; template<> struct TestValueFactory { static ushort *create() { return new ushort(0x1234); } }; template<> struct TestValueFactory { static uchar *create() { return new uchar('u'); } }; template<> struct TestValueFactory { static float *create() { return new float(3.14); } }; template<> struct TestValueFactory { static QObject * *create() { return new QObject *(0); } }; template<> struct TestValueFactory { static QWidget * *create() { return new QWidget *(0); } }; template<> struct TestValueFactory { static void * *create() { return new void *(0); } }; template<> struct TestValueFactory { static qlonglong *create() { return new qlonglong(0x12345678); } }; template<> struct TestValueFactory { static qulonglong *create() { return new qulonglong(0x12345678); } }; template<> struct TestValueFactory { static QStringList *create() { return new QStringList(QStringList() << "Q" << "t"); } }; template<> struct TestValueFactory { static QBitArray *create() { return new QBitArray(QBitArray(256, true)); } }; template<> struct TestValueFactory { static QDate *create() { return new QDate(QDate::currentDate()); } }; template<> struct TestValueFactory { static QTime *create() { return new QTime(QTime::currentTime()); } }; template<> struct TestValueFactory { static QDateTime *create() { return new QDateTime(QDateTime::currentDateTime()); } }; template<> struct TestValueFactory { static QUrl *create() { return new QUrl("http://www.example.org"); } }; template<> struct TestValueFactory { static QLocale *create() { return new QLocale(QLocale::c()); } }; template<> struct TestValueFactory { static QRect *create() { return new QRect(10, 20, 30, 40); } }; template<> struct TestValueFactory { static QRectF *create() { return new QRectF(10, 20, 30, 40); } }; template<> struct TestValueFactory { static QSize *create() { return new QSize(10, 20); } }; template<> struct TestValueFactory { static QSizeF *create() { return new QSizeF(10, 20); } }; template<> struct TestValueFactory { static QLine *create() { return new QLine(10, 20, 30, 40); } }; template<> struct TestValueFactory { static QLineF *create() { return new QLineF(10, 20, 30, 40); } }; template<> struct TestValueFactory { static QPoint *create() { return new QPoint(10, 20); } }; template<> struct TestValueFactory { static QPointF *create() { return new QPointF(10, 20); } }; template<> struct TestValueFactory { static QEasingCurve *create() { return new QEasingCurve(QEasingCurve::InOutElastic); } }; template<> struct TestValueFactory { static QUuid *create() { return new QUuid(); } }; template<> struct TestValueFactory { static QModelIndex *create() { return new QModelIndex(); } }; template<> struct TestValueFactory { static QRegExp *create() { #ifndef QT_NO_REGEXP return new QRegExp("A*"); #else return 0; #endif } }; template<> struct TestValueFactory { static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); } }; void tst_QMetaType::create_data() { QTest::addColumn("type"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ QTest::newRow(QMetaType::typeName(QMetaType::MetaTypeName)) << QMetaType::MetaTypeName; FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } template static void testCreateHelper() { typedef typename MetaEnumToType::Type Type; QMetaType info(ID); void *actual1 = QMetaType::create(ID); void *actual2 = info.create(); if (DefaultValueTraits::IsInitialized) { Type *expected = DefaultValueFactory::create(); QCOMPARE(*static_cast(actual1), *expected); QCOMPARE(*static_cast(actual2), *expected); delete expected; } QMetaType::destroy(ID, actual1); info.destroy(actual2); } template<> void testCreateHelper() { typedef MetaEnumToType::Type Type; void *actual = QMetaType::create(QMetaType::Void); if (DefaultValueTraits::IsInitialized) { QVERIFY(DefaultValueFactory::create()); } QMetaType::destroy(QMetaType::Void, actual); } typedef void (*TypeTestFunction)(); void tst_QMetaType::create() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CREATE_FUNCTION(MetaTypeName, MetaTypeId, RealType) \ case QMetaType::MetaTypeName: \ return testCreateHelper; FOR_EACH_CORE_METATYPE(RETURN_CREATE_FUNCTION) #undef RETURN_CREATE_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } template static void testCreateCopyHelper() { typedef typename MetaEnumToType::Type Type; Type *expected = TestValueFactory::create(); QMetaType info(ID); void *actual1 = QMetaType::create(ID, expected); void *actual2 = info.create(expected); QCOMPARE(*static_cast(actual1), *expected); QCOMPARE(*static_cast(actual2), *expected); QMetaType::destroy(ID, actual1); info.destroy(actual2); delete expected; } template<> void testCreateCopyHelper() { typedef MetaEnumToType::Type Type; Type *expected = TestValueFactory::create(); void *actual = QMetaType::create(QMetaType::Void, expected); QCOMPARE(static_cast(actual), expected); QMetaType::destroy(QMetaType::Void, actual); } void tst_QMetaType::createCopy_data() { create_data(); } void tst_QMetaType::createCopy() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CREATE_COPY_FUNCTION(MetaTypeName, MetaTypeId, RealType) \ case QMetaType::MetaTypeName: \ return testCreateCopyHelper; FOR_EACH_CORE_METATYPE(RETURN_CREATE_COPY_FUNCTION) #undef RETURN_CREATE_COPY_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } void tst_QMetaType::sizeOf_data() { QTest::addColumn("type"); QTest::addColumn("size"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ QTest::newRow(#RealType) << QMetaType::MetaTypeName << int(QTypeInfo::sizeOf); FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } void tst_QMetaType::sizeOf() { QFETCH(QMetaType::Type, type); QFETCH(int, size); QCOMPARE(QMetaType::sizeOf(type), size); } void tst_QMetaType::sizeOfStaticLess_data() { sizeOf_data(); } void tst_QMetaType::sizeOfStaticLess() { QFETCH(QMetaType::Type, type); QFETCH(int, size); QCOMPARE(QMetaType(type).sizeOf(), size); } struct CustomMovable {}; QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(CustomMovable, Q_MOVABLE_TYPE); QT_END_NAMESPACE Q_DECLARE_METATYPE(CustomMovable); class CustomObject : public QObject { Q_OBJECT public: CustomObject(QObject *parent = 0) : QObject(parent) { } }; Q_DECLARE_METATYPE(CustomObject*); struct SecondBase {}; class CustomMultiInheritanceObject : public QObject, SecondBase { Q_OBJECT public: CustomMultiInheritanceObject(QObject *parent = 0) : QObject(parent) { } }; Q_DECLARE_METATYPE(CustomMultiInheritanceObject*); class C { char _[4]; }; class M { char _[4]; }; class P { char _[4]; }; QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(M, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(P, Q_PRIMITIVE_TYPE); QT_END_NAMESPACE // avoid the comma: typedef QPair QPairCC; typedef QPair QPairCM; typedef QPair QPairCP; typedef QPair QPairMC; typedef QPair QPairMM; typedef QPair QPairMP; typedef QPair QPairPC; typedef QPair QPairPM; typedef QPair QPairPP; Q_DECLARE_METATYPE(QPairCC) Q_DECLARE_METATYPE(QPairCM) Q_DECLARE_METATYPE(QPairCP) Q_DECLARE_METATYPE(QPairMC) Q_DECLARE_METATYPE(QPairMM) Q_DECLARE_METATYPE(QPairMP) Q_DECLARE_METATYPE(QPairPC) Q_DECLARE_METATYPE(QPairPM) Q_DECLARE_METATYPE(QPairPP) void tst_QMetaType::flags_data() { QTest::addColumn("type"); QTest::addColumn("isMovable"); QTest::addColumn("isComplex"); QTest::addColumn("isPointerToQObject"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ QTest::newRow(#RealType) << MetaTypeId << bool(!QTypeInfo::isStatic) << bool(QTypeInfo::isComplex) << bool(QtPrivate::IsPointerToTypeDerivedFromQObject::Value); QT_FOR_EACH_STATIC_CORE_CLASS(ADD_METATYPE_TEST_ROW) QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(ADD_METATYPE_TEST_ROW) QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW QTest::newRow("TestSpace::Foo") << ::qMetaTypeId() << false << true << false; QTest::newRow("Whity") << ::qMetaTypeId >() << false << true << false; QTest::newRow("CustomMovable") << ::qMetaTypeId() << true << true << false; QTest::newRow("CustomObject*") << ::qMetaTypeId() << true << false << true; QTest::newRow("CustomMultiInheritanceObject*") << ::qMetaTypeId() << true << false << true; QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << true << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << true << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << true << true << false; QTest::newRow("QPair") << ::qMetaTypeId >() << true << false << false; } void tst_QMetaType::flags() { QFETCH(int, type); QFETCH(bool, isMovable); QFETCH(bool, isComplex); QFETCH(bool, isPointerToQObject); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsConstruction), isComplex); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsDestruction), isComplex); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::MovableType), isMovable); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::PointerToQObject), isPointerToQObject); } void tst_QMetaType::flagsStaticLess_data() { flags_data(); } void tst_QMetaType::flagsStaticLess() { QFETCH(int, type); QFETCH(bool, isMovable); QFETCH(bool, isComplex); int flags = QMetaType(type).flags(); QCOMPARE(bool(flags & QMetaType::NeedsConstruction), isComplex); QCOMPARE(bool(flags & QMetaType::NeedsDestruction), isComplex); QCOMPARE(bool(flags & QMetaType::MovableType), isMovable); } void tst_QMetaType::construct_data() { create_data(); } #ifndef Q_ALIGNOF template struct RoundToNextHighestPowerOfTwo { private: enum { V1 = N-1 }; enum { V2 = V1 | (V1 >> 1) }; enum { V3 = V2 | (V2 >> 2) }; enum { V4 = V3 | (V3 >> 4) }; enum { V5 = V4 | (V4 >> 8) }; enum { V6 = V5 | (V5 >> 16) }; public: enum { Value = V6 + 1 }; }; #endif template struct TypeAlignment { #ifdef Q_ALIGNOF enum { Value = Q_ALIGNOF(T) }; #else enum { Value = RoundToNextHighestPowerOfTwo::Value }; #endif }; template static void testConstructHelper() { typedef typename MetaEnumToType::Type Type; QMetaType info(ID); int size = info.sizeOf(); void *storage1 = qMallocAligned(size, TypeAlignment::Value); void *actual1 = QMetaType::construct(ID, storage1, /*copy=*/0); void *storage2 = qMallocAligned(size, TypeAlignment::Value); void *actual2 = info.construct(storage2, /*copy=*/0); QCOMPARE(actual1, storage1); QCOMPARE(actual2, storage2); if (DefaultValueTraits::IsInitialized) { Type *expected = DefaultValueFactory::create(); QCOMPARE(*static_cast(actual1), *expected); QCOMPARE(*static_cast(actual2), *expected); delete expected; } QMetaType::destruct(ID, actual1); qFreeAligned(storage1); info.destruct(actual2); qFreeAligned(storage2); QVERIFY(QMetaType::construct(ID, 0, /*copy=*/0) == 0); QMetaType::destruct(ID, 0); QVERIFY(info.construct(0, /*copy=*/0) == 0); info.destruct(0); } template<> void testConstructHelper() { typedef MetaEnumToType::Type Type; /*int size = */ QMetaType::sizeOf(QMetaType::Void); void *storage = 0; void *actual = QMetaType::construct(QMetaType::Void, storage, /*copy=*/0); QCOMPARE(actual, storage); if (DefaultValueTraits::IsInitialized) { /*Type *expected = */ DefaultValueFactory::create(); } QMetaType::destruct(QMetaType::Void, actual); qFreeAligned(storage); QVERIFY(QMetaType::construct(QMetaType::Void, 0, /*copy=*/0) == 0); QMetaType::destruct(QMetaType::Void, 0); } void tst_QMetaType::construct() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CONSTRUCT_FUNCTION(MetaTypeName, MetaTypeId, RealType) \ case QMetaType::MetaTypeName: \ return testConstructHelper; FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_FUNCTION) #undef RETURN_CONSTRUCT_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } template static void testConstructCopyHelper() { typedef typename MetaEnumToType::Type Type; Type *expected = TestValueFactory::create(); QMetaType info(ID); int size = QMetaType::sizeOf(ID); QCOMPARE(info.sizeOf(), size); void *storage1 = qMallocAligned(size, TypeAlignment::Value); void *actual1 = QMetaType::construct(ID, storage1, expected); void *storage2 = qMallocAligned(size, TypeAlignment::Value); void *actual2 = info.construct(storage2, expected); QCOMPARE(actual1, storage1); QCOMPARE(actual2, storage2); QCOMPARE(*static_cast(actual1), *expected); QCOMPARE(*static_cast(actual2), *expected); QMetaType::destruct(ID, actual1); qFreeAligned(storage1); info.destruct(actual2); qFreeAligned(storage2); QVERIFY(QMetaType::construct(ID, 0, expected) == 0); QVERIFY(info.construct(0, expected) == 0); delete expected; } template<> void testConstructCopyHelper() { typedef MetaEnumToType::Type Type; Type *expected = TestValueFactory::create(); /* int size = */QMetaType::sizeOf(QMetaType::Void); void *storage = 0; void *actual = QMetaType::construct(QMetaType::Void, storage, expected); QCOMPARE(actual, storage); QMetaType::destruct(QMetaType::Void, actual); qFreeAligned(storage); QVERIFY(QMetaType::construct(QMetaType::Void, 0, expected) == 0); } void tst_QMetaType::constructCopy_data() { create_data(); } void tst_QMetaType::constructCopy() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CONSTRUCT_COPY_FUNCTION(MetaTypeName, MetaTypeId, RealType) \ case QMetaType::MetaTypeName: \ return testConstructCopyHelper; FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION) #undef RETURN_CONSTRUCT_COPY_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } typedef QString CustomString; Q_DECLARE_METATYPE(CustomString) //this line is useless void tst_QMetaType::typedefs() { QCOMPARE(QMetaType::type("long long"), int(QMetaType::LongLong)); QCOMPARE(QMetaType::type("unsigned long long"), int(QMetaType::ULongLong)); QCOMPARE(QMetaType::type("qint8"), int(QMetaType::Char)); QCOMPARE(QMetaType::type("quint8"), int(QMetaType::UChar)); QCOMPARE(QMetaType::type("qint16"), int(QMetaType::Short)); QCOMPARE(QMetaType::type("quint16"), int(QMetaType::UShort)); QCOMPARE(QMetaType::type("qint32"), int(QMetaType::Int)); QCOMPARE(QMetaType::type("quint32"), int(QMetaType::UInt)); QCOMPARE(QMetaType::type("qint64"), int(QMetaType::LongLong)); QCOMPARE(QMetaType::type("quint64"), int(QMetaType::ULongLong)); // make sure the qreal typeId is the type id of the type it's defined to QCOMPARE(QMetaType::type("qreal"), ::qMetaTypeId()); qRegisterMetaType("CustomString"); QCOMPARE(QMetaType::type("CustomString"), ::qMetaTypeId()); typedef Whity WhityDouble; qRegisterMetaType("WhityDouble"); QCOMPARE(QMetaType::type("WhityDouble"), ::qMetaTypeId()); } void tst_QMetaType::registerType() { // Built-in QCOMPARE(qRegisterMetaType("QString"), int(QMetaType::QString)); QCOMPARE(qRegisterMetaType("QString"), int(QMetaType::QString)); // Custom int fooId = qRegisterMetaType("TestSpace::Foo"); QVERIFY(fooId >= int(QMetaType::User)); QCOMPARE(qRegisterMetaType("TestSpace::Foo"), fooId); int movableId = qRegisterMetaType("CustomMovable"); QVERIFY(movableId >= int(QMetaType::User)); QCOMPARE(qRegisterMetaType("CustomMovable"), movableId); // Alias to built-in typedef QString MyString; QCOMPARE(qRegisterMetaType("MyString"), int(QMetaType::QString)); QCOMPARE(qRegisterMetaType("MyString"), int(QMetaType::QString)); QCOMPARE(QMetaType::type("MyString"), int(QMetaType::QString)); // Alias to custom type typedef CustomMovable MyMovable; typedef TestSpace::Foo MyFoo; QCOMPARE(qRegisterMetaType("MyMovable"), movableId); QCOMPARE(qRegisterMetaType("MyMovable"), movableId); QCOMPARE(QMetaType::type("MyMovable"), movableId); QCOMPARE(qRegisterMetaType("MyFoo"), fooId); QCOMPARE(qRegisterMetaType("MyFoo"), fooId); QCOMPARE(QMetaType::type("MyFoo"), fooId); } class IsRegisteredDummyType { }; void tst_QMetaType::isRegistered_data() { QTest::addColumn("typeId"); QTest::addColumn("registered"); // predefined/custom types QTest::newRow("QMetaType::Void") << int(QMetaType::Void) << true; QTest::newRow("QMetaType::Int") << int(QMetaType::Int) << true; int dummyTypeId = qRegisterMetaType("IsRegisteredDummyType"); QTest::newRow("IsRegisteredDummyType") << dummyTypeId << true; // unknown types QTest::newRow("-1") << -1 << false; QTest::newRow("-42") << -42 << false; QTest::newRow("IsRegisteredDummyType + 1") << (dummyTypeId + 1) << false; } void tst_QMetaType::isRegistered() { QFETCH(int, typeId); QFETCH(bool, registered); QCOMPARE(QMetaType::isRegistered(typeId), registered); } void tst_QMetaType::isRegisteredStaticLess_data() { isRegistered_data(); } void tst_QMetaType::isRegisteredStaticLess() { QFETCH(int, typeId); QFETCH(bool, registered); QCOMPARE(QMetaType(typeId).isRegistered(), registered); } void tst_QMetaType::registerStreamBuiltin() { //should not crash; qRegisterMetaTypeStreamOperators("QString"); qRegisterMetaTypeStreamOperators("QVariant"); } Q_DECLARE_METATYPE(QSharedPointer) typedef QHash IntUIntHash; Q_DECLARE_METATYPE(IntUIntHash) typedef QMap IntUIntMap; Q_DECLARE_METATYPE(IntUIntMap) typedef QPair IntUIntPair; Q_DECLARE_METATYPE(IntUIntPair) struct CustomComparable { CustomComparable(int i_ = 0) :i(i_) { } bool operator==(const CustomComparable &other) const { return i == other.i; } int i; }; struct UnregisteredType {}; typedef QHash IntComparableHash; Q_DECLARE_METATYPE(IntComparableHash) typedef QMap IntComparableMap; Q_DECLARE_METATYPE(IntComparableMap) typedef QPair IntComparablePair; Q_DECLARE_METATYPE(IntComparablePair) typedef QHash IntIntHash; typedef int NaturalNumber; class AutoMetaTypeObject : public QObject { Q_OBJECT Q_PROPERTY(IntIntHash someHash READ someHash CONSTANT) Q_PROPERTY(NaturalNumber someInt READ someInt CONSTANT) public: AutoMetaTypeObject(QObject *parent = 0) : QObject(parent), m_int(42) { m_hash.insert(4, 2); } QHash someHash() const { return m_hash; } int someInt() const { return m_int; } private: QHash m_hash; int m_int; }; void tst_QMetaType::automaticTemplateRegistration() { { QList intList; intList << 42; QVERIFY(QVariant::fromValue(intList).value >().first() == 42); QVector > vectorList; vectorList << intList; QVERIFY(QVariant::fromValue(vectorList).value > >().first().first() == 42); } { QList bytearrayList; bytearrayList << QByteArray("foo"); QVERIFY(QVariant::fromValue(bytearrayList).value >().first() == QByteArray("foo")); QVector > vectorList; vectorList << bytearrayList; QVERIFY(QVariant::fromValue(vectorList).value > >().first().first() == QByteArray("foo")); } QCOMPARE(::qMetaTypeId(), (int)QMetaType::QVariantList); QCOMPARE(::qMetaTypeId >(), (int)QMetaType::QVariantList); { QList variantList; variantList << 42; QVERIFY(QVariant::fromValue(variantList).value >().first() == 42); QVector > vectorList; vectorList << variantList; QVERIFY(QVariant::fromValue(vectorList).value > >().first().first() == 42); } { QList > sharedPointerList; QObject *testObject = new QObject; sharedPointerList << QSharedPointer(testObject); QVERIFY(QVariant::fromValue(sharedPointerList).value > >().first() == testObject); QVector > > vectorList; vectorList << sharedPointerList; QVERIFY(QVariant::fromValue(vectorList).value > > >().first().first() == testObject); } { IntIntHash intIntHash; intIntHash.insert(4, 2); QCOMPARE(QVariant::fromValue(intIntHash).value().value(4), 2); AutoMetaTypeObject amto; qRegisterMetaType >("IntIntHash"); QVariant hashVariant = amto.property("someHash"); QCOMPARE(hashVariant.value().value(4), 2); qRegisterMetaType("NaturalNumber"); QVariant intVariant = amto.property("someInt"); QCOMPARE(intVariant.value(), 42); } { IntUIntHash intUIntHash; intUIntHash.insert(4, 2); QCOMPARE(QVariant::fromValue(intUIntHash).value().value(4), (uint)2); } { IntComparableHash intComparableHash; CustomComparable m; intComparableHash.insert(4, m); QCOMPARE(QVariant::fromValue(intComparableHash).value().value(4), m); } { QVariantHash variantHash; variantHash.insert(QStringLiteral("4"), 2); QCOMPARE(QVariant::fromValue(variantHash).value().value(QStringLiteral("4")), QVariant(2)); } { typedef QMap IntIntMap; IntIntMap intIntMap; intIntMap.insert(4, 2); QCOMPARE(QVariant::fromValue(intIntMap).value().value(4), 2); } { IntUIntMap intUIntMap; intUIntMap.insert(4, 2); QCOMPARE(QVariant::fromValue(intUIntMap).value().value(4), (uint)2); } { IntComparableMap intComparableMap; CustomComparable m; intComparableMap.insert(4, m); QCOMPARE(QVariant::fromValue(intComparableMap).value().value(4), m); } { QVariantMap variantMap; variantMap.insert(QStringLiteral("4"), 2); QCOMPARE(QVariant::fromValue(variantMap).value().value(QStringLiteral("4")), QVariant(2)); } { typedef QPair IntIntPair; IntIntPair intIntPair = qMakePair(4, 2); QCOMPARE(QVariant::fromValue(intIntPair).value().first, 4); QCOMPARE(QVariant::fromValue(intIntPair).value().second, 2); } { IntUIntPair intUIntPair = qMakePair(4, 2); QCOMPARE(QVariant::fromValue(intUIntPair).value().first, 4); QCOMPARE(QVariant::fromValue(intUIntPair).value().second, (uint)2); } { CustomComparable m; IntComparablePair intComparablePair = qMakePair(4, m); QCOMPARE(QVariant::fromValue(intComparablePair).value().first, 4); QCOMPARE(QVariant::fromValue(intComparablePair).value().second, m); } { typedef QHash IntUnregisteredTypeHash; QVERIFY(qRegisterMetaType("IntUnregisteredTypeHash") > 0); } { typedef QList UnregisteredTypeList; QVERIFY(qRegisterMetaType("UnregisteredTypeList") > 0); } } // Compile-time test, it should be possible to register function pointer types class Undefined; typedef Undefined (*UndefinedFunction0)(); typedef Undefined (*UndefinedFunction1)(Undefined); typedef Undefined (*UndefinedFunction2)(Undefined, Undefined); typedef Undefined (*UndefinedFunction3)(Undefined, Undefined, Undefined); Q_DECLARE_METATYPE(UndefinedFunction0); Q_DECLARE_METATYPE(UndefinedFunction1); Q_DECLARE_METATYPE(UndefinedFunction2); Q_DECLARE_METATYPE(UndefinedFunction3); QTEST_MAIN(tst_QMetaType) #include "tst_qmetatype.moc"