summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp')
-rw-r--r--tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp339
1 files changed, 162 insertions, 177 deletions
diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
index 333c7931d9..18e4e2a4a9 100644
--- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
+++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -1,32 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QTest>
+#include <QSignalSpy>
#include <QtCore/qlocale.h>
#include <private/qmetaobjectbuilder_p.h>
@@ -50,8 +26,6 @@ private slots:
void relatedMetaObject();
void staticMetacall();
void copyMetaObject();
- void serialize();
- void relocatableData();
void removeNotifySignal();
void usage_signal();
@@ -64,13 +38,28 @@ private slots:
void classNameFirstInStringData();
+ void propertyMetaType();
+
+ void cleanupTestCase();
+
+ void ownMetaTypeNoProperties();
+
private:
static bool checkForSideEffects
(const QMetaObjectBuilder& builder,
QMetaObjectBuilder::AddMembers members);
- static bool sameMetaObject
- (const QMetaObject *meta1, const QMetaObject *meta2);
+ QList<QMetaObject *> dynamicMetaObjectsPendingFree;
+};
+
+struct MetaObjectComparison {
+ bool isSame = false;
+ QString details;
+ operator bool() {return isSame;}
+
+ static inline auto Ok() {return MetaObjectComparison{true, QString()}; }
+ static inline auto Failed(QStringView message) {return MetaObjectComparison{false, message.toString()}; }
};
+MetaObjectComparison sameMetaObject(const QMetaObject *meta1, const QMetaObject *meta2);
// Dummy class that has something of every type of thing moc can generate.
class SomethingOfEverything : public QObject
@@ -85,7 +74,7 @@ class SomethingOfEverything : public QObject
Q_PROPERTY(SomethingFlagEnum fprop READ fprop)
Q_PROPERTY(QLocale::Language language READ language)
Q_ENUMS(SomethingEnum)
- Q_FLAGS(SomethingFlagEnum)
+ Q_FLAGS(SomethingFlag)
public:
Q_INVOKABLE SomethingOfEverything() {}
~SomethingOfEverything() {}
@@ -101,6 +90,7 @@ public:
XYZ = 1,
UVW = 8
};
+ Q_DECLARE_FLAGS(SomethingFlag, SomethingFlagEnum)
Q_INVOKABLE Q_SCRIPTABLE void method1() {}
@@ -193,8 +183,8 @@ void tst_QMetaObjectBuilder::flags()
QCOMPARE(builder.flags(), 0);
// Set flags
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- QCOMPARE(builder.flags(), QMetaObjectBuilder::DynamicMetaObject);
+ builder.setFlags(DynamicMetaObject);
+ QCOMPARE(builder.flags(), DynamicMetaObject);
}
void tst_QMetaObjectBuilder::method()
@@ -747,13 +737,12 @@ void tst_QMetaObjectBuilder::variantProperty()
QMetaObjectBuilder builder;
builder.addProperty("variant", "const QVariant &");
QMetaObject *meta = builder.toMetaObject();
+ dynamicMetaObjectsPendingFree.push_back(meta);
QMetaProperty prop = meta->property(meta->propertyOffset());
- QCOMPARE(QMetaType::Type(prop.type()), QMetaType::QVariant);
+ QCOMPARE(QMetaType::Type(prop.userType()), QMetaType::QVariant);
QCOMPARE(QMetaType::Type(prop.userType()), QMetaType::QVariant);
QCOMPARE(QByteArray(prop.typeName()), QByteArray("QVariant"));
-
- free(meta);
}
void tst_QMetaObjectBuilder::notifySignal()
@@ -790,6 +779,26 @@ void tst_QMetaObjectBuilder::notifySignal()
void tst_QMetaObjectBuilder::enumerator()
{
+ static const QtPrivate::QMetaTypeInterface fooFlagMetaType = {
+ 0,
+ 8,
+ 8,
+ QMetaType::IsEnumeration | QMetaType::IsUnsignedEnumeration | QMetaType::RelocatableType,
+ {},
+ nullptr,
+ "fooFlag",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ };
+
QMetaObjectBuilder builder;
// Add an enumerator and check its attributes.
@@ -821,6 +830,7 @@ void tst_QMetaObjectBuilder::enumerator()
enum1.setIsFlag(true);
enum1.setIsScoped(true);
enum1.setEnumName(QByteArrayLiteral("fooFlag"));
+ enum1.setMetaType(QMetaType(&fooFlagMetaType));
QCOMPARE(enum1.addKey("ABC", 0), 0);
QCOMPARE(enum1.addKey("DEF", 1), 1);
QCOMPARE(enum1.addKey("GHI", -1), 2);
@@ -830,6 +840,7 @@ void tst_QMetaObjectBuilder::enumerator()
QVERIFY(enum1.isFlag());
QVERIFY(enum1.isScoped());
QCOMPARE(enum1.enumName(), QByteArray("fooFlag"));
+ QCOMPARE(enum1.metaType(), QMetaType(&fooFlagMetaType));
QCOMPARE(enum1.keyCount(), 3);
QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC"));
@@ -997,106 +1008,23 @@ void tst_QMetaObjectBuilder::copyMetaObject()
{
QMetaObjectBuilder builder(&QObject::staticMetaObject);
QMetaObject *meta = builder.toMetaObject();
- QVERIFY(sameMetaObject(meta, &QObject::staticMetaObject));
- free(meta);
+ dynamicMetaObjectsPendingFree.push_back(meta);
+ auto compared = sameMetaObject(meta, &QObject::staticMetaObject);
+ QVERIFY2(compared, qPrintable(compared.details));
QMetaObjectBuilder builder2(&staticMetaObject);
meta = builder2.toMetaObject();
- QVERIFY(sameMetaObject(meta, &staticMetaObject));
- free(meta);
+ dynamicMetaObjectsPendingFree.push_back(meta);
+ compared = sameMetaObject(meta, &staticMetaObject);
+ QVERIFY2(compared, qPrintable(compared.details));
QMetaObjectBuilder builder3(&SomethingOfEverything::staticMetaObject);
meta = builder3.toMetaObject();
- QVERIFY(sameMetaObject(meta, &SomethingOfEverything::staticMetaObject));
- free(meta);
-}
-
-// Serialize and deserialize a meta object and check that
-// it round-trips to the exact same value.
-void tst_QMetaObjectBuilder::serialize()
-{
- // Full QMetaObjectBuilder
- {
- QMetaObjectBuilder builder(&SomethingOfEverything::staticMetaObject);
- QMetaObject *meta = builder.toMetaObject();
-
- QByteArray data;
- QDataStream stream(&data, QIODevice::WriteOnly | QIODevice::Append);
- builder.serialize(stream);
-
- QMetaObjectBuilder builder2;
- QDataStream stream2(data);
- QMap<QByteArray, const QMetaObject *> references;
- references.insert(QByteArray("QLocale"), &QLocale::staticMetaObject);
- builder2.deserialize(stream2, references);
- builder2.setStaticMetacallFunction(builder.staticMetacallFunction());
- QMetaObject *meta2 = builder2.toMetaObject();
-
- QVERIFY(sameMetaObject(meta, meta2));
- free(meta);
- free(meta2);
- }
-
- // Partial QMetaObjectBuilder
- {
- QMetaObjectBuilder builder;
- builder.setClassName("Test");
- builder.addProperty("foo", "int");
-
- QByteArray data;
- QDataStream stream(&data, QIODevice::WriteOnly | QIODevice::Append);
- builder.serialize(stream);
-
- QMetaObjectBuilder builder2;
- QDataStream stream2(data);
- builder2.deserialize(stream2, QMap<QByteArray, const QMetaObject *>());
-
- QCOMPARE(builder.superClass(), builder2.superClass());
- QCOMPARE(builder.className(), builder2.className());
- QCOMPARE(builder.propertyCount(), builder2.propertyCount());
- QCOMPARE(builder.property(0).name(), builder2.property(0).name());
- QCOMPARE(builder.property(0).type(), builder2.property(0).type());
- }
-}
-
-void tst_QMetaObjectBuilder::relocatableData()
-{
- QMetaObjectBuilder builder;
- builder.setClassName("TestObject");
-
- QMetaMethodBuilder intPropChanged = builder.addSignal("intPropChanged(int)");
- intPropChanged.setParameterNames(QList<QByteArray>() << "newIntPropValue");
-
- QMetaPropertyBuilder prop = builder.addProperty("intProp", "int");
- prop.setNotifySignal(intPropChanged);
-
- QMetaMethodBuilder voidSlotInt = builder.addSlot("voidSlotInt(int)");
- voidSlotInt.setParameterNames(QList<QByteArray>() << "slotIntArg");
-
- QMetaMethodBuilder listInvokableQRealQString = builder.addMethod("listInvokableQRealQString(qreal,QString)");
- listInvokableQRealQString.setReturnType("QVariantList");
- listInvokableQRealQString.setParameterNames(QList<QByteArray>() << "qrealArg" << "qstringArg");
-
- bool ok = false;
- QByteArray data = builder.toRelocatableData(&ok);
- QVERIFY(ok);
-
- QMetaObjectBuilder builder2;
- QMetaObject meta2;
- builder2.fromRelocatableData(&meta2, &QObject::staticMetaObject, data);
-
- QMetaObject *meta = builder.toMetaObject();
-
- QVERIFY(sameMetaObject(meta, &meta2));
-
- QVERIFY(!meta2.d.extradata);
- QVERIFY(!meta2.d.relatedMetaObjects);
- QVERIFY(!meta2.d.static_metacall);
-
- free(meta);
+ dynamicMetaObjectsPendingFree.push_back(meta);
+ compared = sameMetaObject(meta, &SomethingOfEverything::staticMetaObject);
+ QVERIFY2(compared, qPrintable(compared.details));
}
-
// Check that removing a method updates notify signals appropriately
void tst_QMetaObjectBuilder::removeNotifySignal()
{
@@ -1207,13 +1135,13 @@ static bool sameMethod(const QMetaMethod& method1, const QMetaMethod& method2)
return true;
}
-static bool sameProperty(const QMetaProperty& prop1, const QMetaProperty& prop2)
+static MetaObjectComparison sameProperty(const QMetaProperty& prop1, const QMetaProperty& prop2)
{
if (QByteArray(prop1.name()) != QByteArray(prop2.name()))
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Property names differ: %1 vs %2").arg(prop1.name(), prop2.name()));
if (QByteArray(prop1.typeName()) != QByteArray(prop2.typeName()))
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Property type names differ: %1 vs %2").arg(prop1.typeName(), prop2.typeName()));
if (prop1.isReadable() != prop2.isReadable() ||
prop1.isWritable() != prop2.isWritable() ||
@@ -1226,17 +1154,21 @@ static bool sameProperty(const QMetaProperty& prop1, const QMetaProperty& prop2)
prop1.isEnumType() != prop2.isEnumType() ||
prop1.hasNotifySignal() != prop2.hasNotifySignal() ||
prop1.hasStdCppSet() != prop2.hasStdCppSet())
- return false;
+ return MetaObjectComparison::Failed(u"Flags differ");
if (prop1.hasNotifySignal()) {
if (prop1.notifySignalIndex() != prop2.notifySignalIndex())
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Notify signal index differ: %1 vs %2").arg(
+ QString::number(prop1.notifySignalIndex()),
+ QString::number(prop2.notifySignalIndex())));
}
- if (prop1.revision() != prop2.revision())
- return false;
+ const int revision1 = prop1.revision();
+ const int revision2 = prop2.revision();
+ if (revision1 != revision2)
+ return MetaObjectComparison::Failed(QStringLiteral("Revisions differ: %1 vs %2").arg(QString::number(revision1), QString::number(revision2)));
- return true;
+ return MetaObjectComparison::Ok();
}
static bool sameEnumerator(const QMetaEnum& enum1, const QMetaEnum& enum2)
@@ -1264,69 +1196,89 @@ static bool sameEnumerator(const QMetaEnum& enum1, const QMetaEnum& enum2)
}
// Determine if two meta objects are identical.
-bool tst_QMetaObjectBuilder::sameMetaObject
- (const QMetaObject *meta1, const QMetaObject *meta2)
+MetaObjectComparison sameMetaObject(const QMetaObject *meta1, const QMetaObject *meta2)
{
int index;
- if (strcmp(meta1->className(), meta2->className()) != 0)
- return false;
+ if (strcmp(meta1->className(), meta2->className()) != 0) {
+ QString message = QLatin1String("Class names differ: %1 %2").arg(meta1->className(), meta2->className());
+ return MetaObjectComparison::Failed(message);
+ }
if (meta1->superClass() != meta2->superClass())
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Super classes differ"));
- if (meta1->constructorCount() != meta2->constructorCount() ||
- meta1->methodCount() != meta2->methodCount() ||
- meta1->enumeratorCount() != meta2->enumeratorCount() ||
- meta1->propertyCount() != meta2->propertyCount() ||
- meta1->classInfoCount() != meta2->classInfoCount())
- return false;
+ auto numCompare = [](int num1, int num2, const QString &message) {
+ if (num1 != num2)
+ return MetaObjectComparison::Failed(message.arg(QString::number(num1), QString::number(num2)));
+ return MetaObjectComparison::Ok();
+ };
+
+ auto compared = numCompare(meta1->constructorCount(), meta2->constructorCount(), QStringLiteral("Construct counts differ: %1 %2"));
+ if (!compared.isSame)
+ return compared;
+ compared = numCompare(meta1->methodCount(), meta2->methodCount(), QStringLiteral("Method counts differ: %1 %2"));
+ if (!compared.isSame)
+ return compared;
+ compared = numCompare(meta1->enumeratorCount(), meta2->enumeratorCount(), QStringLiteral("Enumerator counts differ: %1 %2"));
+ if (!compared.isSame)
+ return compared;
+ compared = numCompare(meta1->propertyCount(), meta2->propertyCount(), QStringLiteral("Property counts differ: %1 %2"));
+ if (!compared.isSame)
+ return compared;
+ compared = numCompare(meta1->classInfoCount(), meta2->classInfoCount(), QStringLiteral("ClassInfo counts differ: %1 %2"));
+ if (!compared.isSame)
+ return compared;
for (index = 0; index < meta1->constructorCount(); ++index) {
if (!sameMethod(meta1->constructor(index), meta2->constructor(index)))
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Constructors difer at index %1").arg(index));
}
for (index = 0; index < meta1->methodCount(); ++index) {
if (!sameMethod(meta1->method(index), meta2->method(index)))
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Methods difer at index %1").arg(index));
}
for (index = 0; index < meta1->propertyCount(); ++index) {
- if (!sameProperty(meta1->property(index), meta2->property(index)))
- return false;
+ if (auto compared = sameProperty(meta1->property(index), meta2->property(index)); !compared) {
+ compared.details += QStringLiteral(" at index %1").arg(index);
+ return compared;
+ }
}
for (index = 0; index < meta1->enumeratorCount(); ++index) {
if (!sameEnumerator(meta1->enumerator(index), meta2->enumerator(index)))
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Enumerators difer at index %1").arg(index));
}
for (index = 0; index < meta1->classInfoCount(); ++index) {
- if (QByteArray(meta1->classInfo(index).name()) !=
- QByteArray(meta2->classInfo(index).name()))
- return false;
- if (QByteArray(meta1->classInfo(index).value()) !=
- QByteArray(meta2->classInfo(index).value()))
- return false;
+ const auto name1= QByteArray(meta1->classInfo(index).name());
+ const auto name2= QByteArray(meta1->classInfo(index).name());
+ if (name1 != name2)
+ return MetaObjectComparison::Failed(QStringLiteral("Class infos difer at index %1: %2 vs %3").arg(QString::number(index), name1, name2));
+ const auto value1 = QByteArray(meta1->classInfo(index).value());
+ const auto value2= QByteArray(meta2->classInfo(index).value());
+ if ( value1 != value2)
+ return MetaObjectComparison::Failed(QStringLiteral("Class infos difer at index %1: %2 vs %3").arg(QString::number(index), value1, value2));
}
const auto *objects1 = meta1->d.relatedMetaObjects;
const auto *objects2 = meta2->d.relatedMetaObjects;
if (objects1 && !objects2)
- return false;
+ return MetaObjectComparison::Failed(u"Metaobject 1 had related metaobjects, but Metaoject 2 did not");
if (objects2 && !objects1)
- return false;
+ return MetaObjectComparison::Failed(u"Metaobject 2 had related metaobjects, but Metaoject 1 did not");
if (objects1 && objects2) {
while (*objects1 != 0 && *objects2 != 0) {
if (*objects1 != *objects2)
- return false;
+ return MetaObjectComparison::Failed(QStringLiteral("Related metaobjects differ at index %1").arg(index));
++objects1;
++objects2;
}
}
- return true;
+ return MetaObjectComparison::Ok();
}
@@ -1350,7 +1302,7 @@ private:
//Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged)
public:
- TestObject(QObject *parent = 0); // Q_INVOKABLE
+ TestObject(QObject *parent = nullptr); // Q_INVOKABLE
~TestObject();
// Property accessors
@@ -1529,9 +1481,7 @@ int TestObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
if (_id < ownMethodCount)
qt_static_metacall(this, _c, _id, _a);
_id -= ownMethodCount;
- }
-#ifndef QT_NO_PROPERTIES
- else if (_c == QMetaObject::ReadProperty) {
+ } else if (_c == QMetaObject::ReadProperty) {
void *_v = _a[0];
switch (_id) {
case 0: *reinterpret_cast< int*>(_v) = intProp(); break;
@@ -1554,7 +1504,6 @@ int TestObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
} else if (_c == QMetaObject::ResetProperty) {
_id -= ownPropertyCount;
}
-#endif // QT_NO_PROPERTIES
return _id;
}
@@ -1572,8 +1521,8 @@ void tst_QMetaObjectBuilder::usage_signal()
QSignalSpy propChangedSpy(testObject.data(), &TestObject::intPropChanged);
testObject->emitIntPropChanged();
- QCOMPARE(propChangedSpy.count(), 1);
- QCOMPARE(propChangedSpy.at(0).count(), 1);
+ QCOMPARE(propChangedSpy.size(), 1);
+ QCOMPARE(propChangedSpy.at(0).size(), 1);
QCOMPARE(propChangedSpy.at(0).at(0).toInt(), testObject->intProp());
}
@@ -1582,15 +1531,15 @@ void tst_QMetaObjectBuilder::usage_property()
QScopedPointer<TestObject> testObject(new TestObject);
QVariant prop = testObject->property("intProp");
- QCOMPARE(prop.type(), QVariant::Int);
+ QCOMPARE(prop.metaType(), QMetaType(QMetaType::Int));
QCOMPARE(prop.toInt(), testObject->intProp());
QSignalSpy propChangedSpy(testObject.data(), &TestObject::intPropChanged);
QVERIFY(testObject->intProp() != 123);
testObject->setProperty("intProp", 123);
- QCOMPARE(propChangedSpy.count(), 1);
+ QCOMPARE(propChangedSpy.size(), 1);
prop = testObject->property("intProp");
- QCOMPARE(prop.type(), QVariant::Int);
+ QCOMPARE(prop.metaType(), QMetaType(QMetaType::Int));
QCOMPARE(prop.toInt(), 123);
}
@@ -1618,9 +1567,9 @@ void tst_QMetaObjectBuilder::usage_method()
QVERIFY(listInvokableQRealQString.invoke(testObject.data(), Q_RETURN_ARG(QVariantList, list),
Q_ARG(qreal, 123.0), Q_ARG(QString, "ciao")));
QCOMPARE(list.size(), 2);
- QCOMPARE(list.at(0).type(), QVariant::Type(QMetaType::QReal));
+ QCOMPARE(list.at(0).metaType(), QMetaType(QMetaType::QReal));
QCOMPARE(list.at(0).toDouble(), double(123));
- QCOMPARE(list.at(1).type(), QVariant::String);
+ QCOMPARE(list.at(1).metaType(), QMetaType(QMetaType::QString));
QCOMPARE(list.at(1).toString(), QString::fromLatin1("ciao"));
}
@@ -1688,6 +1637,42 @@ void tst_QMetaObjectBuilder::classNameFirstInStringData()
free(mo);
}
+struct MyFoo {};
+struct myParameter {};
+
+void tst_QMetaObjectBuilder::propertyMetaType()
+{
+ qRegisterMetaType<myParameter>();
+ QMetaType meta = QMetaType::fromType<MyFoo>();
+ auto metaId = meta.id();
+ QMetaObjectBuilder builder;
+ builder.setClassName("Test");
+ builder.addProperty("myParameter", "MyFoo");
+ auto mo = builder.toMetaObject();
+
+ QMetaProperty metaProp = mo->property(mo->indexOfProperty("myParameter"));
+ QCOMPARE(metaProp.typeName(), meta.name());
+ QCOMPARE(metaProp.typeId(), metaId);
+ QCOMPARE(metaProp.metaType(), meta);
+ free(mo);
+}
+
+void tst_QMetaObjectBuilder::ownMetaTypeNoProperties()
+{
+ QMetaObjectBuilder builder;
+ builder.setClassName("NoProperties");
+ auto mo = builder.toMetaObject();
+ auto cleanup = qScopeGuard([&](){ free(mo); });
+ // own metatype should be invalid, as the dynamic metaobject has not been registered
+ QVERIFY(!mo->metaType().isValid());// should not crash
+}
+
+void tst_QMetaObjectBuilder::cleanupTestCase()
+{
+ for (QMetaObject *obj: dynamicMetaObjectsPendingFree)
+ free(obj);
+}
+
QTEST_MAIN(tst_QMetaObjectBuilder)
#include "tst_qmetaobjectbuilder.moc"