summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-08-10 10:07:08 -0700
committerThiago Macieira <thiago.macieira@intel.com>2023-08-14 20:19:36 -0700
commit56bd5d60c9fb9b9078847e4c4919956af3cbf08a (patch)
tree05045c4792407f4aee96d8d2fcaf675276dc74e5
parent7a1ffacca0096125603b99a58f651c322468db27 (diff)
Fix registration of QtDBus types' metatypes
By actually registering them. Commit 850d850c5af8ff77a4b9d53457ec6b1ba6c20cb3 changed from qMetaTypeId<QDBusArgument>() to QMetaType::fromType<QDBusArgument>() and in Qt 6, fromType() does not register the type with the database. That means the lines became runtime no-ops at that time or during the QMetaType updates since 6.0. All they did was instantiate the C++ inline variable. The testing also detected we didn't register QList<QDBusVariant> as an alias for the "av" signature. I'm not entirely sure you're allowed to use this because QtDBus does not like re-registration of the built-in types, and "av" is already assigned to QVariantList. This is no trouble for the parser, anyway. Minor change to qdbuscpp2xml to allow reading from stdin, so we don't have to create temporary files. Pick-to: 6.5 6.6 Fixes: QTBUG-115964 Change-Id: I80612a7d275c41f1baf0fffd177a14925e7d23ac Reviewed-by: Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>
-rw-r--r--src/dbus/qdbusmetatype.cpp20
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp14
-rw-r--r--tests/auto/tools/qdbuscpp2xml/CMakeLists.txt2
-rw-r--r--tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp77
4 files changed, 99 insertions, 14 deletions
diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp
index 0a0139aaed..5fe5a60a3a 100644
--- a/src/dbus/qdbusmetatype.cpp
+++ b/src/dbus/qdbusmetatype.cpp
@@ -53,14 +53,14 @@ void QDBusMetaTypeId::init()
// reentrancy is not a problem since everything else is locked on their own
// set the guard variable at the end
if (!initialized.loadRelaxed()) {
- // register our types with Qt Core (calling qMetaTypeId<T>() does this implicitly)
- (void)message();
- (void)argument();
- (void)variant();
- (void)objectpath();
- (void)signature();
- (void)error();
- (void)unixfd();
+ // register our types with Qt Core
+ message().registerType();
+ argument().registerType();
+ variant().registerType();
+ objectpath().registerType();
+ signature().registerType();
+ error().registerType();
+ unixfd().registerType();
#ifndef QDBUS_NO_SPECIALTYPES
// and register Qt Core's with us
@@ -78,7 +78,6 @@ void QDBusMetaTypeId::init()
qDBusRegisterMetaType<QVariantList>();
qDBusRegisterMetaType<QVariantMap>();
qDBusRegisterMetaType<QVariantHash>();
- qDBusRegisterMetaType<QDBusObjectPath>();
qDBusRegisterMetaType<QList<bool> >();
qDBusRegisterMetaType<QList<short> >();
@@ -88,6 +87,9 @@ void QDBusMetaTypeId::init()
qDBusRegisterMetaType<QList<qlonglong> >();
qDBusRegisterMetaType<QList<qulonglong> >();
qDBusRegisterMetaType<QList<double> >();
+
+ // plus lists of our own types
+ qDBusRegisterMetaType<QList<QDBusVariant> >();
qDBusRegisterMetaType<QList<QDBusObjectPath> >();
qDBusRegisterMetaType<QList<QDBusSignature> >();
qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
index 295a60c01a..7182e923f3 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -433,12 +433,20 @@ int main(int argc, char **argv)
QList<ClassDef> classes;
+ if (args.isEmpty())
+ args << u"-"_s;
for (const auto &arg: std::as_const(args)) {
- if (arg.startsWith(u'-'))
+ if (arg.startsWith(u'-') && arg.size() > 1)
continue;
- QFile f(arg);
- if (!f.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ QFile f;
+ if (arg == u'-') {
+ f.open(stdin, QIODevice::ReadOnly | QIODevice::Text);
+ } else {
+ f.setFileName(arg);
+ f.open(QIODevice::ReadOnly | QIODevice::Text);
+ }
+ if (!f.isOpen()) {
fprintf(stderr, PROGRAMNAME ": could not open '%s': %s\n",
qPrintable(arg), qPrintable(f.errorString()));
return 1;
diff --git a/tests/auto/tools/qdbuscpp2xml/CMakeLists.txt b/tests/auto/tools/qdbuscpp2xml/CMakeLists.txt
index 557cf57537..ef35bcd34d 100644
--- a/tests/auto/tools/qdbuscpp2xml/CMakeLists.txt
+++ b/tests/auto/tools/qdbuscpp2xml/CMakeLists.txt
@@ -16,7 +16,7 @@ qt_internal_add_test(tst_qdbuscpp2xml
test1.h
tst_qdbuscpp2xml.cpp
LIBRARIES
- Qt::DBus
+ Qt::DBusPrivate
)
# Resources:
diff --git a/tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp b/tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp
index 7282ff85b0..973c3587d2 100644
--- a/tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp
+++ b/tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp
@@ -5,9 +5,11 @@
#include <QLibraryInfo>
#include <QProcess>
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/private/dbus_minimal_p.h>
+
#include "test1.h"
-#include <QtDBus/QDBusConnection>
// in qdbusxmlgenerator.cpp
QT_BEGIN_NAMESPACE
@@ -32,6 +34,8 @@ class tst_qdbuscpp2xml : public QObject
private slots:
void qdbuscpp2xml_data();
void qdbuscpp2xml();
+ void qtdbusTypes_data();
+ void qtdbusTypes();
void initTestCase();
void cleanupTestCase();
@@ -138,6 +142,77 @@ void tst_qdbuscpp2xml::qdbuscpp2xml()
QCOMPARE(out, expected);
}
+void tst_qdbuscpp2xml::qtdbusTypes_data()
+{
+ QTest::addColumn<QByteArray>("type");
+ QTest::addColumn<QByteArray>("expectedSignature");
+ auto addRow = [](QByteArray type, QByteArray signature) {
+ QTest::addRow("%s", type.constData()) << type << signature;
+
+ // lists and vectors
+ QTest::addRow("QList-%s", type.constData())
+ << "QList<" + type + '>' << DBUS_TYPE_ARRAY + signature;
+ QTest::addRow("QVector-%s", type.constData())
+ << "QVector<" + type + '>' << DBUS_TYPE_ARRAY + signature;
+ };
+ addRow("QDBusVariant", DBUS_TYPE_VARIANT_AS_STRING);
+ addRow("QDBusObjectPath", DBUS_TYPE_OBJECT_PATH_AS_STRING);
+ addRow("QDBusSignature", DBUS_TYPE_SIGNATURE_AS_STRING);
+ addRow("QDBusUnixFileDescriptor", DBUS_TYPE_UNIX_FD_AS_STRING);
+
+ // QDBusMessage is not a type, but must be recognized
+ QTest::newRow("QDBusMessage") << QByteArray("QDBusMessage") << QByteArray();
+}
+
+void tst_qdbuscpp2xml::qtdbusTypes()
+{
+ static const char cppSkeleton[] = R"(
+class QDBusVariantBugRepro : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.qtproject.test")
+public Q_SLOTS:
+ void method(const @TYPE@ &);
+};)";
+ static const char methodXml[] = R"(<method name="method")";
+ static const char expectedSkeleton[] = R"(<arg type="@S@" direction="in"/>)";
+
+ QFETCH(QByteArray, type);
+ QFETCH(QByteArray, expectedSignature);
+
+ const QString binpath = QLibraryInfo::path(QLibraryInfo::BinariesPath);
+ const QString command = binpath + QLatin1String("/qdbuscpp2xml");
+ QProcess process;
+ process.start(command);
+
+ process.write(QByteArray(cppSkeleton).replace("@TYPE@", type));
+ process.closeWriteChannel();
+
+ if (!process.waitForStarted()) {
+ const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
+ QString message = QString::fromLatin1("'%1' could not be found when run from '%2'. Path: '%3' ").
+ arg(command, QDir::currentPath(), path);
+ QFAIL(qPrintable(message));
+ }
+ QVERIFY2(process.waitForFinished(), qPrintable(process.errorString()));
+
+ // verify nothing was printed on stderr
+ QCOMPARE(process.readAllStandardError(), QString());
+
+ // we don't do a full XML parsing here...
+ QByteArray output = process.readAll().simplified();
+ QVERIFY2(output.contains("<node>") && output.contains("</node>"), "Output was: " + output);
+ output = output.mid(output.indexOf("<node>") + strlen("<node>"));
+ output = output.left(output.indexOf("</node>"));
+
+ QVERIFY2(output.contains(methodXml), "Output was: " + output);
+
+ if (!expectedSignature.isEmpty()) {
+ QByteArray expected = QByteArray(expectedSkeleton).replace("@S@", expectedSignature);
+ QVERIFY2(output.contains(expected), "Expected: '" + expected + "'; got: '" + output + '\'');
+ }
+}
+
QTEST_APPLESS_MAIN(tst_qdbuscpp2xml)
#include "tst_qdbuscpp2xml.moc"