diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-02-07 11:45:06 +0100 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-02-09 14:27:20 +0100 |
commit | 85416ae6fd9da00540e471e5b0864a3e1678f423 (patch) | |
tree | 6d637033fac75defdc83a44de93f3d2f8b14a45f /tests/auto | |
parent | 2861cfb6f851d7cee503b19f0e800a33374db66c (diff) |
Split up the QMetaType unit test
gcc 9 consumed enourmous amounts of memory building the test, regularly
dying on a VM with 4GB RAM. Splitting it up helps.
As a drive-by, use inline static variables, and rename the header used by
other tests to tst_qmetatype_common.h.
Change-Id: Ib716d8e3506aac6c87845e57b04cb1a4f6c68387
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto')
7 files changed, 969 insertions, 915 deletions
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index 9fd7b255d7..732d81d84a 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -45,7 +45,7 @@ #include <QtCore> #include <QtGui> -#include "tst_qmetatype.h" +#include "tst_qmetatype_common.h" #include <cctype> #include <stdlib.h> diff --git a/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt b/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt index d3e576127f..49fcecebc3 100644 --- a/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt +++ b/tests/auto/corelib/kernel/qmetatype/CMakeLists.txt @@ -9,7 +9,7 @@ list(APPEND test_data "./typeFlags.bin") qt_internal_add_test(tst_qmetatype SOURCES - tst_qmetatype.cpp + tst_qmetatype.h tst_qmetatype.cpp tst_qmetatype2.cpp DEFINES QT_DISABLE_DEPRECATED_BEFORE=0 INCLUDE_DIRECTORIES diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 1978e9e1b7..81a67f1b78 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -26,14 +26,10 @@ ** ****************************************************************************/ +#include "tst_qmetatype.h" -#include <QtCore> -#include <QTest> #include <QtCore/private/qmetaobjectbuilder_p.h> -#include "tst_qmetatype.h" -#include "tst_qvariant_common.h" - #ifdef Q_OS_LINUX # include <pthread.h> #endif @@ -153,91 +149,6 @@ static_assert(!QTypeTraits::has_operator_less_than_v<std::tuple<int, Nested2>>); } - -class tst_QMetaType: public QObject -{ - Q_OBJECT - Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp) - -public: - struct GadgetPropertyType { - QByteArray type; - QByteArray name; - QVariant testData; - }; - - tst_QMetaType() { propList << 42 << "Hello"; } - - QList<QVariant> prop() const { return propList; } - void setProp(const QList<QVariant> &list) { propList = list; } - -private: - void registerGadget(const char * name, const QList<GadgetPropertyType> &gadgetProperties); - QList<QVariant> propList; - -private slots: - void defined(); - void threadSafety(); - void namespaces(); - void id(); - void qMetaTypeId(); - void properties(); - void normalizedTypes(); - void typeName_data(); - void typeName(); - void type_data(); - void type(); - void type_fromSubString_data(); - void type_fromSubString(); - void create_data(); - void create(); - void createCopy_data(); - void createCopy(); - void sizeOf_data(); - void sizeOf(); - void sizeOfStaticLess_data(); - void sizeOfStaticLess(); - void alignOf_data(); - void alignOf(); - void flags_data(); - void flags(); - void flagsStaticLess_data(); - void flagsStaticLess(); - void flagsBinaryCompatibility6_0_data(); - void flagsBinaryCompatibility6_0(); - void construct_data(); - void construct(); - void typedConstruct(); - void constructCopy_data(); - void constructCopy(); - void typedefs(); - void registerType(); - void isRegistered_data(); - void isRegistered(); - void isRegisteredStaticLess_data(); - void isRegisteredStaticLess(); - void isEnum(); - void automaticTemplateRegistration(); - void saveAndLoadBuiltin_data(); - void saveAndLoadBuiltin(); - void saveAndLoadCustom(); - void metaObject_data(); - void metaObject(); - void constexprMetaTypeIds(); - void constRefs(); - void convertCustomType_data(); - void convertCustomType(); - void compareCustomEqualOnlyType(); - void customDebugStream(); - void unknownType(); - void fromType(); - void operatorEq_data(); - void operatorEq(); - void typesWithInaccessibleDTors(); - void voidIsNotUnknown(); - void typeNameNormalization(); -}; - struct BaseGenericType { int m_typeId = -1; @@ -647,18 +558,6 @@ void tst_QMetaType::properties() QCOMPARE(v.toList().count(), 4); } -template <typename T> -struct Whity { T t; Whity() {} }; - -Q_DECLARE_METATYPE( Whity < int > ) -Q_DECLARE_METATYPE(Whity<double>) - -#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501 -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(Whity<double>, Q_RELOCATABLE_TYPE); -QT_END_NAMESPACE -#endif - void tst_QMetaType::normalizedTypes() { int WhityIntId = ::qMetaTypeId<Whity<int> >(); @@ -1011,20 +910,6 @@ void tst_QMetaType::alignOf() QCOMPARE(size_t(QMetaType(type).alignOf()), size); } -struct CustomMovable { CustomMovable() {} }; - -// needed for QSet<CustomMovable>. We actually check that it makes sense. -bool operator==(const CustomMovable &, const CustomMovable &) { return true; } -qsizetype qHash(const CustomMovable &, qsizetype seed = 0) { return seed; } - -#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501 -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(CustomMovable, Q_RELOCATABLE_TYPE); -QT_END_NAMESPACE -#endif - -Q_DECLARE_METATYPE(CustomMovable); - class CustomObject : public QObject { Q_OBJECT @@ -2234,549 +2119,5 @@ void tst_QMetaType::constexprMetaTypeIds() Q_UNUSED(metaType); } -void tst_QMetaType::constRefs() -{ - QCOMPARE(::qMetaTypeId<const int &>(), ::qMetaTypeId<int>()); - QCOMPARE(::qMetaTypeId<const QString &>(), ::qMetaTypeId<QString>()); - QCOMPARE(::qMetaTypeId<const CustomMovable &>(), ::qMetaTypeId<CustomMovable>()); - QCOMPARE(::qMetaTypeId<const QList<CustomMovable> &>(), ::qMetaTypeId<QList<CustomMovable> >()); - static_assert(::qMetaTypeId<const int &>() == ::qMetaTypeId<int>()); -} - -struct CustomConvertibleType -{ - explicit CustomConvertibleType(const QVariant &foo = QVariant()) : m_foo(foo) {} - virtual ~CustomConvertibleType() {} - QString toString() const { return m_foo.toString(); } - operator QPoint() const { return QPoint(12, 34); } - template<typename To> - To convert() const { return s_value.value<To>();} - template<typename To> - To convertOk(bool *ok) const { *ok = s_ok; return s_value.value<To>();} - - QVariant m_foo; - static QVariant s_value; - static bool s_ok; -}; - -bool operator<(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs) -{ return lhs.m_foo.toString() < rhs.m_foo.toString(); } -bool operator==(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs) -{ return lhs.m_foo == rhs.m_foo; } -bool operator!=(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs) -{ return !operator==(lhs, rhs); } - -QVariant CustomConvertibleType::s_value; -bool CustomConvertibleType::s_ok = true; - -struct CustomConvertibleType2 -{ - // implicit - CustomConvertibleType2(const CustomConvertibleType &t = CustomConvertibleType()) - : m_foo(t.m_foo) {} - virtual ~CustomConvertibleType2() {} - - QVariant m_foo; -}; - -struct CustomDebugStreamableType -{ - QString toString() const { return "test"; } -}; - -struct CustomDebugStreamableType2 -{ - QString toString() const { return "test"; } -}; - -QDebug operator<<(QDebug dbg, const CustomDebugStreamableType&) -{ - return dbg << "string-content"; -} - -bool operator==(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs) -{ return lhs.m_foo == rhs.m_foo; } -bool operator!=(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs) -{ return !operator==(lhs, rhs); } - - -struct CustomEqualsOnlyType -{ - explicit CustomEqualsOnlyType(int value = 0) : val(value) {} - virtual ~CustomEqualsOnlyType() {} - - int val; -}; -bool operator==(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs) -{ return lhs.val == rhs.val;} -bool operator!=(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs) -{ return !operator==(lhs, rhs); } - -static_assert(QTypeTraits::has_operator_equal_v<CustomEqualsOnlyType>); -static_assert(!QTypeTraits::has_operator_less_than_v<CustomEqualsOnlyType>); - -Q_DECLARE_METATYPE(CustomConvertibleType); -Q_DECLARE_METATYPE(CustomConvertibleType2); -Q_DECLARE_METATYPE(CustomDebugStreamableType); -Q_DECLARE_METATYPE(CustomEqualsOnlyType); - -template<typename T, typename U> -U convert(const T &t) -{ - return t; -} - -template<typename From> -struct ConvertFunctor -{ - CustomConvertibleType operator()(const From& f) const - { - return CustomConvertibleType(QVariant::fromValue(f)); - } -}; - -template<typename From, typename To> -bool hasRegisteredConverterFunction() -{ - return QMetaType::hasRegisteredConverterFunction<From, To>(); -} - -template<typename From, typename To> -void testCustomTypeNotYetConvertible() -{ - QVERIFY((!hasRegisteredConverterFunction<From, To>())); - QVERIFY((!QVariant::fromValue<From>(From()).template canConvert<To>())); -} - -template<typename From, typename To> -void testCustomTypeConvertible() -{ - QVERIFY((hasRegisteredConverterFunction<From, To>())); - QVERIFY((QVariant::fromValue<From>(From()).template canConvert<To>())); -} - -void customTypeNotYetConvertible() -{ - testCustomTypeNotYetConvertible<CustomConvertibleType, QString>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, bool>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, int>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, double>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, float>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QRect>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QRectF>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QPoint>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QPointF>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QSize>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QSizeF>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QLine>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QLineF>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, QChar>(); - testCustomTypeNotYetConvertible<QString, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<bool, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<int, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<double, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<float, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QRect, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QRectF, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QPoint, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QPointF, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QSize, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QSizeF, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QLine, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QLineF, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<QChar, CustomConvertibleType>(); - testCustomTypeNotYetConvertible<CustomConvertibleType, CustomConvertibleType2>(); -} - -void registerCustomTypeConversions() -{ - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QString>(&CustomConvertibleType::convertOk<QString>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, bool>(&CustomConvertibleType::convert<bool>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, int>(&CustomConvertibleType::convertOk<int>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, double>(&CustomConvertibleType::convert<double>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, float>(&CustomConvertibleType::convertOk<float>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QRect>(&CustomConvertibleType::convert<QRect>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QRectF>(&CustomConvertibleType::convertOk<QRectF>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QPoint>(convert<CustomConvertibleType,QPoint>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QPointF>(&CustomConvertibleType::convertOk<QPointF>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QSize>(&CustomConvertibleType::convert<QSize>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QSizeF>(&CustomConvertibleType::convertOk<QSizeF>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLine>(&CustomConvertibleType::convert<QLine>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLineF>(&CustomConvertibleType::convertOk<QLineF>))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QChar>(&CustomConvertibleType::convert<QChar>))); - QVERIFY((QMetaType::registerConverter<QString, CustomConvertibleType>(ConvertFunctor<QString>()))); - QVERIFY((QMetaType::registerConverter<bool, CustomConvertibleType>(ConvertFunctor<bool>()))); - QVERIFY((QMetaType::registerConverter<int, CustomConvertibleType>(ConvertFunctor<int>()))); - QVERIFY((QMetaType::registerConverter<double, CustomConvertibleType>(ConvertFunctor<double>()))); - QVERIFY((QMetaType::registerConverter<float, CustomConvertibleType>(ConvertFunctor<float>()))); - QVERIFY((QMetaType::registerConverter<QRect, CustomConvertibleType>(ConvertFunctor<QRect>()))); - QVERIFY((QMetaType::registerConverter<QRectF, CustomConvertibleType>(ConvertFunctor<QRectF>()))); - QVERIFY((QMetaType::registerConverter<QPoint, CustomConvertibleType>(ConvertFunctor<QPoint>()))); - QVERIFY((QMetaType::registerConverter<QPointF, CustomConvertibleType>(ConvertFunctor<QPointF>()))); - QVERIFY((QMetaType::registerConverter<QSize, CustomConvertibleType>(ConvertFunctor<QSize>()))); - QVERIFY((QMetaType::registerConverter<QSizeF, CustomConvertibleType>(ConvertFunctor<QSizeF>()))); - QVERIFY((QMetaType::registerConverter<QLine, CustomConvertibleType>(ConvertFunctor<QLine>()))); - QVERIFY((QMetaType::registerConverter<QLineF, CustomConvertibleType>(ConvertFunctor<QLineF>()))); - QVERIFY((QMetaType::registerConverter<QChar, CustomConvertibleType>(ConvertFunctor<QChar>()))); - QVERIFY((QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>())); - QTest::ignoreMessage(QtWarningMsg, "Type conversion already registered from type CustomConvertibleType to type CustomConvertibleType2"); - QVERIFY((!QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>())); -} - -void tst_QMetaType::convertCustomType_data() -{ - customTypeNotYetConvertible(); - registerCustomTypeConversions(); - - QTest::addColumn<bool>("ok"); - QTest::addColumn<QString>("testQString"); - QTest::addColumn<bool>("testBool"); - QTest::addColumn<int>("testInt"); - QTest::addColumn<double>("testDouble"); - QTest::addColumn<float>("testFloat"); - QTest::addColumn<QRect>("testQRect"); - QTest::addColumn<QRectF>("testQRectF"); - QTest::addColumn<QPoint>("testQPoint"); - QTest::addColumn<QPointF>("testQPointF"); - QTest::addColumn<QSize>("testQSize"); - QTest::addColumn<QSizeF>("testQSizeF"); - QTest::addColumn<QLine>("testQLine"); - QTest::addColumn<QLineF>("testQLineF"); - QTest::addColumn<QChar>("testQChar"); - QTest::addColumn<CustomConvertibleType>("testCustom"); - - QTest::newRow("default") << true - << QString::fromLatin1("string") << true << 15 - << double(3.14) << float(3.6) << QRect(1, 2, 3, 4) - << QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34) - << QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8) - << QLine(3, 9, 29, 4) << QLineF(38.9, 28.9, 102.3, 0.0) - << QChar('Q') << CustomConvertibleType(QString::fromLatin1("test")); - QTest::newRow("not ok") << false - << QString::fromLatin1("string") << true << 15 - << double(3.14) << float(3.6) << QRect(1, 2, 3, 4) - << QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34) - << QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8) - << QLine(3, 9, 29, 4) << QLineF() - << QChar('Q') << CustomConvertibleType(42); -} - -void tst_QMetaType::convertCustomType() -{ - QFETCH(bool, ok); - CustomConvertibleType::s_ok = ok; - - CustomConvertibleType t; - QVariant v = QVariant::fromValue(t); - QFETCH(QString, testQString); - CustomConvertibleType::s_value = testQString; - QCOMPARE(v.toString(), ok ? testQString : QString()); - QCOMPARE(v.value<QString>(), ok ? testQString : QString()); - QVERIFY(CustomConvertibleType::s_value.canConvert<CustomConvertibleType>()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toString()), testQString); - - QFETCH(bool, testBool); - CustomConvertibleType::s_value = testBool; - QCOMPARE(v.toBool(), testBool); - QCOMPARE(v.value<bool>(), testBool); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toBool()), testBool); - - QFETCH(int, testInt); - CustomConvertibleType::s_value = testInt; - QCOMPARE(v.toInt(), ok ? testInt : 0); - QCOMPARE(v.value<int>(), ok ? testInt : 0); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toInt()), testInt); - - QFETCH(double, testDouble); - CustomConvertibleType::s_value = testDouble; - QCOMPARE(v.toDouble(), testDouble); - QCOMPARE(v.value<double>(), testDouble); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toDouble()), testDouble); - - QFETCH(float, testFloat); - CustomConvertibleType::s_value = testFloat; - QCOMPARE(v.toFloat(), ok ? testFloat : 0.0); - QCOMPARE(v.value<float>(), ok ? testFloat : 0.0); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toFloat()), testFloat); - - QFETCH(QRect, testQRect); - CustomConvertibleType::s_value = testQRect; - QCOMPARE(v.toRect(), testQRect); - QCOMPARE(v.value<QRect>(), testQRect); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRect()), testQRect); - - QFETCH(QRectF, testQRectF); - CustomConvertibleType::s_value = testQRectF; - QCOMPARE(v.toRectF(), ok ? testQRectF : QRectF()); - QCOMPARE(v.value<QRectF>(), ok ? testQRectF : QRectF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRectF()), testQRectF); - - QFETCH(QPoint, testQPoint); - CustomConvertibleType::s_value = testQPoint; - QCOMPARE(v.toPoint(), testQPoint); - QCOMPARE(v.value<QPoint>(), testQPoint); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPoint()), testQPoint); - - QFETCH(QPointF, testQPointF); - CustomConvertibleType::s_value = testQPointF; - QCOMPARE(v.toPointF(), ok ? testQPointF : QPointF()); - QCOMPARE(v.value<QPointF>(), ok ? testQPointF : QPointF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPointF()), testQPointF); - - QFETCH(QSize, testQSize); - CustomConvertibleType::s_value = testQSize; - QCOMPARE(v.toSize(), testQSize); - QCOMPARE(v.value<QSize>(), testQSize); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSize()), testQSize); - - QFETCH(QSizeF, testQSizeF); - CustomConvertibleType::s_value = testQSizeF; - QCOMPARE(v.toSizeF(), ok ? testQSizeF : QSizeF()); - QCOMPARE(v.value<QSizeF>(), ok ? testQSizeF : QSizeF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSizeF()), testQSizeF); - - QFETCH(QLine, testQLine); - CustomConvertibleType::s_value = testQLine; - QCOMPARE(v.toLine(), testQLine); - QCOMPARE(v.value<QLine>(), testQLine); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLine()), testQLine); - - QFETCH(QLineF, testQLineF); - CustomConvertibleType::s_value = testQLineF; - QCOMPARE(v.toLineF(), ok ? testQLineF : QLineF()); - QCOMPARE(v.value<QLineF>(), ok ? testQLineF : QLineF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLineF()), testQLineF); - - QFETCH(QChar, testQChar); - CustomConvertibleType::s_value = testQChar; - QCOMPARE(v.toChar(), testQChar); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toChar()), testQChar); - - QFETCH(CustomConvertibleType, testCustom); - v = QVariant::fromValue(testCustom); - QVERIFY(v.canConvert(::qMetaTypeId<CustomConvertibleType2>())); - QCOMPARE(v.value<CustomConvertibleType2>().m_foo, testCustom.m_foo); -} - -void tst_QMetaType::compareCustomEqualOnlyType() -{ - QMetaType type = QMetaType::fromType<CustomEqualsOnlyType>(); - - CustomEqualsOnlyType val50(50); - CustomEqualsOnlyType val100(100); - CustomEqualsOnlyType val100x(100); - - QVariant variant50 = QVariant::fromValue(val50); - QVariant variant100 = QVariant::fromValue(val100); - QVariant variant100x = QVariant::fromValue(val100x); - - QVERIFY(variant50 != variant100); - QVERIFY(variant50 != variant100x); - QVERIFY(variant100 != variant50); - QVERIFY(variant100x != variant50); - QCOMPARE(variant100, variant100x); - QCOMPARE(variant100, variant100); - - // check QMetaType::compare works/doesn't crash for equals only comparators - auto cmp = type.compare(variant50.constData(), variant50.constData()); - QCOMPARE(cmp, QPartialOrdering::Unordered); - bool equals = type.equals(variant50.constData(), variant50.constData()); - QVERIFY(equals); - - cmp = type.compare(variant100.constData(), variant100x.constData()); - QCOMPARE(cmp, QPartialOrdering::Unordered); - equals = type.equals(variant100.constData(), variant100x.constData()); - QVERIFY(equals); - - cmp = type.compare(variant50.constData(), variant100.constData()); - QCOMPARE(cmp, QPartialOrdering::Unordered); - equals = type.equals(variant50.constData(), variant100.constData()); - QVERIFY(!equals); - - //check QMetaType::equals for type w/o equals comparator being registered - CustomMovable movable1; - CustomMovable movable2; - type = QMetaType::fromType<CustomMovable>(); - equals = type.equals(&movable1, &movable2); -} - -struct MessageHandlerCustom : public MessageHandler -{ - MessageHandlerCustom(const int typeId) - : MessageHandler(typeId, handler) - {} - static void handler(QtMsgType, const QMessageLogContext &, const QString &msg) - { - QCOMPARE(msg.trimmed(), expectedMessage.trimmed()); - } - static QString expectedMessage; -}; - -QString MessageHandlerCustom::expectedMessage; - -void tst_QMetaType::customDebugStream() -{ - MessageHandlerCustom handler(::qMetaTypeId<CustomDebugStreamableType>()); - QVariant v1 = QVariant::fromValue(CustomDebugStreamableType()); - handler.expectedMessage = "QVariant(CustomDebugStreamableType, string-content)"; - qDebug() << v1; - - MessageHandlerCustom handler2(::qMetaTypeId<CustomDebugStreamableType2>()); - QMetaType::registerConverter<CustomDebugStreamableType2, QString>(&CustomDebugStreamableType2::toString); - handler2.expectedMessage = "QVariant(CustomDebugStreamableType2, \"test\")"; - QVariant v2 = QVariant::fromValue(CustomDebugStreamableType2()); - qDebug() << v2; -} - -void tst_QMetaType::unknownType() -{ - QMetaType invalid(QMetaType::UnknownType); - QVERIFY(!invalid.create()); - QVERIFY(!invalid.sizeOf()); - QVERIFY(!invalid.metaObject()); - int buffer = 0xBAD; - invalid.construct(&buffer); - QCOMPARE(buffer, 0xBAD); -} - -void tst_QMetaType::fromType() -{ - #define FROMTYPE_CHECK(MetaTypeName, MetaTypeId, RealType) \ - QCOMPARE(QMetaType::fromType<RealType>(), QMetaType(MetaTypeId)); \ - QVERIFY(QMetaType::fromType<RealType>() == QMetaType(MetaTypeId)); \ - QVERIFY(!(QMetaType::fromType<RealType>() != QMetaType(MetaTypeId))); \ - if (MetaTypeId != QMetaType::Void) \ - QCOMPARE(QMetaType::fromType<RealType>().id(), MetaTypeId); - - FOR_EACH_CORE_METATYPE(FROMTYPE_CHECK) - - QVERIFY(QMetaType::fromType<QString>() != QMetaType()); - QCOMPARE(QMetaType(), QMetaType()); - QCOMPARE(QMetaType(QMetaType::UnknownType), QMetaType()); - - FROMTYPE_CHECK(_, ::qMetaTypeId<Whity<int>>(), Whity<int>) - #undef FROMTYPE_CHECK -} - -template<char X, typename T = void> -struct CharTemplate -{ - struct - { - int a; - } x; -}; - -void tst_QMetaType::operatorEq_data() -{ - QTest::addColumn<QMetaType>("typeA"); - QTest::addColumn<QMetaType>("typeB"); - QTest::addColumn<bool>("eq"); - - QTest::newRow("String") << QMetaType(QMetaType::QString) - << QMetaType::fromType<const QString &>() << true; - QTest::newRow("void1") << QMetaType(QMetaType::UnknownType) << QMetaType::fromType<void>() - << false; - QTest::newRow("void2") << QMetaType::fromType<const void>() << QMetaType::fromType<void>() - << true; - QTest::newRow("list1") << QMetaType::fromType<QList<const int *>>() - << QMetaType::fromType<QList<const int *>>() << true; - QTest::newRow("list2") << QMetaType::fromType<QList<const int *>>() - << QMetaType::fromType<QList<int *>>() << false; - QTest::newRow("char1") << QMetaType::fromType<CharTemplate<'>'>>() - << QMetaType::fromType<CharTemplate<'>', void>>() << true; - QTest::newRow("annon1") << QMetaType::fromType<decltype(CharTemplate<'>'>::x)>() - << QMetaType::fromType<decltype(CharTemplate<'>'>::x)>() << true; - QTest::newRow("annon2") << QMetaType::fromType<decltype(CharTemplate<'>'>::x)>() - << QMetaType::fromType<decltype(CharTemplate<'<'>::x)>() << false; -} - -void tst_QMetaType::operatorEq() -{ - QFETCH(QMetaType, typeA); - QFETCH(QMetaType, typeB); - QFETCH(bool, eq); - - QCOMPARE(typeA == typeB, eq); - QCOMPARE(typeB == typeA, eq); - QCOMPARE(typeA != typeB, !eq); - QCOMPARE(typeB != typeA, !eq); -} - -class WithPrivateDTor { - ~WithPrivateDTor(){}; -}; - -struct WithDeletedDtor { - ~WithDeletedDtor() = delete; -}; - -void tst_QMetaType::typesWithInaccessibleDTors() -{ - // should compile - Q_UNUSED(QMetaType::fromType<WithPrivateDTor>()); - Q_UNUSED(QMetaType::fromType<WithDeletedDtor>()); -} - -void tst_QMetaType::voidIsNotUnknown() -{ - QMetaType voidType = QMetaType::fromType<void>(); - QMetaType voidType2 = QMetaType(QMetaType::Void); - QCOMPARE(voidType, voidType2); - QVERIFY(voidType != QMetaType(QMetaType::UnknownType)); -} - -void tst_QMetaType::typeNameNormalization() -{ - // check the we normalize types the right way - -#define CHECK_TYPE_NORMALIZATION(Normalized, ...) \ - do { \ - /*QCOMPARE(QtPrivate::typenameHelper<Type>(), Normalized);*/ \ - QByteArray typeName = QMetaObject::normalizedType(#__VA_ARGS__); \ - QCOMPARE(typeName, Normalized); \ - typeName = QMetaType::fromType<__VA_ARGS__>().name(); \ - QCOMPARE(typeName, Normalized); \ - } while (0) - - CHECK_TYPE_NORMALIZATION("QList<QString*const>", QList<QString * const>); - CHECK_TYPE_NORMALIZATION("QList<const QString*>", QList<const QString * >); - CHECK_TYPE_NORMALIZATION("QList<const QString*const>", QList<const QString * const>); - CHECK_TYPE_NORMALIZATION("QList<const QString*>", QList<QString const *>); - CHECK_TYPE_NORMALIZATION("QList<signed char>", QList<signed char>); - CHECK_TYPE_NORMALIZATION("QList<uint>", QList<unsigned>); - CHECK_TYPE_NORMALIZATION("uint", uint); - CHECK_TYPE_NORMALIZATION("QList<QHash<uint,QString*>>", QList<QHash<unsigned, QString *>>); - CHECK_TYPE_NORMALIZATION("QList<qlonglong>", QList<qlonglong>); - CHECK_TYPE_NORMALIZATION("QList<qulonglong>", QList<qulonglong>); - CHECK_TYPE_NORMALIZATION("QList<qlonglong>", QList<long long>); - CHECK_TYPE_NORMALIZATION("QList<qulonglong>", QList<unsigned long long>); - CHECK_TYPE_NORMALIZATION("QList<qulonglong*>", QList<unsigned long long *>); - CHECK_TYPE_NORMALIZATION("QList<ulong>", QList<long unsigned >); -#ifdef Q_CC_MSVC - CHECK_TYPE_NORMALIZATION("qulonglong", __int64 unsigned); -#endif - CHECK_TYPE_NORMALIZATION("std::pair<const QString&&,short>", QPair<const QString &&, signed short>); - - // The string based normalization doesn't handle aliases, QMetaType::fromType() does -// CHECK_TYPE_NORMALIZATION("qulonglong", quint64); - QCOMPARE(QMetaType::fromType<quint64>().name(), "qulonglong"); -} - -// 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); -typedef Undefined (*UndefinedFunction4)(Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined); - -Q_DECLARE_METATYPE(UndefinedFunction0); -Q_DECLARE_METATYPE(UndefinedFunction1); -Q_DECLARE_METATYPE(UndefinedFunction2); -Q_DECLARE_METATYPE(UndefinedFunction3); -Q_DECLARE_METATYPE(UndefinedFunction4); - QTEST_MAIN(tst_QMetaType) #include "tst_qmetatype.moc" diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h index 43a099de17..2a0e177be1 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -26,273 +26,207 @@ ** ****************************************************************************/ -// Used by both tst_qmetatype and tst_qsettings +#include <QtCore> +#include <QTest> +#include "tst_qmetatype_common.h" +#include "tst_qvariant_common.h" -#ifndef TST_QMETATYPE_H -#define TST_QMETATYPE_H - -#include <qmetatype.h> -#include <float.h> - -#define FOR_EACH_PRIMITIVE_METATYPE(F) \ - QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \ - QT_FOR_EACH_STATIC_CORE_POINTER(F) \ +struct MessageHandlerCustom : public MessageHandler +{ + MessageHandlerCustom(const int typeId) + : MessageHandler(typeId, handler) + {} + static void handler(QtMsgType, const QMessageLogContext &, const QString &msg) + { + QCOMPARE(msg.trimmed(), expectedMessage.trimmed()); + } + inline static QString expectedMessage; +}; -#define FOR_EACH_COMPLEX_CORE_METATYPE(F) \ - QT_FOR_EACH_STATIC_CORE_CLASS(F) \ - QT_FOR_EACH_STATIC_CORE_TEMPLATE(F) +class tst_QMetaType: public QObject +{ + Q_OBJECT + Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp) + +public: + struct GadgetPropertyType { + QByteArray type; + QByteArray name; + QVariant testData; + }; + + tst_QMetaType() { propList << 42 << "Hello"; } + + QList<QVariant> prop() const { return propList; } + void setProp(const QList<QVariant> &list) { propList = list; } + +private: + void registerGadget(const char * name, const QList<GadgetPropertyType> &gadgetProperties); + QList<QVariant> propList; + +private slots: + void defined(); + void threadSafety(); + void namespaces(); + void id(); + void qMetaTypeId(); + void properties(); + void normalizedTypes(); + void typeName_data(); + void typeName(); + void type_data(); + void type(); + void type_fromSubString_data(); + void type_fromSubString(); + void create_data(); + void create(); + void createCopy_data(); + void createCopy(); + void sizeOf_data(); + void sizeOf(); + void sizeOfStaticLess_data(); + void sizeOfStaticLess(); + void alignOf_data(); + void alignOf(); + void flags_data(); + void flags(); + void flagsStaticLess_data(); + void flagsStaticLess(); + void flagsBinaryCompatibility6_0_data(); + void flagsBinaryCompatibility6_0(); + void construct_data(); + void construct(); + void typedConstruct(); + void constructCopy_data(); + void constructCopy(); + void typedefs(); + void registerType(); + void isRegistered_data(); + void isRegistered(); + void isRegisteredStaticLess_data(); + void isRegisteredStaticLess(); + void isEnum(); + void automaticTemplateRegistration(); + void saveAndLoadBuiltin_data(); + void saveAndLoadBuiltin(); + void saveAndLoadCustom(); + void metaObject_data(); + void metaObject(); + void constexprMetaTypeIds(); + + // tst_qmetatype2.cpp + void constRefs(); + void convertCustomType_data(); + void convertCustomType(); + void compareCustomEqualOnlyType(); + void customDebugStream(); + void unknownType(); + void fromType(); + void operatorEq_data(); + void operatorEq(); + void typesWithInaccessibleDTors(); + void voidIsNotUnknown(); + void typeNameNormalization(); +}; + +template <typename T> +struct Whity { T t; Whity() {} }; + +Q_DECLARE_METATYPE(Whity<int>) +Q_DECLARE_METATYPE(Whity<double>) + +#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501 +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(Whity<double>, Q_RELOCATABLE_TYPE); +QT_END_NAMESPACE +#endif -#define FOR_EACH_CORE_METATYPE(F) \ - FOR_EACH_PRIMITIVE_METATYPE(F) \ - FOR_EACH_COMPLEX_CORE_METATYPE(F) \ +struct CustomConvertibleType +{ + explicit CustomConvertibleType(const QVariant &foo = QVariant()) : m_foo(foo) {} + virtual ~CustomConvertibleType() {} + QString toString() const { return m_foo.toString(); } + operator QPoint() const { return QPoint(12, 34); } + template<typename To> + To convert() const { return s_value.value<To>();} + template<typename To> + To convertOk(bool *ok) const { *ok = s_ok; return s_value.value<To>();} + + QVariant m_foo; + inline static QVariant s_value; + inline static bool s_ok = true; + + friend bool operator<(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs) + { return lhs.m_foo.toString() < rhs.m_foo.toString(); } + friend bool operator==(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs) + { return lhs.m_foo == rhs.m_foo; } + friend bool operator!=(const CustomConvertibleType &lhs, const CustomConvertibleType &rhs) + { return !operator==(lhs, rhs); } +}; + +struct CustomConvertibleType2 +{ + // implicit + CustomConvertibleType2(const CustomConvertibleType &t = CustomConvertibleType()) + : m_foo(t.m_foo) {} + virtual ~CustomConvertibleType2() {} -template <int ID> -struct MetaEnumToType {}; + QVariant m_foo; -#define DEFINE_META_ENUM_TO_TYPE(MetaTypeName, MetaTypeId, RealType) \ -template<> \ -struct MetaEnumToType<QMetaType::MetaTypeName> { \ - typedef RealType Type; \ + friend bool operator==(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs) + { return lhs.m_foo == rhs.m_foo; } + friend bool operator!=(const CustomConvertibleType2 &lhs, const CustomConvertibleType2 &rhs) + { return !operator==(lhs, rhs); } }; -FOR_EACH_CORE_METATYPE(DEFINE_META_ENUM_TO_TYPE) -#undef DEFINE_META_ENUM_TO_TYPE -template <int ID> -struct DefaultValueFactory +struct CustomDebugStreamableType { - typedef typename MetaEnumToType<ID>::Type Type; - static Type *create() { return new Type; } -}; + QString toString() const { return "test"; } -template <> -struct DefaultValueFactory<QMetaType::Void> -{ - typedef MetaEnumToType<QMetaType::Void>::Type Type; - static Type *create() { return 0; } + friend QDebug operator<<(QDebug dbg, const CustomDebugStreamableType&) + { + return dbg << "string-content"; + } }; -template <int ID> -struct DefaultValueTraits +struct CustomDebugStreamableType2 { - // 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 }; + QString toString() const { return "test"; } }; -#define DEFINE_NON_INITIALIZED_DEFAULT_VALUE_TRAITS(MetaTypeName, MetaTypeId, RealType) \ -template<> struct DefaultValueTraits<QMetaType::MetaTypeName> { \ - 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 +struct CustomEqualsOnlyType +{ + explicit CustomEqualsOnlyType(int value = 0) : val(value) {} + virtual ~CustomEqualsOnlyType() {} -template <int ID> -struct TestValueFactory {}; + int val; -template<> struct TestValueFactory<QMetaType::Void> { - static void *create() { return 0; } + friend bool operator==(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs) + { return lhs.val == rhs.val;} + friend bool operator!=(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs) + { return !operator==(lhs, rhs); } }; -template<> struct TestValueFactory<QMetaType::QString> { - static QString *create() { return new QString(QString::fromLatin1("QString")); } -}; -template<> struct TestValueFactory<QMetaType::Int> { - static int *create() { return new int(INT_MIN); } -}; -template<> struct TestValueFactory<QMetaType::UInt> { - static uint *create() { return new uint(UINT_MAX); } -}; -template<> struct TestValueFactory<QMetaType::Bool> { - static bool *create() { return new bool(true); } -}; -template<> struct TestValueFactory<QMetaType::Double> { - static double *create() { return new double(DBL_MIN); } -}; -template<> struct TestValueFactory<QMetaType::QByteArray> { - static QByteArray *create() { return new QByteArray(QByteArray("QByteArray")); } -}; -template<> struct TestValueFactory<QMetaType::QByteArrayList> { - static QByteArrayList *create() { return new QByteArrayList(QByteArrayList() << "Q" << "Byte" << "Array" << "List"); } -}; -template<> struct TestValueFactory<QMetaType::QVariantMap> { - static QVariantMap *create() { return new QVariantMap(); } -}; -template<> struct TestValueFactory<QMetaType::QVariantHash> { - static QVariantHash *create() { return new QVariantHash(); } -}; -template<> struct TestValueFactory<QMetaType::QVariantPair> { - static QVariantPair *create() { return new QVariantPair(); } -}; +static_assert(QTypeTraits::has_operator_equal_v<CustomEqualsOnlyType>); +static_assert(!QTypeTraits::has_operator_less_than_v<CustomEqualsOnlyType>); -template<> struct TestValueFactory<QMetaType::QVariantList> { - static QVariantList *create() { return new QVariantList(QVariantList() << 123 << "Q" << "Variant" << "List"); } -}; -template<> struct TestValueFactory<QMetaType::QChar> { - static QChar *create() { return new QChar(QChar('q')); } -}; -template<> struct TestValueFactory<QMetaType::Long> { - static long *create() { return new long(LONG_MIN); } -}; -template<> struct TestValueFactory<QMetaType::Short> { - static short *create() { return new short(SHRT_MIN); } -}; -template<> struct TestValueFactory<QMetaType::Char> { - static char *create() { return new char('c'); } -}; -template<> struct TestValueFactory<QMetaType::Char16> { - static char16_t *create() { return new char16_t('c'); } -}; -template<> struct TestValueFactory<QMetaType::Char32> { - static char32_t *create() { return new char32_t('c'); } -}; -template<> struct TestValueFactory<QMetaType::ULong> { - static ulong *create() { return new ulong(ULONG_MAX); } -}; -template<> struct TestValueFactory<QMetaType::UShort> { - static ushort *create() { return new ushort(USHRT_MAX); } -}; -template<> struct TestValueFactory<QMetaType::SChar> { - static signed char *create() { return new signed char(CHAR_MIN); } -}; -template<> struct TestValueFactory<QMetaType::UChar> { - static uchar *create() { return new uchar(UCHAR_MAX); } -}; -template<> struct TestValueFactory<QMetaType::Float> { - static float *create() { return new float(FLT_MIN); } -}; -template<> struct TestValueFactory<QMetaType::QObjectStar> { - static QObject * *create() { return new QObject *(0); } -}; -template<> struct TestValueFactory<QMetaType::VoidStar> { - static void * *create() { return new void *(0); } -}; -template<> struct TestValueFactory<QMetaType::LongLong> { - static qlonglong *create() { return new qlonglong(LLONG_MIN); } -}; -template<> struct TestValueFactory<QMetaType::ULongLong> { - static qulonglong *create() { return new qulonglong(ULLONG_MAX); } -}; -template<> struct TestValueFactory<QMetaType::QStringList> { - static QStringList *create() { return new QStringList(QStringList() << "Q" << "t"); } -}; -template<> struct TestValueFactory<QMetaType::QBitArray> { - static QBitArray *create() { return new QBitArray(QBitArray(256, true)); } -}; -template<> struct TestValueFactory<QMetaType::QDate> { - static QDate *create() { return new QDate(QDate::currentDate()); } -}; -template<> struct TestValueFactory<QMetaType::QTime> { - static QTime *create() { return new QTime(QTime::currentTime()); } -}; -template<> struct TestValueFactory<QMetaType::QDateTime> { - static QDateTime *create() { return new QDateTime(QDateTime::currentDateTime()); } -}; -template<> struct TestValueFactory<QMetaType::QUrl> { - static QUrl *create() { return new QUrl("http://www.example.org"); } -}; -template<> struct TestValueFactory<QMetaType::QLocale> { - static QLocale *create() { return new QLocale(QLocale::c()); } -}; -template<> struct TestValueFactory<QMetaType::QRect> { - static QRect *create() { return new QRect(10, 20, 30, 40); } -}; -template<> struct TestValueFactory<QMetaType::QRectF> { - static QRectF *create() { return new QRectF(10, 20, 30, 40); } -}; -template<> struct TestValueFactory<QMetaType::QSize> { - static QSize *create() { return new QSize(10, 20); } -}; -template<> struct TestValueFactory<QMetaType::QSizeF> { - static QSizeF *create() { return new QSizeF(10, 20); } -}; -template<> struct TestValueFactory<QMetaType::QLine> { - static QLine *create() { return new QLine(10, 20, 30, 40); } -}; -template<> struct TestValueFactory<QMetaType::QLineF> { - static QLineF *create() { return new QLineF(10, 20, 30, 40); } -}; -template<> struct TestValueFactory<QMetaType::QPoint> { - static QPoint *create() { return new QPoint(10, 20); } -}; -template<> struct TestValueFactory<QMetaType::QPointF> { - static QPointF *create() { return new QPointF(10, 20); } -}; -template<> struct TestValueFactory<QMetaType::QEasingCurve> { - static QEasingCurve *create() { return new QEasingCurve(QEasingCurve::InOutElastic); } -}; -template<> struct TestValueFactory<QMetaType::QUuid> { - static QUuid *create() { return new QUuid(); } -}; -template<> struct TestValueFactory<QMetaType::QModelIndex> { - static QModelIndex *create() { return new QModelIndex(); } -}; -template<> struct TestValueFactory<QMetaType::QPersistentModelIndex> { - static QPersistentModelIndex *create() { return new QPersistentModelIndex(); } -}; -template<> struct TestValueFactory<QMetaType::Nullptr> { - static std::nullptr_t *create() { return new std::nullptr_t; } -}; -template<> struct TestValueFactory<QMetaType::QRegularExpression> { - static QRegularExpression *create() - { -#if QT_CONFIG(regularexpression) - return new QRegularExpression("abc.*def"); -#else - return 0; -#endif - } -}; -template<> struct TestValueFactory<QMetaType::QJsonValue> { - static QJsonValue *create() { return new QJsonValue(123.); } -}; -template<> struct TestValueFactory<QMetaType::QJsonObject> { - static QJsonObject *create() { - QJsonObject *o = new QJsonObject(); - o->insert("a", 123.); - o->insert("b", true); - o->insert("c", QJsonValue::Null); - o->insert("d", QLatin1String("ciao")); - return o; - } -}; -template<> struct TestValueFactory<QMetaType::QJsonArray> { - static QJsonArray *create() { - QJsonArray *a = new QJsonArray(); - a->append(123.); - a->append(true); - a->append(QJsonValue::Null); - a->append(QLatin1String("ciao")); - return a; - } -}; -template<> struct TestValueFactory<QMetaType::QJsonDocument> { - static QJsonDocument *create() { - return new QJsonDocument( - QJsonDocument::fromJson("{ 'foo': 123, 'bar': [true, null, 'ciao'] }") - ); - } -}; +Q_DECLARE_METATYPE(CustomConvertibleType); +Q_DECLARE_METATYPE(CustomConvertibleType2); +Q_DECLARE_METATYPE(CustomDebugStreamableType); +Q_DECLARE_METATYPE(CustomEqualsOnlyType); -template<> struct TestValueFactory<QMetaType::QCborSimpleType> { - static QCborSimpleType *create() { return new QCborSimpleType(QCborSimpleType::True); } -}; -template<> struct TestValueFactory<QMetaType::QCborValue> { - static QCborValue *create() { return new QCborValue(123.); } -}; -template<> struct TestValueFactory<QMetaType::QCborMap> { - static QCborMap *create() { - return new QCborMap{{0, 0}, {"Hello", 1}, {1, nullptr}}; - } -}; -template<> struct TestValueFactory<QMetaType::QCborArray> { - static QCborArray *create() { - return new QCborArray{0, 1, -2, 2.5, false, nullptr, "Hello", QByteArray("World") }; - } -}; +struct CustomMovable { + CustomMovable() {} -template<> struct TestValueFactory<QMetaType::QVariant> { - static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); } + friend bool operator==(const CustomMovable &, const CustomMovable &) { return true; } + // needed for QSet<CustomMovable>. We actually check that it makes sense. + friend qsizetype qHash(const CustomMovable &, qsizetype seed = 0) { return seed; } }; -#endif // TST_QMETATYPE_H +#if !defined(Q_CC_CLANG) && defined(Q_CC_GNU) && Q_CC_GNU < 501 +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(CustomMovable, Q_RELOCATABLE_TYPE); +QT_END_NAMESPACE +#endif + +Q_DECLARE_METATYPE(CustomMovable); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp new file mode 100644 index 0000000000..3c097ad0d8 --- /dev/null +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp @@ -0,0 +1,483 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 "tst_qmetatype.h" +#include "tst_qvariant_common.h" + +#include <QtCore/private/qmetaobjectbuilder_p.h> + +void tst_QMetaType::constRefs() +{ + QCOMPARE(::qMetaTypeId<const int &>(), ::qMetaTypeId<int>()); + QCOMPARE(::qMetaTypeId<const QString &>(), ::qMetaTypeId<QString>()); + QCOMPARE(::qMetaTypeId<const CustomMovable &>(), ::qMetaTypeId<CustomMovable>()); + QCOMPARE(::qMetaTypeId<const QList<CustomMovable> &>(), ::qMetaTypeId<QList<CustomMovable> >()); + static_assert(::qMetaTypeId<const int &>() == ::qMetaTypeId<int>()); +} + +template<typename T, typename U> +U convert(const T &t) +{ + return t; +} + +template<typename From> +struct ConvertFunctor +{ + CustomConvertibleType operator()(const From& f) const + { + return CustomConvertibleType(QVariant::fromValue(f)); + } +}; + +template<typename From, typename To> +bool hasRegisteredConverterFunction() +{ + return QMetaType::hasRegisteredConverterFunction<From, To>(); +} + +template<typename From, typename To> +void testCustomTypeNotYetConvertible() +{ + QVERIFY((!hasRegisteredConverterFunction<From, To>())); + QVERIFY((!QVariant::fromValue<From>(From()).template canConvert<To>())); +} + +template<typename From, typename To> +void testCustomTypeConvertible() +{ + QVERIFY((hasRegisteredConverterFunction<From, To>())); + QVERIFY((QVariant::fromValue<From>(From()).template canConvert<To>())); +} + +void customTypeNotYetConvertible() +{ + testCustomTypeNotYetConvertible<CustomConvertibleType, QString>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, bool>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, int>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, double>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, float>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QRect>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QRectF>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QPoint>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QPointF>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QSize>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QSizeF>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QLine>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QLineF>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, QChar>(); + testCustomTypeNotYetConvertible<QString, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<bool, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<int, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<double, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<float, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QRect, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QRectF, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QPoint, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QPointF, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QSize, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QSizeF, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QLine, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QLineF, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<QChar, CustomConvertibleType>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, CustomConvertibleType2>(); +} + +void registerCustomTypeConversions() +{ + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QString>(&CustomConvertibleType::convertOk<QString>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, bool>(&CustomConvertibleType::convert<bool>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, int>(&CustomConvertibleType::convertOk<int>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, double>(&CustomConvertibleType::convert<double>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, float>(&CustomConvertibleType::convertOk<float>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QRect>(&CustomConvertibleType::convert<QRect>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QRectF>(&CustomConvertibleType::convertOk<QRectF>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QPoint>(convert<CustomConvertibleType,QPoint>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QPointF>(&CustomConvertibleType::convertOk<QPointF>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QSize>(&CustomConvertibleType::convert<QSize>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QSizeF>(&CustomConvertibleType::convertOk<QSizeF>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLine>(&CustomConvertibleType::convert<QLine>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLineF>(&CustomConvertibleType::convertOk<QLineF>))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QChar>(&CustomConvertibleType::convert<QChar>))); + QVERIFY((QMetaType::registerConverter<QString, CustomConvertibleType>(ConvertFunctor<QString>()))); + QVERIFY((QMetaType::registerConverter<bool, CustomConvertibleType>(ConvertFunctor<bool>()))); + QVERIFY((QMetaType::registerConverter<int, CustomConvertibleType>(ConvertFunctor<int>()))); + QVERIFY((QMetaType::registerConverter<double, CustomConvertibleType>(ConvertFunctor<double>()))); + QVERIFY((QMetaType::registerConverter<float, CustomConvertibleType>(ConvertFunctor<float>()))); + QVERIFY((QMetaType::registerConverter<QRect, CustomConvertibleType>(ConvertFunctor<QRect>()))); + QVERIFY((QMetaType::registerConverter<QRectF, CustomConvertibleType>(ConvertFunctor<QRectF>()))); + QVERIFY((QMetaType::registerConverter<QPoint, CustomConvertibleType>(ConvertFunctor<QPoint>()))); + QVERIFY((QMetaType::registerConverter<QPointF, CustomConvertibleType>(ConvertFunctor<QPointF>()))); + QVERIFY((QMetaType::registerConverter<QSize, CustomConvertibleType>(ConvertFunctor<QSize>()))); + QVERIFY((QMetaType::registerConverter<QSizeF, CustomConvertibleType>(ConvertFunctor<QSizeF>()))); + QVERIFY((QMetaType::registerConverter<QLine, CustomConvertibleType>(ConvertFunctor<QLine>()))); + QVERIFY((QMetaType::registerConverter<QLineF, CustomConvertibleType>(ConvertFunctor<QLineF>()))); + QVERIFY((QMetaType::registerConverter<QChar, CustomConvertibleType>(ConvertFunctor<QChar>()))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>())); + QTest::ignoreMessage(QtWarningMsg, "Type conversion already registered from type CustomConvertibleType to type CustomConvertibleType2"); + QVERIFY((!QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>())); +} + +void tst_QMetaType::convertCustomType_data() +{ + customTypeNotYetConvertible(); + registerCustomTypeConversions(); + + QTest::addColumn<bool>("ok"); + QTest::addColumn<QString>("testQString"); + QTest::addColumn<bool>("testBool"); + QTest::addColumn<int>("testInt"); + QTest::addColumn<double>("testDouble"); + QTest::addColumn<float>("testFloat"); + QTest::addColumn<QRect>("testQRect"); + QTest::addColumn<QRectF>("testQRectF"); + QTest::addColumn<QPoint>("testQPoint"); + QTest::addColumn<QPointF>("testQPointF"); + QTest::addColumn<QSize>("testQSize"); + QTest::addColumn<QSizeF>("testQSizeF"); + QTest::addColumn<QLine>("testQLine"); + QTest::addColumn<QLineF>("testQLineF"); + QTest::addColumn<QChar>("testQChar"); + QTest::addColumn<CustomConvertibleType>("testCustom"); + + QTest::newRow("default") << true + << QString::fromLatin1("string") << true << 15 + << double(3.14) << float(3.6) << QRect(1, 2, 3, 4) + << QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34) + << QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8) + << QLine(3, 9, 29, 4) << QLineF(38.9, 28.9, 102.3, 0.0) + << QChar('Q') << CustomConvertibleType(QString::fromLatin1("test")); + QTest::newRow("not ok") << false + << QString::fromLatin1("string") << true << 15 + << double(3.14) << float(3.6) << QRect(1, 2, 3, 4) + << QRectF(1.4, 1.9, 10.9, 40.2) << QPoint(12, 34) + << QPointF(9.2, 2.7) << QSize(4, 9) << QSizeF(3.3, 9.8) + << QLine(3, 9, 29, 4) << QLineF() + << QChar('Q') << CustomConvertibleType(42); +} + +void tst_QMetaType::convertCustomType() +{ + QFETCH(bool, ok); + CustomConvertibleType::s_ok = ok; + + CustomConvertibleType t; + QVariant v = QVariant::fromValue(t); + QFETCH(QString, testQString); + CustomConvertibleType::s_value = testQString; + QCOMPARE(v.toString(), ok ? testQString : QString()); + QCOMPARE(v.value<QString>(), ok ? testQString : QString()); + QVERIFY(CustomConvertibleType::s_value.canConvert<CustomConvertibleType>()); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toString()), testQString); + + QFETCH(bool, testBool); + CustomConvertibleType::s_value = testBool; + QCOMPARE(v.toBool(), testBool); + QCOMPARE(v.value<bool>(), testBool); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toBool()), testBool); + + QFETCH(int, testInt); + CustomConvertibleType::s_value = testInt; + QCOMPARE(v.toInt(), ok ? testInt : 0); + QCOMPARE(v.value<int>(), ok ? testInt : 0); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toInt()), testInt); + + QFETCH(double, testDouble); + CustomConvertibleType::s_value = testDouble; + QCOMPARE(v.toDouble(), testDouble); + QCOMPARE(v.value<double>(), testDouble); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toDouble()), testDouble); + + QFETCH(float, testFloat); + CustomConvertibleType::s_value = testFloat; + QCOMPARE(v.toFloat(), ok ? testFloat : 0.0); + QCOMPARE(v.value<float>(), ok ? testFloat : 0.0); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toFloat()), testFloat); + + QFETCH(QRect, testQRect); + CustomConvertibleType::s_value = testQRect; + QCOMPARE(v.toRect(), testQRect); + QCOMPARE(v.value<QRect>(), testQRect); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRect()), testQRect); + + QFETCH(QRectF, testQRectF); + CustomConvertibleType::s_value = testQRectF; + QCOMPARE(v.toRectF(), ok ? testQRectF : QRectF()); + QCOMPARE(v.value<QRectF>(), ok ? testQRectF : QRectF()); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRectF()), testQRectF); + + QFETCH(QPoint, testQPoint); + CustomConvertibleType::s_value = testQPoint; + QCOMPARE(v.toPoint(), testQPoint); + QCOMPARE(v.value<QPoint>(), testQPoint); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPoint()), testQPoint); + + QFETCH(QPointF, testQPointF); + CustomConvertibleType::s_value = testQPointF; + QCOMPARE(v.toPointF(), ok ? testQPointF : QPointF()); + QCOMPARE(v.value<QPointF>(), ok ? testQPointF : QPointF()); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPointF()), testQPointF); + + QFETCH(QSize, testQSize); + CustomConvertibleType::s_value = testQSize; + QCOMPARE(v.toSize(), testQSize); + QCOMPARE(v.value<QSize>(), testQSize); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSize()), testQSize); + + QFETCH(QSizeF, testQSizeF); + CustomConvertibleType::s_value = testQSizeF; + QCOMPARE(v.toSizeF(), ok ? testQSizeF : QSizeF()); + QCOMPARE(v.value<QSizeF>(), ok ? testQSizeF : QSizeF()); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSizeF()), testQSizeF); + + QFETCH(QLine, testQLine); + CustomConvertibleType::s_value = testQLine; + QCOMPARE(v.toLine(), testQLine); + QCOMPARE(v.value<QLine>(), testQLine); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLine()), testQLine); + + QFETCH(QLineF, testQLineF); + CustomConvertibleType::s_value = testQLineF; + QCOMPARE(v.toLineF(), ok ? testQLineF : QLineF()); + QCOMPARE(v.value<QLineF>(), ok ? testQLineF : QLineF()); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLineF()), testQLineF); + + QFETCH(QChar, testQChar); + CustomConvertibleType::s_value = testQChar; + QCOMPARE(v.toChar(), testQChar); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toChar()), testQChar); + + QFETCH(CustomConvertibleType, testCustom); + v = QVariant::fromValue(testCustom); + QVERIFY(v.canConvert(::qMetaTypeId<CustomConvertibleType2>())); + QCOMPARE(v.value<CustomConvertibleType2>().m_foo, testCustom.m_foo); +} + +void tst_QMetaType::compareCustomEqualOnlyType() +{ + QMetaType type = QMetaType::fromType<CustomEqualsOnlyType>(); + + CustomEqualsOnlyType val50(50); + CustomEqualsOnlyType val100(100); + CustomEqualsOnlyType val100x(100); + + QVariant variant50 = QVariant::fromValue(val50); + QVariant variant100 = QVariant::fromValue(val100); + QVariant variant100x = QVariant::fromValue(val100x); + + QVERIFY(variant50 != variant100); + QVERIFY(variant50 != variant100x); + QVERIFY(variant100 != variant50); + QVERIFY(variant100x != variant50); + QCOMPARE(variant100, variant100x); + QCOMPARE(variant100, variant100); + + // check QMetaType::compare works/doesn't crash for equals only comparators + auto cmp = type.compare(variant50.constData(), variant50.constData()); + QCOMPARE(cmp, QPartialOrdering::Unordered); + bool equals = type.equals(variant50.constData(), variant50.constData()); + QVERIFY(equals); + + cmp = type.compare(variant100.constData(), variant100x.constData()); + QCOMPARE(cmp, QPartialOrdering::Unordered); + equals = type.equals(variant100.constData(), variant100x.constData()); + QVERIFY(equals); + + cmp = type.compare(variant50.constData(), variant100.constData()); + QCOMPARE(cmp, QPartialOrdering::Unordered); + equals = type.equals(variant50.constData(), variant100.constData()); + QVERIFY(!equals); + + //check QMetaType::equals for type w/o equals comparator being registered + CustomMovable movable1; + CustomMovable movable2; + type = QMetaType::fromType<CustomMovable>(); + equals = type.equals(&movable1, &movable2); +} + +void tst_QMetaType::customDebugStream() +{ + MessageHandlerCustom handler(::qMetaTypeId<CustomDebugStreamableType>()); + QVariant v1 = QVariant::fromValue(CustomDebugStreamableType()); + handler.expectedMessage = "QVariant(CustomDebugStreamableType, string-content)"; + qDebug() << v1; + + MessageHandlerCustom handler2(::qMetaTypeId<CustomDebugStreamableType2>()); + QMetaType::registerConverter<CustomDebugStreamableType2, QString>(&CustomDebugStreamableType2::toString); + handler2.expectedMessage = "QVariant(CustomDebugStreamableType2, \"test\")"; + QVariant v2 = QVariant::fromValue(CustomDebugStreamableType2()); + qDebug() << v2; +} + +void tst_QMetaType::unknownType() +{ + QMetaType invalid(QMetaType::UnknownType); + QVERIFY(!invalid.create()); + QVERIFY(!invalid.sizeOf()); + QVERIFY(!invalid.metaObject()); + int buffer = 0xBAD; + invalid.construct(&buffer); + QCOMPARE(buffer, 0xBAD); +} + +void tst_QMetaType::fromType() +{ + #define FROMTYPE_CHECK(MetaTypeName, MetaTypeId, RealType) \ + QCOMPARE(QMetaType::fromType<RealType>(), QMetaType(MetaTypeId)); \ + QVERIFY(QMetaType::fromType<RealType>() == QMetaType(MetaTypeId)); \ + QVERIFY(!(QMetaType::fromType<RealType>() != QMetaType(MetaTypeId))); \ + if (MetaTypeId != QMetaType::Void) \ + QCOMPARE(QMetaType::fromType<RealType>().id(), MetaTypeId); + + FOR_EACH_CORE_METATYPE(FROMTYPE_CHECK) + + QVERIFY(QMetaType::fromType<QString>() != QMetaType()); + QCOMPARE(QMetaType(), QMetaType()); + QCOMPARE(QMetaType(QMetaType::UnknownType), QMetaType()); + + FROMTYPE_CHECK(_, ::qMetaTypeId<Whity<int>>(), Whity<int>) + #undef FROMTYPE_CHECK +} + +template<char X, typename T = void> +struct CharTemplate +{ + struct + { + int a; + } x; +}; + +void tst_QMetaType::operatorEq_data() +{ + QTest::addColumn<QMetaType>("typeA"); + QTest::addColumn<QMetaType>("typeB"); + QTest::addColumn<bool>("eq"); + QTest::newRow("String") << QMetaType(QMetaType::QString) + << QMetaType::fromType<const QString &>() << true; + QTest::newRow("void1") << QMetaType(QMetaType::UnknownType) << QMetaType::fromType<void>() + << false; + QTest::newRow("void2") << QMetaType::fromType<const void>() << QMetaType::fromType<void>() + << true; + QTest::newRow("list1") << QMetaType::fromType<QList<const int *>>() + << QMetaType::fromType<QList<const int *>>() << true; + QTest::newRow("list2") << QMetaType::fromType<QList<const int *>>() + << QMetaType::fromType<QList<int *>>() << false; + QTest::newRow("char1") << QMetaType::fromType<CharTemplate<'>'>>() + << QMetaType::fromType<CharTemplate<'>', void>>() << true; + QTest::newRow("annon1") << QMetaType::fromType<decltype(CharTemplate<'>'>::x)>() + << QMetaType::fromType<decltype(CharTemplate<'>'>::x)>() << true; + QTest::newRow("annon2") << QMetaType::fromType<decltype(CharTemplate<'>'>::x)>() + << QMetaType::fromType<decltype(CharTemplate<'<'>::x)>() << false; +} + +void tst_QMetaType::operatorEq() +{ + QFETCH(QMetaType, typeA); + QFETCH(QMetaType, typeB); + QFETCH(bool, eq); + + QCOMPARE(typeA == typeB, eq); + QCOMPARE(typeB == typeA, eq); + QCOMPARE(typeA != typeB, !eq); + QCOMPARE(typeB != typeA, !eq); +} + +class WithPrivateDTor { + ~WithPrivateDTor(){}; +}; + +struct WithDeletedDtor { + ~WithDeletedDtor() = delete; +}; + +void tst_QMetaType::typesWithInaccessibleDTors() +{ + // should compile + Q_UNUSED(QMetaType::fromType<WithPrivateDTor>()); + Q_UNUSED(QMetaType::fromType<WithDeletedDtor>()); +} + +void tst_QMetaType::voidIsNotUnknown() +{ + QMetaType voidType = QMetaType::fromType<void>(); + QMetaType voidType2 = QMetaType(QMetaType::Void); + QCOMPARE(voidType, voidType2); + QVERIFY(voidType != QMetaType(QMetaType::UnknownType)); +} + +void tst_QMetaType::typeNameNormalization() +{ + // check the we normalize types the right way +#define CHECK_TYPE_NORMALIZATION(Normalized, ...) \ + do { \ + /*QCOMPARE(QtPrivate::typenameHelper<Type>(), Normalized);*/ \ + QByteArray typeName = QMetaObject::normalizedType(#__VA_ARGS__); \ + QCOMPARE(typeName, Normalized); \ + typeName = QMetaType::fromType<__VA_ARGS__>().name(); \ + QCOMPARE(typeName, Normalized); \ + } while (0) + + CHECK_TYPE_NORMALIZATION("QList<QString*const>", QList<QString * const>); + CHECK_TYPE_NORMALIZATION("QList<const QString*>", QList<const QString * >); + CHECK_TYPE_NORMALIZATION("QList<const QString*const>", QList<const QString * const>); + CHECK_TYPE_NORMALIZATION("QList<const QString*>", QList<QString const *>); + CHECK_TYPE_NORMALIZATION("QList<signed char>", QList<signed char>); + CHECK_TYPE_NORMALIZATION("QList<uint>", QList<unsigned>); + CHECK_TYPE_NORMALIZATION("uint", uint); + CHECK_TYPE_NORMALIZATION("QList<QHash<uint,QString*>>", QList<QHash<unsigned, QString *>>); + CHECK_TYPE_NORMALIZATION("QList<qlonglong>", QList<qlonglong>); + CHECK_TYPE_NORMALIZATION("QList<qulonglong>", QList<qulonglong>); + CHECK_TYPE_NORMALIZATION("QList<qlonglong>", QList<long long>); + CHECK_TYPE_NORMALIZATION("QList<qulonglong>", QList<unsigned long long>); + CHECK_TYPE_NORMALIZATION("QList<qulonglong*>", QList<unsigned long long *>); + CHECK_TYPE_NORMALIZATION("QList<ulong>", QList<long unsigned >); +#ifdef Q_CC_MSVC + CHECK_TYPE_NORMALIZATION("qulonglong", __int64 unsigned); +#endif + CHECK_TYPE_NORMALIZATION("std::pair<const QString&&,short>", QPair<const QString &&, signed short>); + + // The string based normalization doesn't handle aliases, QMetaType::fromType() does +// CHECK_TYPE_NORMALIZATION("qulonglong", quint64); + QCOMPARE(QMetaType::fromType<quint64>().name(), "qulonglong"); +} + +// 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); +typedef Undefined (*UndefinedFunction4)(Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined, Undefined); + +Q_DECLARE_METATYPE(UndefinedFunction0); +Q_DECLARE_METATYPE(UndefinedFunction1); +Q_DECLARE_METATYPE(UndefinedFunction2); +Q_DECLARE_METATYPE(UndefinedFunction3); +Q_DECLARE_METATYPE(UndefinedFunction4); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype_common.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype_common.h new file mode 100644 index 0000000000..6193ca93b8 --- /dev/null +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype_common.h @@ -0,0 +1,298 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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$ +** +****************************************************************************/ + +// Used by both tst_qmetatype and tst_qsettings + +#ifndef TST_QMETATYPE_H +#define TST_QMETATYPE_H + +#include <qmetatype.h> +#include <float.h> + +#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) \ + QT_FOR_EACH_STATIC_CORE_TEMPLATE(F) + +#define FOR_EACH_CORE_METATYPE(F) \ + FOR_EACH_PRIMITIVE_METATYPE(F) \ + FOR_EACH_COMPLEX_CORE_METATYPE(F) \ + +template <int ID> +struct MetaEnumToType {}; + +#define DEFINE_META_ENUM_TO_TYPE(MetaTypeName, MetaTypeId, RealType) \ +template<> \ +struct MetaEnumToType<QMetaType::MetaTypeName> { \ + typedef RealType Type; \ +}; +FOR_EACH_CORE_METATYPE(DEFINE_META_ENUM_TO_TYPE) +#undef DEFINE_META_ENUM_TO_TYPE + +template <int ID> +struct DefaultValueFactory +{ + typedef typename MetaEnumToType<ID>::Type Type; + static Type *create() { return new Type; } +}; + +template <> +struct DefaultValueFactory<QMetaType::Void> +{ + typedef MetaEnumToType<QMetaType::Void>::Type Type; + static Type *create() { return 0; } +}; + +template <int ID> +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<QMetaType::MetaTypeName> { \ + 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 <int ID> +struct TestValueFactory {}; + +template<> struct TestValueFactory<QMetaType::Void> { + static void *create() { return 0; } +}; + +template<> struct TestValueFactory<QMetaType::QString> { + static QString *create() { return new QString(QString::fromLatin1("QString")); } +}; +template<> struct TestValueFactory<QMetaType::Int> { + static int *create() { return new int(INT_MIN); } +}; +template<> struct TestValueFactory<QMetaType::UInt> { + static uint *create() { return new uint(UINT_MAX); } +}; +template<> struct TestValueFactory<QMetaType::Bool> { + static bool *create() { return new bool(true); } +}; +template<> struct TestValueFactory<QMetaType::Double> { + static double *create() { return new double(DBL_MIN); } +}; +template<> struct TestValueFactory<QMetaType::QByteArray> { + static QByteArray *create() { return new QByteArray(QByteArray("QByteArray")); } +}; +template<> struct TestValueFactory<QMetaType::QByteArrayList> { + static QByteArrayList *create() { return new QByteArrayList(QByteArrayList() << "Q" << "Byte" << "Array" << "List"); } +}; +template<> struct TestValueFactory<QMetaType::QVariantMap> { + static QVariantMap *create() { return new QVariantMap(); } +}; +template<> struct TestValueFactory<QMetaType::QVariantHash> { + static QVariantHash *create() { return new QVariantHash(); } +}; +template<> struct TestValueFactory<QMetaType::QVariantPair> { + static QVariantPair *create() { return new QVariantPair(); } +}; + +template<> struct TestValueFactory<QMetaType::QVariantList> { + static QVariantList *create() { return new QVariantList(QVariantList() << 123 << "Q" << "Variant" << "List"); } +}; +template<> struct TestValueFactory<QMetaType::QChar> { + static QChar *create() { return new QChar(QChar('q')); } +}; +template<> struct TestValueFactory<QMetaType::Long> { + static long *create() { return new long(LONG_MIN); } +}; +template<> struct TestValueFactory<QMetaType::Short> { + static short *create() { return new short(SHRT_MIN); } +}; +template<> struct TestValueFactory<QMetaType::Char> { + static char *create() { return new char('c'); } +}; +template<> struct TestValueFactory<QMetaType::Char16> { + static char16_t *create() { return new char16_t('c'); } +}; +template<> struct TestValueFactory<QMetaType::Char32> { + static char32_t *create() { return new char32_t('c'); } +}; +template<> struct TestValueFactory<QMetaType::ULong> { + static ulong *create() { return new ulong(ULONG_MAX); } +}; +template<> struct TestValueFactory<QMetaType::UShort> { + static ushort *create() { return new ushort(USHRT_MAX); } +}; +template<> struct TestValueFactory<QMetaType::SChar> { + static signed char *create() { return new signed char(CHAR_MIN); } +}; +template<> struct TestValueFactory<QMetaType::UChar> { + static uchar *create() { return new uchar(UCHAR_MAX); } +}; +template<> struct TestValueFactory<QMetaType::Float> { + static float *create() { return new float(FLT_MIN); } +}; +template<> struct TestValueFactory<QMetaType::QObjectStar> { + static QObject * *create() { return new QObject *(0); } +}; +template<> struct TestValueFactory<QMetaType::VoidStar> { + static void * *create() { return new void *(0); } +}; +template<> struct TestValueFactory<QMetaType::LongLong> { + static qlonglong *create() { return new qlonglong(LLONG_MIN); } +}; +template<> struct TestValueFactory<QMetaType::ULongLong> { + static qulonglong *create() { return new qulonglong(ULLONG_MAX); } +}; +template<> struct TestValueFactory<QMetaType::QStringList> { + static QStringList *create() { return new QStringList(QStringList() << "Q" << "t"); } +}; +template<> struct TestValueFactory<QMetaType::QBitArray> { + static QBitArray *create() { return new QBitArray(QBitArray(256, true)); } +}; +template<> struct TestValueFactory<QMetaType::QDate> { + static QDate *create() { return new QDate(QDate::currentDate()); } +}; +template<> struct TestValueFactory<QMetaType::QTime> { + static QTime *create() { return new QTime(QTime::currentTime()); } +}; +template<> struct TestValueFactory<QMetaType::QDateTime> { + static QDateTime *create() { return new QDateTime(QDateTime::currentDateTime()); } +}; +template<> struct TestValueFactory<QMetaType::QUrl> { + static QUrl *create() { return new QUrl("http://www.example.org"); } +}; +template<> struct TestValueFactory<QMetaType::QLocale> { + static QLocale *create() { return new QLocale(QLocale::c()); } +}; +template<> struct TestValueFactory<QMetaType::QRect> { + static QRect *create() { return new QRect(10, 20, 30, 40); } +}; +template<> struct TestValueFactory<QMetaType::QRectF> { + static QRectF *create() { return new QRectF(10, 20, 30, 40); } +}; +template<> struct TestValueFactory<QMetaType::QSize> { + static QSize *create() { return new QSize(10, 20); } +}; +template<> struct TestValueFactory<QMetaType::QSizeF> { + static QSizeF *create() { return new QSizeF(10, 20); } +}; +template<> struct TestValueFactory<QMetaType::QLine> { + static QLine *create() { return new QLine(10, 20, 30, 40); } +}; +template<> struct TestValueFactory<QMetaType::QLineF> { + static QLineF *create() { return new QLineF(10, 20, 30, 40); } +}; +template<> struct TestValueFactory<QMetaType::QPoint> { + static QPoint *create() { return new QPoint(10, 20); } +}; +template<> struct TestValueFactory<QMetaType::QPointF> { + static QPointF *create() { return new QPointF(10, 20); } +}; +template<> struct TestValueFactory<QMetaType::QEasingCurve> { + static QEasingCurve *create() { return new QEasingCurve(QEasingCurve::InOutElastic); } +}; +template<> struct TestValueFactory<QMetaType::QUuid> { + static QUuid *create() { return new QUuid(); } +}; +template<> struct TestValueFactory<QMetaType::QModelIndex> { + static QModelIndex *create() { return new QModelIndex(); } +}; +template<> struct TestValueFactory<QMetaType::QPersistentModelIndex> { + static QPersistentModelIndex *create() { return new QPersistentModelIndex(); } +}; +template<> struct TestValueFactory<QMetaType::Nullptr> { + static std::nullptr_t *create() { return new std::nullptr_t; } +}; +template<> struct TestValueFactory<QMetaType::QRegularExpression> { + static QRegularExpression *create() + { +#if QT_CONFIG(regularexpression) + return new QRegularExpression("abc.*def"); +#else + return 0; +#endif + } +}; +template<> struct TestValueFactory<QMetaType::QJsonValue> { + static QJsonValue *create() { return new QJsonValue(123.); } +}; +template<> struct TestValueFactory<QMetaType::QJsonObject> { + static QJsonObject *create() { + QJsonObject *o = new QJsonObject(); + o->insert("a", 123.); + o->insert("b", true); + o->insert("c", QJsonValue::Null); + o->insert("d", QLatin1String("ciao")); + return o; + } +}; +template<> struct TestValueFactory<QMetaType::QJsonArray> { + static QJsonArray *create() { + QJsonArray *a = new QJsonArray(); + a->append(123.); + a->append(true); + a->append(QJsonValue::Null); + a->append(QLatin1String("ciao")); + return a; + } +}; +template<> struct TestValueFactory<QMetaType::QJsonDocument> { + static QJsonDocument *create() { + return new QJsonDocument( + QJsonDocument::fromJson("{ 'foo': 123, 'bar': [true, null, 'ciao'] }") + ); + } +}; + +template<> struct TestValueFactory<QMetaType::QCborSimpleType> { + static QCborSimpleType *create() { return new QCborSimpleType(QCborSimpleType::True); } +}; +template<> struct TestValueFactory<QMetaType::QCborValue> { + static QCborValue *create() { return new QCborValue(123.); } +}; +template<> struct TestValueFactory<QMetaType::QCborMap> { + static QCborMap *create() { + return new QCborMap{{0, 0}, {"Hello", 1}, {1, nullptr}}; + } +}; +template<> struct TestValueFactory<QMetaType::QCborArray> { + static QCborArray *create() { + return new QCborArray{0, 1, -2, 2.5, false, nullptr, "Hello", QByteArray("World") }; + } +}; + +template<> struct TestValueFactory<QMetaType::QVariant> { + static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); } +}; + +#endif // TST_QMETATYPE_H diff --git a/tests/auto/other/qvariant_common/tst_qvariant_common.h b/tests/auto/other/qvariant_common/tst_qvariant_common.h index 7851bf8dcc..70a44ad10f 100644 --- a/tests/auto/other/qvariant_common/tst_qvariant_common.h +++ b/tests/auto/other/qvariant_common/tst_qvariant_common.h @@ -72,11 +72,9 @@ protected: } QtMessageHandler oldMsgHandler; - static int currentId; - static bool ok; + inline static int currentId = {}; + inline static bool ok = {}; }; -bool MessageHandler::ok; -int MessageHandler::currentId; #define TST_QVARIANT_CANCONVERT_DATATABLE_HEADERS \ QTest::addColumn<QVariant>("val"); \ |