diff options
Diffstat (limited to 'tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp')
-rw-r--r-- | tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp | 298 |
1 files changed, 240 insertions, 58 deletions
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index 02399fdcdf..04c2a5bfdb 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qstandardpaths.h> #include <qtest.h> @@ -36,13 +11,16 @@ #include <private/qqmlmetatype_p.h> #include <private/qqmlpropertyvalueinterceptor_p.h> #include <private/qqmlengine_p.h> -#include "../../shared/util.h" +#include <private/qqmlanybinding_p.h> +#include <QtQuickTestUtils/private/qmlutils_p.h> + +using namespace Qt::StringLiterals; class tst_qqmlmetatype : public QQmlDataTest { Q_OBJECT public: - tst_qqmlmetatype() {} + tst_qqmlmetatype() : QQmlDataTest(QT_QMLTEST_DATADIR) {} private slots: void initTestCase() override; @@ -57,6 +35,8 @@ private slots: void compositeType(); void externalEnums(); + void interceptorAPI(); + void isList(); void defaultObject(); @@ -69,6 +49,11 @@ private slots: void enumsInRecursiveImport_data(); void enumsInRecursiveImport(); + + void revertValueTypeAnimation(); + + void clearPropertyCaches(); + void builtins(); }; class TestType : public QObject @@ -116,8 +101,8 @@ QObject *testTypeProvider(QQmlEngine *engine, QJSEngine *scriptEngine) class ParserStatusTestType : public QObject, public QQmlParserStatus { Q_OBJECT - void classBegin(){} - void componentComplete(){} + void classBegin() override {} + void componentComplete() override {} Q_CLASSINFO("DefaultProperty", "foo") // Missing default property Q_INTERFACES(QQmlParserStatus) }; @@ -128,7 +113,7 @@ class ValueSourceTestType : public QObject, public QQmlPropertyValueSource Q_OBJECT Q_INTERFACES(QQmlPropertyValueSource) public: - virtual void setTarget(const QQmlProperty &) {} + void setTarget(const QQmlProperty &) override {} }; QML_DECLARE_TYPE(ValueSourceTestType); @@ -137,8 +122,8 @@ class ValueInterceptorTestType : public QObject, public QQmlPropertyValueInterce Q_OBJECT Q_INTERFACES(QQmlPropertyValueInterceptor) public: - virtual void setTarget(const QQmlProperty &) {} - virtual void write(const QVariant &) {} + void setTarget(const QQmlProperty &) override {} + void write(const QVariant &) override {} }; QML_DECLARE_TYPE(ValueInterceptorTestType); @@ -157,14 +142,14 @@ void tst_qqmlmetatype::initTestCase() void tst_qqmlmetatype::qmlParserStatusCast() { - QVERIFY(!QQmlMetaType::qmlType(QMetaType::Int).isValid()); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid()); - QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).parserStatusCast(), -1); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).isValid()); - QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).parserStatusCast(), -1); + QVERIFY(!QQmlMetaType::qmlType(QMetaType::fromType<int>()).isValid()); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<TestType *>()).isValid()); + QCOMPARE(QQmlMetaType::qmlType(QMetaType::fromType<TestType *>()).parserStatusCast(), -1); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<ValueSourceTestType *>()).isValid()); + QCOMPARE(QQmlMetaType::qmlType(QMetaType::fromType<ValueSourceTestType *>()).parserStatusCast(), -1); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid()); - int cast = QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).parserStatusCast(); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<ParserStatusTestType *>()).isValid()); + int cast = QQmlMetaType::qmlType(QMetaType::fromType<ParserStatusTestType *>()).parserStatusCast(); QVERIFY(cast != -1); QVERIFY(cast != 0); @@ -177,14 +162,14 @@ void tst_qqmlmetatype::qmlParserStatusCast() void tst_qqmlmetatype::qmlPropertyValueSourceCast() { - QVERIFY(!QQmlMetaType::qmlType(QMetaType::Int).isValid()); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid()); - QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).propertyValueSourceCast(), -1); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid()); - QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).propertyValueSourceCast(), -1); + QVERIFY(!QQmlMetaType::qmlType(QMetaType::fromType<int>()).isValid()); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<TestType *>()).isValid()); + QCOMPARE(QQmlMetaType::qmlType(QMetaType::fromType<TestType *>()).propertyValueSourceCast(), -1); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<ParserStatusTestType *>()).isValid()); + QCOMPARE(QQmlMetaType::qmlType(QMetaType::fromType<ParserStatusTestType *>()).propertyValueSourceCast(), -1); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).isValid()); - int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueSourceTestType *>()).propertyValueSourceCast(); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<ValueSourceTestType *>()).isValid()); + int cast = QQmlMetaType::qmlType(QMetaType::fromType<ValueSourceTestType *>()).propertyValueSourceCast(); QVERIFY(cast != -1); QVERIFY(cast != 0); @@ -197,14 +182,14 @@ void tst_qqmlmetatype::qmlPropertyValueSourceCast() void tst_qqmlmetatype::qmlPropertyValueInterceptorCast() { - QVERIFY(!QQmlMetaType::qmlType(QMetaType::Int).isValid()); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).isValid()); - QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<TestType *>()).propertyValueInterceptorCast(), -1); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).isValid()); - QCOMPARE(QQmlMetaType::qmlType(qMetaTypeId<ParserStatusTestType *>()).propertyValueInterceptorCast(), -1); + QVERIFY(!QQmlMetaType::qmlType(QMetaType::fromType<int>()).isValid()); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<TestType *>()).isValid()); + QCOMPARE(QQmlMetaType::qmlType(QMetaType::fromType<TestType *>()).propertyValueInterceptorCast(), -1); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<ParserStatusTestType *>()).isValid()); + QCOMPARE(QQmlMetaType::qmlType(QMetaType::fromType<ParserStatusTestType *>()).propertyValueInterceptorCast(), -1); - QVERIFY(QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>()).isValid()); - int cast = QQmlMetaType::qmlType(qMetaTypeId<ValueInterceptorTestType *>()).propertyValueInterceptorCast(); + QVERIFY(QQmlMetaType::qmlType(QMetaType::fromType<ValueInterceptorTestType *>()).isValid()); + int cast = QQmlMetaType::qmlType(QMetaType::fromType<ValueInterceptorTestType *>()).propertyValueInterceptorCast(); QVERIFY(cast != -1); QVERIFY(cast != 0); @@ -257,9 +242,9 @@ void tst_qqmlmetatype::prettyTypeName() void tst_qqmlmetatype::isList() { - QCOMPARE(QQmlMetaType::isList(QMetaType::UnknownType), false); - QCOMPARE(QQmlMetaType::isList(QMetaType::Int), false); - QCOMPARE(QQmlMetaType::isList(qMetaTypeId<QQmlListProperty<TestType> >()), true); + QCOMPARE(QQmlMetaType::isList(QMetaType {}), false); + QCOMPARE(QQmlMetaType::isList(QMetaType::fromType<int>()), false); + QCOMPARE(QQmlMetaType::isList(QMetaType::fromType<QQmlListProperty<TestType> >()), true); } void tst_qqmlmetatype::defaultObject() @@ -337,6 +322,60 @@ void tst_qqmlmetatype::externalEnums() } +class ForwardAndLogInterceptor : public QObject, public QQmlPropertyValueInterceptor { + Q_OBJECT + Q_INTERFACES(QQmlPropertyValueInterceptor) +public: + + // QQmlPropertyValueInterceptor interface + void setTarget(const QQmlProperty &property) override + { + m_property = property; + } + void write(const QVariant &value) override + { + interceptedWrite = true; + QQmlPropertyPrivate::write(m_property, value, QQmlPropertyData::BypassInterceptor); + } + bool bindable(QUntypedBindable *bindable, QUntypedBindable target) override + { + interceptedBindable = true; + *bindable = target; + return true; + } + + QQmlProperty m_property; + bool interceptedBindable = false; + bool interceptedWrite = false; +}; + +void tst_qqmlmetatype::interceptorAPI() +{ + qmlRegisterType<ForwardAndLogInterceptor>("test", 1, 0, "Interceptor"); + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("interceptorApi.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + + auto interceptor = obj->property("i").value<ForwardAndLogInterceptor *>(); + QVERIFY(interceptor->interceptedBindable); + QVERIFY(interceptor->interceptedWrite); + + QQmlProperty objectName(obj.get(), "objectName"); + QProperty<QString> hello(u"Hello, World!"_s); + QQmlAnyBinding binding; + binding = Qt::makePropertyBinding(hello); + interceptor->interceptedBindable = false; + binding.installOn(objectName, QQmlAnyBinding::RespectInterceptors); + QVERIFY(interceptor->interceptedBindable); + binding = QQmlAnyBinding::takeFrom(objectName); + objectName.write("bar"); + interceptor->interceptedBindable = false; + binding.installOn(objectName, QQmlAnyBinding::IgnoreInterceptors); + QVERIFY(!interceptor->interceptedBindable); + QCOMPARE(objectName.read().toString(), hello.value()); +} + class Controller1 : public QObject { Q_OBJECT @@ -573,6 +612,7 @@ class Grouped : public QObject { Q_OBJECT Q_PROPERTY(int prop READ prop WRITE setProp NOTIFY propChanged REVISION 1) + Q_PROPERTY(int prop2 READ prop WRITE setProp NOTIFY prop2Changed REVISION 2) public: int prop() const { return m_prop; } void setProp(int prop) @@ -580,11 +620,13 @@ public: if (prop != m_prop) { m_prop = prop; emit propChanged(prop); + emit prop2Changed(prop); } } signals: Q_REVISION(1) void propChanged(int prop); + Q_REVISION(2) void prop2Changed(int prop); private: int m_prop = 0; @@ -602,13 +644,24 @@ private: QScopedPointer<Grouped> m_grouped; }; +class MyRevisioned : public MyItem +{ + Q_OBJECT + Q_PROPERTY(int revisioned READ revisioned CONSTANT REVISION 1) +public: + int revisioned() const { return 12; } +}; + void tst_qqmlmetatype::revisionedGroupedProperties() { qmlClearTypeRegistrations(); qmlRegisterType<MyItem>("GroupedTest", 1, 0, "MyItem"); qmlRegisterType<MyItem, 1>("GroupedTest", 1, 1, "MyItem"); + qmlRegisterType<MyRevisioned>("GroupedTest", 1, 0, "MyRevisioned"); + qmlRegisterType<MyRevisioned, 1>("GroupedTest", 1, 1, "MyRevisioned"); qmlRegisterUncreatableType<Grouped>("GroupedTest", 1, 0, "Grouped", "Grouped"); qmlRegisterUncreatableType<Grouped, 1>("GroupedTest", 1, 1, "Grouped", "Grouped"); + qmlRegisterUncreatableType<Grouped, 2>("GroupedTest", 1, 2, "Grouped", "Grouped"); { QQmlEngine engine; @@ -623,6 +676,15 @@ void tst_qqmlmetatype::revisionedGroupedProperties() QQmlComponent invalid(&engine, testFileUrl("revisionedGroupedPropertiesInvalid.qml")); QVERIFY(invalid.isError()); } + + { + QQmlEngine engine; + QQmlComponent unversioned( + &engine, testFileUrl("revisionedGroupedPropertiesUnversioned.qml")); + QVERIFY2(unversioned.isReady(), qPrintable(unversioned.errorString())); + QScopedPointer<QObject> obj(unversioned.create()); + QVERIFY(!obj.isNull()); + } } void tst_qqmlmetatype::enumsInRecursiveImport_data() @@ -654,6 +716,126 @@ void tst_qqmlmetatype::enumsInRecursiveImport() QTRY_COMPARE(obj->property("color").toString(), QString("green")); } +void tst_qqmlmetatype::revertValueTypeAnimation() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("animationOnValueType.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QScopedPointer<QObject> o(c.create()); + QTRY_COMPARE(o->property("letterSpacing").toDouble(), 24.0); + QCOMPARE(o->property("pointSize").toDouble(), 12.0); +} + +void tst_qqmlmetatype::clearPropertyCaches() +{ + qmlClearTypeRegistrations(); + qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "A"); + QQmlPropertyCache::ConstPtr oldCache = QQmlMetaType::propertyCache(&TestType::staticMetaObject); + QVERIFY(oldCache); + qmlClearTypeRegistrations(); + qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "B"); + QQmlPropertyCache::ConstPtr newCache = QQmlMetaType::propertyCache(&TestType::staticMetaObject); + QVERIFY(oldCache.data() != newCache.data()); +} + +template<typename T> +void checkBuiltinBaseType() +{ + const QQmlType type = QQmlMetaType::qmlType(QMetaType::fromType<T>()); + QVERIFY(type.isValid()); + QCOMPARE(type.typeId(), QMetaType::fromType<T>()); + QCOMPARE(type.qListTypeId(), QMetaType::fromType<QList<T>>()); +} + +template<typename T> +void checkBuiltinListType() +{ + const QQmlType listType = QQmlMetaType::qmlListType(QMetaType::fromType<QList<T>>()); + QVERIFY(listType.isValid()); + QVERIFY(listType.isSequentialContainer()); + QCOMPARE(listType.typeId(), QMetaType::fromType<T>()); + QCOMPARE(listType.qListTypeId(), QMetaType::fromType<QList<T>>()); + QCOMPARE(listType.listMetaSequence().valueMetaType(), QMetaType::fromType<T>()); +} + +template<typename... T> +void checkBuiltinTypes() +{ + (checkBuiltinBaseType<T>(), ...); + (checkBuiltinListType<T>(), ...); +} + +template<typename T> +void checkNamedBuiltin(const QString &name) +{ + const QQmlType expected = QQmlMetaType::qmlType(QMetaType::fromType<T>()); + const QQmlType actual = QQmlMetaType::qmlType("QML/" + name, QTypeRevision::fromVersion(1, 0)); + if (actual != expected) { + qWarning() << Q_FUNC_INFO << "looking for" << name; + qWarning() << "found" << actual.module() << actual.elementName() << actual.version() + << actual.typeId(); + qWarning() << "expected" << expected.module() << expected.elementName() + << expected.version() << expected.typeId(); + QFAIL("mismatch"); + } +} + +template<typename T> +void checkObjectBuiltin(const QString &name) +{ + const QQmlType objectType = QQmlMetaType::qmlType(QMetaType::fromType<T *>()); + QVERIFY(objectType.isValid()); + QCOMPARE(objectType.typeId(), QMetaType::fromType<T *>()); + QCOMPARE(objectType.qListTypeId(), QMetaType::fromType<QQmlListProperty<T>>()); + + const QQmlType listType = QQmlMetaType::qmlListType(QMetaType::fromType<QQmlListProperty<T>>()); + QVERIFY(listType.isValid()); + QCOMPARE(listType.typeId(), QMetaType::fromType<T *>()); + QCOMPARE(listType.qListTypeId(), QMetaType::fromType<QQmlListProperty<T>>()); + + checkNamedBuiltin<T *>(name); +} + +void tst_qqmlmetatype::builtins() +{ + qmlClearTypeRegistrations(); + QQmlEngine engine; // registers the builtins + + checkBuiltinTypes< + QVariant, QJSValue, qint8, quint8, short, ushort, int, uint, qlonglong, qulonglong, float, + double, QChar, QString, bool, QDateTime, QDate, QTime, QUrl, QByteArray>(); + + checkNamedBuiltin<QVariant>("var"); + checkNamedBuiltin<QVariant>("variant"); + checkNamedBuiltin<int>("int"); + checkNamedBuiltin<double>("double"); + checkNamedBuiltin<double>("real"); + checkNamedBuiltin<QString>("string"); + checkNamedBuiltin<bool>("bool"); + checkNamedBuiltin<QDateTime>("date"); + checkNamedBuiltin<QUrl>("url"); + +#if QT_CONFIG(regularexpression) + checkBuiltinBaseType<QRegularExpression>(); + checkBuiltinListType<QRegularExpression>(); + checkNamedBuiltin<QRegularExpression>("regexp"); +#endif + + // Can't retrieve this one by metatype + const QQmlType voidType = QQmlMetaType::qmlType("QML/void", QTypeRevision::fromVersion(1, 0)); + QVERIFY(voidType.isValid()); + QCOMPARE(voidType.typeId(), QMetaType()); + QCOMPARE(voidType.qListTypeId(), QMetaType()); + + // No separate list types + checkBuiltinBaseType<std::nullptr_t>(); + checkBuiltinBaseType<QVariantMap>(); + + checkObjectBuiltin<QObject>("QtObject"); + checkObjectBuiltin<QQmlComponent>("Component"); +} + QTEST_MAIN(tst_qqmlmetatype) #include "tst_qqmlmetatype.moc" |