diff options
Diffstat (limited to 'tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h')
-rw-r--r-- | tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h | 566 |
1 files changed, 299 insertions, 267 deletions
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h index 3f00db5519..1694e49491 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h @@ -1,294 +1,326 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -// 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 +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> +#include "tst_qmetatype_common.h" +#include "tst_qvariant_common.h" -template <int ID> -struct DefaultValueFactory +struct Derived : QObject { - typedef typename MetaEnumToType<ID>::Type Type; - static Type *create() { return new Type; } + Q_OBJECT }; -template <> -struct DefaultValueFactory<QMetaType::Void> +struct MessageHandlerCustom : public MessageHandler { - typedef MetaEnumToType<QMetaType::Void>::Type Type; - static Type *create() { return 0; } + 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; }; -template <int ID> -struct DefaultValueTraits +class tst_QMetaType: public QObject { - // 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 }; -}; + Q_OBJECT + Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp) -#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 +public: + struct GadgetPropertyType { + QByteArray type; + QByteArray name; + QVariant testData; + }; -template <int ID> -struct TestValueFactory {}; + tst_QMetaType() { propList << 42 << "Hello"; } -template<> struct TestValueFactory<QMetaType::Void> { - static void *create() { return 0; } -}; + QList<QVariant> prop() const { return propList; } + void setProp(const QList<QVariant> &list) { propList = list; } -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::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; } +private: + void registerGadget(const char * name, const QList<GadgetPropertyType> &gadgetProperties); + QList<QVariant> propList; + +private slots: + void defined(); +#if QT_CONFIG(thread) + void threadSafety(); +#endif + 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 flags2_data(); + void flags2(); + void flagsBinaryCompatibility6_0_data(); + void flagsBinaryCompatibility6_0(); + void construct_data(); + void construct(); + void defaultConstructTrivial_QTBUG_109594(); + void typedConstruct(); + void constructCopy_data(); + void constructCopy(); + void selfCompare_data(); + void selfCompare(); + void typedefs(); + void registerType(); + void isRegistered_data(); + void isRegistered(); + void isRegisteredStaticLess_data(); + void isRegisteredStaticLess(); + void isNotRegistered(); + void isEnum(); + void underlyingType_data(); + void underlyingType(); + void automaticTemplateRegistration_1(); + void automaticTemplateRegistration_2(); // defined in tst_qmetatype3.cpp + 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 convertConstNonConst(); + void compareCustomEqualOnlyType(); + void customDebugStream(); + void unknownType(); + void fromType(); + void operatorEq_data(); + void operatorEq(); + void operatorEq2_data(); + void operatorEq2(); + void operatorEqAcrossLibs_data(); + void operatorEqAcrossLibs(); + void typesWithInaccessibleDTors(); + void voidIsNotUnknown(); + void typeNameNormalization(); + void typeNameInQtPrivate(); + + // Tests for deprecated APIs +#if QT_DEPRECATED_SINCE(6, 0) + void testDeprecatedGetters_data() { type_data(); } + void testDeprecatedGetters(); + void testDeprecatedLoadSave_data() { saveAndLoadBuiltin_data(); } + void testDeprecatedLoadSave(); +#endif }; -template<> struct TestValueFactory<QMetaType::QRegularExpression> { - static QRegularExpression *create() - { -#if QT_CONFIG(regularexpression) - return new QRegularExpression("abc.*def"); -#else - return 0; + +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 - } + +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); } }; -template<> struct TestValueFactory<QMetaType::QJsonValue> { - static QJsonValue *create() { return new QJsonValue(123.); } + +struct CustomConvertibleType2 +{ + // implicit + CustomConvertibleType2(const CustomConvertibleType &t = CustomConvertibleType()) + : m_foo(t.m_foo) {} + virtual ~CustomConvertibleType2() {} + + QVariant m_foo; + + 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); } }; -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; + +struct CustomDebugStreamableType +{ + QString toString() const { return "test"; } + + friend QDebug operator<<(QDebug dbg, const CustomDebugStreamableType&) + { + return dbg << "string-content"; } }; -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; - } + +struct CustomDebugStreamableType2 +{ + QString toString() const { return "test"; } }; -template<> struct TestValueFactory<QMetaType::QJsonDocument> { - static QJsonDocument *create() { - return new QJsonDocument( - QJsonDocument::fromJson("{ 'foo': 123, 'bar': [true, null, 'ciao'] }") - ); - } + +struct CustomEqualsOnlyType +{ + explicit CustomEqualsOnlyType(int value = 0) : val(value) {} + virtual ~CustomEqualsOnlyType() {} + + int val; + + 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::QCborSimpleType> { - static QCborSimpleType *create() { return new QCborSimpleType(QCborSimpleType::True); } +static_assert(QTypeTraits::has_operator_equal_v<CustomEqualsOnlyType>); +static_assert(!QTypeTraits::has_operator_less_than_v<CustomEqualsOnlyType>); + +struct BaseGadgetType +{ + Q_GADGET +public: + explicit BaseGadgetType(QVariant foo = QVariant()) : m_foo(std::move(foo)) {} + QVariant m_foo; }; -template<> struct TestValueFactory<QMetaType::QCborValue> { - static QCborValue *create() { return new QCborValue(123.); } + +struct DerivedGadgetType : public BaseGadgetType +{ + Q_GADGET +public: + explicit DerivedGadgetType(QVariant foo = QVariant()) : BaseGadgetType(std::move(foo)) {} + int bar = 25; }; -template<> struct TestValueFactory<QMetaType::QCborMap> { - static QCborMap *create() { - return new QCborMap{{0, 0}, {"Hello", 1}, {1, nullptr}}; - } + +Q_DECLARE_METATYPE(CustomConvertibleType); +Q_DECLARE_METATYPE(CustomConvertibleType2); +Q_DECLARE_METATYPE(CustomDebugStreamableType); +Q_DECLARE_METATYPE(CustomEqualsOnlyType); + +struct CustomMovable { + CustomMovable() {} + + 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; } }; -template<> struct TestValueFactory<QMetaType::QCborArray> { - static QCborArray *create() { - return new QCborArray{0, 1, -2, 2.5, false, nullptr, "Hello", QByteArray("World") }; + +#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); + +#define FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \ + F(bool) \ + F(int) \ + F(qulonglong) \ + F(double) \ + F(short) \ + F(char) \ + F(ulong) \ + F(uchar) \ + F(float) \ + F(QObject*) \ + F(QString) \ + F(CustomMovable) + +#define FOR_EACH_STATIC_PRIMITIVE_TYPE2(F, SecondaryRealName) \ + F(uint, SecondaryRealName) \ + F(qlonglong, SecondaryRealName) \ + F(char, SecondaryRealName) \ + F(uchar, SecondaryRealName) \ + F(QObject*, SecondaryRealName) + +#define CREATE_AND_VERIFY_CONTAINER(CONTAINER, ...) \ + { \ + CONTAINER< __VA_ARGS__ > t; \ + const QVariant v = QVariant::fromValue(t); \ + QByteArray tn = createTypeName(#CONTAINER "<", #__VA_ARGS__); \ + const int expectedType = ::qMetaTypeId<CONTAINER< __VA_ARGS__ > >(); \ + const int type = QMetaType::fromName(tn).id(); \ + QCOMPARE(type, expectedType); \ + QCOMPARE((QMetaType::fromType<CONTAINER< __VA_ARGS__ >>().id()), expectedType); \ } -}; -template<> struct TestValueFactory<QMetaType::QVariant> { - static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); } -}; +#define FOR_EACH_1ARG_TEMPLATE_TYPE(F, TYPE) \ + F(QList, TYPE) \ + F(QQueue, TYPE) \ + F(QStack, TYPE) \ + F(QSet, TYPE) + +#define PRINT_1ARG_TEMPLATE(RealName) \ + FOR_EACH_1ARG_TEMPLATE_TYPE(CREATE_AND_VERIFY_CONTAINER, RealName) + +#define FOR_EACH_2ARG_TEMPLATE_TYPE(F, RealName1, RealName2) \ + F(QHash, RealName1, RealName2) \ + F(QMap, RealName1, RealName2) \ + F(std::pair, RealName1, RealName2) + +#define PRINT_2ARG_TEMPLATE_INTERNAL(RealName1, RealName2) \ + FOR_EACH_2ARG_TEMPLATE_TYPE(CREATE_AND_VERIFY_CONTAINER, RealName1, RealName2) + +#define PRINT_2ARG_TEMPLATE(RealName) \ + FOR_EACH_STATIC_PRIMITIVE_TYPE2(PRINT_2ARG_TEMPLATE_INTERNAL, RealName) + +#define REGISTER_TYPEDEF(TYPE, ARG1, ARG2) \ + qRegisterMetaType<TYPE <ARG1, ARG2>>(#TYPE "<" #ARG1 "," #ARG2 ">"); + +static inline QByteArray createTypeName(const char *begin, const char *va) +{ + QByteArray tn(begin); + const QList<QByteArray> args = QByteArray(va).split(','); + tn += args.first().trimmed(); + if (args.size() > 1) { + QList<QByteArray>::const_iterator it = args.constBegin() + 1; + const QList<QByteArray>::const_iterator end = args.constEnd(); + for (; it != end; ++it) { + tn += ","; + tn += it->trimmed(); + } + } + if (tn.endsWith('>')) + tn += ' '; + tn += '>'; + return tn; +} -#endif // TST_QMETATYPE_H +Q_DECLARE_METATYPE(const void*) |