diff options
-rw-r--r-- | src/dbus/qdbusargument_p.h | 4 | ||||
-rw-r--r-- | src/dbus/qdbusdemarshaller.cpp | 51 | ||||
-rw-r--r-- | tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 115 |
3 files changed, 163 insertions, 7 deletions
diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h index 7d7fc05..36e9f2d 100644 --- a/src/dbus/qdbusargument_p.h +++ b/src/dbus/qdbusargument_p.h @@ -201,6 +201,7 @@ public: QVariant toVariantInternal(); QDBusArgument::ElementType currentType(); + bool isCurrentTypeStringLike(); public: DBusMessageIter iterator; @@ -208,6 +209,9 @@ public: private: Q_DISABLE_COPY(QDBusDemarshaller) + QString toStringUnchecked(); + QDBusObjectPath toObjectPathUnchecked(); + QDBusSignature toSignatureUnchecked(); }; inline QDBusMarshaller *QDBusArgumentPrivate::marshaller() diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp index c8af347..8769846 100644 --- a/src/dbus/qdbusdemarshaller.cpp +++ b/src/dbus/qdbusdemarshaller.cpp @@ -130,19 +130,43 @@ inline double QDBusDemarshaller::toDouble() return qIterGet<double>(&iterator); } -inline QString QDBusDemarshaller::toString() +inline QString QDBusDemarshaller::toStringUnchecked() { return QString::fromUtf8(qIterGet<char *>(&iterator)); } +inline QString QDBusDemarshaller::toString() +{ + if (isCurrentTypeStringLike()) + return toStringUnchecked(); + else + return QString(); +} + +inline QDBusObjectPath QDBusDemarshaller::toObjectPathUnchecked() + { + return QDBusObjectPath(QString::fromUtf8(qIterGet<char *>(&iterator))); + } + inline QDBusObjectPath QDBusDemarshaller::toObjectPath() { - return QDBusObjectPath(QString::fromUtf8(qIterGet<char *>(&iterator))); + if (isCurrentTypeStringLike()) + return toObjectPathUnchecked(); + else + return QDBusObjectPath(); } +inline QDBusSignature QDBusDemarshaller::toSignatureUnchecked() + { + return QDBusSignature(QString::fromUtf8(qIterGet<char *>(&iterator))); + } + inline QDBusSignature QDBusDemarshaller::toSignature() { - return QDBusSignature(QString::fromUtf8(qIterGet<char *>(&iterator))); + if (isCurrentTypeStringLike()) + return toSignatureUnchecked(); + else + return QDBusSignature(); } inline QDBusUnixFileDescriptor QDBusDemarshaller::toUnixFileDescriptor() @@ -236,11 +260,11 @@ QVariant QDBusDemarshaller::toVariantInternal() case DBUS_TYPE_UINT64: return toULongLong(); case DBUS_TYPE_STRING: - return toString(); + return toStringUnchecked(); case DBUS_TYPE_OBJECT_PATH: - return QVariant::fromValue(toObjectPath()); + return QVariant::fromValue(toObjectPathUnchecked()); case DBUS_TYPE_SIGNATURE: - return QVariant::fromValue(toSignature()); + return QVariant::fromValue(toSignatureUnchecked()); case DBUS_TYPE_VARIANT: return QVariant::fromValue(toVariant()); @@ -280,6 +304,19 @@ QVariant QDBusDemarshaller::toVariantInternal() }; } +bool QDBusDemarshaller::isCurrentTypeStringLike() +{ + const int type = q_dbus_message_iter_get_arg_type(&iterator); + switch (type) { + case DBUS_TYPE_STRING: //FALLTHROUGH + case DBUS_TYPE_OBJECT_PATH: //FALLTHROUGH + case DBUS_TYPE_SIGNATURE: + return true; + default: + return false; + } +} + QStringList QDBusDemarshaller::toStringList() { QStringList list; @@ -288,7 +325,7 @@ QStringList QDBusDemarshaller::toStringList() q_dbus_message_iter_recurse(&iterator, &sub.iterator); q_dbus_message_iter_next(&iterator); while (!sub.atEnd()) - list.append(sub.toString()); + list.append(sub.toStringUnchecked()); return list; } diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index cc5e68d..bf7270e 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -96,6 +96,9 @@ private slots: void demarshallPrimitives_data(); void demarshallPrimitives(); + void demarshallStrings_data(); + void demarshallStrings(); + private: int fileDescriptorForTest(); @@ -1268,5 +1271,117 @@ void tst_QDBusMarshall::demarshallPrimitives() } } +void tst_QDBusMarshall::demarshallStrings_data() +{ + QTest::addColumn<QVariant>("value"); + QTest::addColumn<char>("targetSig"); + QTest::addColumn<QVariant>("expectedValue"); + + // All primitive types demarshall to null string types + typedef QPair<QVariant, char> ValSigPair; + const QList<ValSigPair> nullStringTypes + = QList<ValSigPair>() + << ValSigPair(qVariantFromValue(QString()), 's') + << ValSigPair(qVariantFromValue(QDBusObjectPath()), 'o') + << ValSigPair(qVariantFromValue(QDBusSignature()), 'g'); + foreach (ValSigPair valSigPair, nullStringTypes) { + QTest::newRow("bool(false)") << QVariant(false) << valSigPair.second << valSigPair.first; + QTest::newRow("bool(true)") << QVariant(true) << valSigPair.second << valSigPair.first; + QTest::newRow("byte") << qVariantFromValue(uchar(1)) << valSigPair.second << valSigPair.first; + QTest::newRow("int16") << qVariantFromValue(short(2)) << valSigPair.second << valSigPair.first; + QTest::newRow("uint16") << qVariantFromValue(ushort(3)) << valSigPair.second << valSigPair.first; + QTest::newRow("int") << QVariant(1) << valSigPair.second << valSigPair.first; + QTest::newRow("uint") << QVariant(2U) << valSigPair.second << valSigPair.first; + QTest::newRow("int64") << QVariant(Q_INT64_C(3)) << valSigPair.second << valSigPair.first; + QTest::newRow("uint64") << QVariant(Q_UINT64_C(4)) << valSigPair.second << valSigPair.first; + QTest::newRow("double") << QVariant(42.5) << valSigPair.second << valSigPair.first; + } + + // String types should demarshall to each other. This is a regression test + // to check released functionality is maintained even after checks have + // been added to string demarshalling + QTest::newRow("empty string->invalid objectpath") << QVariant("") + << 'o' << qVariantFromValue(QDBusObjectPath()); + QTest::newRow("null string->invalid objectpath") << QVariant(QString()) + << 'o' << qVariantFromValue(QDBusObjectPath()); + QTest::newRow("string->invalid objectpath") << QVariant("invalid objectpath") + << 'o' << qVariantFromValue(QDBusObjectPath()); + QTest::newRow("string->valid objectpath") << QVariant("/org/kde") + << 'o' << qVariantFromValue(QDBusObjectPath("/org/kde")); + + QTest::newRow("empty string->invalid signature") << QVariant("") + << 'g' << qVariantFromValue(QDBusSignature()); + QTest::newRow("null string->invalid signature") << QVariant(QString()) + << 'g' << qVariantFromValue(QDBusSignature()); + QTest::newRow("string->invalid signature") << QVariant("_invalid signature") + << 'g' << qVariantFromValue(QDBusSignature()); + QTest::newRow("string->valid signature") << QVariant("s") + << 'g' << qVariantFromValue(QDBusSignature("s")); + + QTest::newRow("objectpath->string") << qVariantFromValue(QDBusObjectPath("/org/kde")) + << 's' << qVariantFromValue(QString("/org/kde")); + QTest::newRow("objectpath->invalid signature") << qVariantFromValue(QDBusObjectPath("/org/kde")) + << 'g' << qVariantFromValue(QDBusSignature()); + + QTest::newRow("signature->string") << qVariantFromValue(QDBusSignature("s")) + << 's' << qVariantFromValue(QString("s")); + QTest::newRow("signature->invalid objectpath") << qVariantFromValue(QDBusSignature("s")) + << 'o' << qVariantFromValue(QDBusObjectPath()); +} + +QVariant demarshallAsString(const QDBusArgument& dbusArg, char targetSig) +{ + switch (targetSig) { + case 's': { + QString s; + dbusArg >> s; + return s; + } + case 'o': { + QDBusObjectPath op; + dbusArg >> op; + return qVariantFromValue(op); + } + case 'g' : { + QDBusSignature sig; + dbusArg >> sig; + return qVariantFromValue(sig); + } + default: { + return QVariant(); + } + } +} + +void tst_QDBusMarshall::demarshallStrings() +{ + QFETCH(QVariant, value); + QFETCH(char, targetSig); + QFETCH(QVariant, expectedValue); + + QDBusConnection con = QDBusConnection::sessionBus(); + + QVERIFY(con.isConnected()); + + QDBusMessage msg = QDBusMessage::createMethodCall(serviceName, objectPath, + interfaceName, "ping"); + QDBusArgument sendArg; + sendArg.beginStructure(); + sendArg.appendVariant(value); + sendArg.endStructure(); + msg.setArguments(QVariantList() << qVariantFromValue(sendArg)); + QDBusMessage reply = con.call(msg); + + const QDBusArgument receiveArg = qvariant_cast<QDBusArgument>(reply.arguments().at(0)); + receiveArg.beginStructure(); + + QVariant receiveValue = demarshallAsString(receiveArg, targetSig); + QVERIFY2(receiveValue.isValid(), "Invalid targetSig in demarshallStrings_data()"); + QVERIFY(compare(receiveValue, expectedValue)); + + receiveArg.endStructure(); + QVERIFY(receiveArg.atEnd()); +} + QTEST_MAIN(tst_QDBusMarshall) #include "tst_qdbusmarshall.moc" |