/**************************************************************************** ** ** 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 #include #include Q_DECLARE_METATYPE(QMetaType::Type) class tst_QGuiMetaType: public QObject { Q_OBJECT private slots: void create_data(); void create(); void createCopy_data(); void createCopy(); void sizeOf_data(); void sizeOf(); void flags_data(); void flags(); void construct_data(); void construct(); void constructCopy_data(); void constructCopy(); void saveAndLoadBuiltin_data(); void saveAndLoadBuiltin(); }; #define FOR_EACH_GUI_METATYPE_BASE(F) \ F(QFont, QFont) \ F(QPixmap, QPixmap) \ F(QBrush, QBrush) \ F(QColor, QColor) \ F(QPalette, QPalette) \ F(QImage, QImage) \ F(QPolygon, QPolygon) \ F(QRegion, QRegion) \ F(QBitmap, QBitmap) \ F(QKeySequence, QKeySequence) \ F(QPen, QPen) \ F(QTextLength, QTextLength) \ F(QTextFormat, QTextFormat) \ F(QTransform, QTransform) \ F(QMatrix4x4, QMatrix4x4) \ F(QVector2D, QVector2D) \ F(QVector3D, QVector3D) \ F(QVector4D, QVector4D) \ F(QQuaternion, QQuaternion) #ifndef QT_NO_CURSOR # define FOR_EACH_GUI_METATYPE(F) \ FOR_EACH_GUI_METATYPE_BASE(F) \ F(QCursor, QCursor) #else // !QT_NO_CURSOR # define FOR_EACH_GUI_METATYPE(F) \ FOR_EACH_GUI_METATYPE_BASE(F) #endif // !QT_NO_CURSOR namespace { template struct static_assert_trigger { static_assert(( QMetaTypeId2::IsBuiltIn )); enum { value = true }; }; } #define CHECK_BUILTIN(TYPE, ID) static_assert_trigger< TYPE >::value && static_assert(( FOR_EACH_GUI_METATYPE(CHECK_BUILTIN) true )); #undef CHECK_BUILTIN static_assert((!QMetaTypeId2 >::IsBuiltIn)); static_assert((!QMetaTypeId2 >::IsBuiltIn)); template struct MetaEnumToType {}; #define DEFINE_META_ENUM_TO_TYPE(TYPE, ID) \ template<> \ struct MetaEnumToType { \ typedef TYPE Type; \ }; FOR_EACH_GUI_METATYPE(DEFINE_META_ENUM_TO_TYPE) #undef DEFINE_META_ENUM_TO_TYPE // Not all types have operator== template struct TypeComparator { typedef typename MetaEnumToType::Type Type; static bool equal(const Type &v1, const Type &v2) { return v1 == v2; } }; template<> struct TypeComparator { static bool equal(const QPixmap &v1, const QPixmap &v2) { return v1.size() == v2.size(); } }; template<> struct TypeComparator { static bool equal(const QBitmap &v1, const QBitmap &v2) { return v1.size() == v2.size(); } }; #ifndef QT_NO_CURSOR template<> struct TypeComparator { static bool equal(const QCursor &v1, const QCursor &v2) { return v1.shape() == v2.shape(); } }; #endif template struct DefaultValueFactory { typedef typename MetaEnumToType::Type Type; static Type *create() { return new Type; } }; template struct TestValueFactory {}; template<> struct TestValueFactory { static QFont *create() { return new QFont("Arial"); } }; template<> struct TestValueFactory { static QPixmap *create() { return new QPixmap(16, 32); } }; template<> struct TestValueFactory { static QBrush *create() { return new QBrush(Qt::SolidPattern); } }; template<> struct TestValueFactory { static QColor *create() { return new QColor(Qt::blue); } }; template<> struct TestValueFactory { static QPalette *create() { return new QPalette(Qt::yellow, Qt::green); } }; template<> struct TestValueFactory { static QImage *create() { return new QImage(16, 32, QImage::Format_ARGB32_Premultiplied); } }; template<> struct TestValueFactory { static QPolygon *create() { return new QPolygon(QRect(10, 20, 30, 40), true); } }; template<> struct TestValueFactory { static QRegion *create() { return new QRegion(QRect(10, 20, 30, 40), QRegion::Ellipse); } }; template<> struct TestValueFactory { static QBitmap *create() { return new QBitmap(16, 32); } }; #ifndef QT_NO_CURSOR template<> struct TestValueFactory { static QCursor *create() { return new QCursor(Qt::WaitCursor); } }; #endif #if QT_CONFIG(shortcut) template<> struct TestValueFactory { static QKeySequence *create() { return new QKeySequence(QKeySequence::Close); } }; #endif template<> struct TestValueFactory { static QPen *create() { return new QPen(Qt::DashDotDotLine); } }; template<> struct TestValueFactory { static QTextLength *create() { return new QTextLength(QTextLength::PercentageLength, 50); } }; template<> struct TestValueFactory { static QTextFormat *create() { return new QTextFormat(QTextFormat::FrameFormat); } }; template<> struct TestValueFactory { static QTransform *create() { return new QTransform(10, 20, 30, 40, 50, 60); } }; template<> struct TestValueFactory { static QMatrix4x4 *create() { return new QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); } }; template<> struct TestValueFactory { static QVector2D *create() { return new QVector2D(10, 20); } }; template<> struct TestValueFactory { static QVector3D *create() { return new QVector3D(10, 20, 30); } }; template<> struct TestValueFactory { static QVector4D *create() { return new QVector4D(10, 20, 30, 40); } }; template<> struct TestValueFactory { static QQuaternion *create() { return new QQuaternion(10, 20, 30, 40); } }; void tst_QGuiMetaType::create_data() { QTest::addColumn("type"); #define ADD_METATYPE_TEST_ROW(TYPE, ID) \ QTest::newRow(QMetaType(QMetaType::ID).name()) << QMetaType::ID; FOR_EACH_GUI_METATYPE(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } template static void testCreateHelper() { typedef typename MetaEnumToType::Type Type; void *actual = QMetaType(ID).create(); Type *expected = DefaultValueFactory::create(); QVERIFY(TypeComparator::equal(*static_cast(actual), *expected)); delete expected; QMetaType(ID).destroy(actual); } typedef void (*TypeTestFunction)(); void tst_QGuiMetaType::create() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CREATE_FUNCTION(TYPE, ID) \ case QMetaType::ID: \ return testCreateHelper; FOR_EACH_GUI_METATYPE(RETURN_CREATE_FUNCTION) #undef RETURN_CREATE_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } void tst_QGuiMetaType::createCopy_data() { create_data(); } template static void testCreateCopyHelper() { typedef typename MetaEnumToType::Type Type; Type *expected = TestValueFactory::create(); void *actual = QMetaType(ID).create(expected); QVERIFY(TypeComparator::equal(*static_cast(actual), *expected)); QMetaType(ID).destroy(actual); delete expected; } void tst_QGuiMetaType::createCopy() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CREATE_COPY_FUNCTION(TYPE, ID) \ case QMetaType::ID: \ return testCreateCopyHelper; FOR_EACH_GUI_METATYPE(RETURN_CREATE_COPY_FUNCTION) #undef RETURN_CREATE_COPY_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } void tst_QGuiMetaType::sizeOf_data() { QTest::addColumn("type"); QTest::addColumn("size"); #define ADD_METATYPE_TEST_ROW(TYPE, ID) \ QTest::newRow(QMetaType(QMetaType::ID).name()) << QMetaType::ID << int(sizeof(TYPE)); FOR_EACH_GUI_METATYPE(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } void tst_QGuiMetaType::sizeOf() { QFETCH(QMetaType::Type, type); QFETCH(int, size); QCOMPARE(QMetaType(type).sizeOf(), size); } template struct TypeAlignment { enum { Value = alignof(T) }; }; void tst_QGuiMetaType::flags_data() { QTest::addColumn("type"); QTest::addColumn("isRelocatable"); QTest::addColumn("isComplex"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ QTest::newRow(#RealType) << MetaTypeId << bool(QTypeInfoQuery::isRelocatable) << bool(QTypeInfoQuery::isComplex); QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } void tst_QGuiMetaType::flags() { QFETCH(int, type); QFETCH(bool, isRelocatable); QFETCH(bool, isComplex); QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsConstruction), isComplex); QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsDestruction), isComplex); QCOMPARE(bool(QMetaType(type).flags() & QMetaType::MovableType), isRelocatable); } void tst_QGuiMetaType::construct_data() { create_data(); } template static void testConstructHelper() { typedef typename MetaEnumToType::Type Type; int size = QMetaType(ID).sizeOf(); void *storage = qMallocAligned(size, TypeAlignment::Value); void *actual = QMetaType(ID).construct(storage, /*copy=*/0); QCOMPARE(actual, storage); Type *expected = DefaultValueFactory::create(); QVERIFY2(TypeComparator::equal(*static_cast(actual), *expected), QMetaType(ID).name()); delete expected; QMetaType(ID).destruct(actual); qFreeAligned(storage); } void tst_QGuiMetaType::construct() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CONSTRUCT_FUNCTION(TYPE, ID) \ case QMetaType::ID: \ return testConstructHelper; FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_FUNCTION) #undef RETURN_CONSTRUCT_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } void tst_QGuiMetaType::constructCopy_data() { create_data(); } template static void testConstructCopyHelper() { typedef typename MetaEnumToType::Type Type; Type *expected = TestValueFactory::create(); int size = QMetaType(ID).sizeOf(); void *storage = qMallocAligned(size, TypeAlignment::Value); void *actual = QMetaType(ID).construct(storage, expected); QCOMPARE(actual, storage); QVERIFY2(TypeComparator::equal(*static_cast(actual), *expected), QMetaType(ID).name()); QMetaType(ID).destruct(actual); qFreeAligned(storage); delete expected; } void tst_QGuiMetaType::constructCopy() { struct TypeTestFunctionGetter { static TypeTestFunction get(int type) { switch (type) { #define RETURN_CONSTRUCT_COPY_FUNCTION(TYPE, ID) \ case QMetaType::ID: \ return testConstructCopyHelper; FOR_EACH_GUI_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION) #undef RETURN_CONSTRUCT_COPY_FUNCTION } return 0; } }; QFETCH(QMetaType::Type, type); TypeTestFunctionGetter::get(type)(); } template struct StreamingTraits { // Streamable by default, as currently all gui built-in types are streamable enum { isStreamable = 1 }; }; void tst_QGuiMetaType::saveAndLoadBuiltin_data() { QTest::addColumn("type"); QTest::addColumn("isStreamable"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ QTest::newRow(#RealType) << MetaTypeId << bool(StreamingTraits::isStreamable); QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } void tst_QGuiMetaType::saveAndLoadBuiltin() { QFETCH(int, type); QFETCH(bool, isStreamable); void *value = QMetaType(type).create(); QByteArray ba; QDataStream stream(&ba, QIODevice::ReadWrite); QCOMPARE(QMetaType(type).save(stream, value), isStreamable); QCOMPARE(stream.status(), QDataStream::Ok); if (isStreamable) QVERIFY(QMetaType(type).load(stream, value)); stream.device()->seek(0); stream.resetStatus(); QCOMPARE(QMetaType(type).load(stream, value), isStreamable); QCOMPARE(stream.status(), QDataStream::Ok); if (isStreamable) QVERIFY(QMetaType(type).load(stream, value)); QMetaType(type).destroy(value); } QTEST_MAIN(tst_QGuiMetaType) #include "tst_qguimetatype.moc"