From daf24b1b6489260798239d266a876607273cb11e Mon Sep 17 00:00:00 2001 From: Jo Asplin Date: Wed, 31 Aug 2011 12:42:57 +0200 Subject: Moved dbus autotests into new directory structure Task-number: QTBUG-21108 Change-Id: I8cdd4af59db3716921e7392379584f349ed29136 Reviewed-on: http://codereview.qt.nokia.com/3602 Reviewed-by: Qt Sanity Bot Reviewed-by: Rohan McGovern --- tests/auto/dbus/qdbusmarshall/.gitignore | 2 + tests/auto/dbus/qdbusmarshall/common.h | 755 +++++++++++++ tests/auto/dbus/qdbusmarshall/dummy.cpp | 44 + tests/auto/dbus/qdbusmarshall/qdbusmarshall.pro | 14 + tests/auto/dbus/qdbusmarshall/qpong/qpong.cpp | 81 ++ tests/auto/dbus/qdbusmarshall/qpong/qpong.pro | 6 + tests/auto/dbus/qdbusmarshall/test/test.pro | 9 + .../auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp | 1172 ++++++++++++++++++++ 8 files changed, 2083 insertions(+) create mode 100644 tests/auto/dbus/qdbusmarshall/.gitignore create mode 100644 tests/auto/dbus/qdbusmarshall/common.h create mode 100644 tests/auto/dbus/qdbusmarshall/dummy.cpp create mode 100644 tests/auto/dbus/qdbusmarshall/qdbusmarshall.pro create mode 100644 tests/auto/dbus/qdbusmarshall/qpong/qpong.cpp create mode 100644 tests/auto/dbus/qdbusmarshall/qpong/qpong.pro create mode 100644 tests/auto/dbus/qdbusmarshall/test/test.pro create mode 100644 tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp (limited to 'tests/auto/dbus/qdbusmarshall') diff --git a/tests/auto/dbus/qdbusmarshall/.gitignore b/tests/auto/dbus/qdbusmarshall/.gitignore new file mode 100644 index 0000000000..d227388521 --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/.gitignore @@ -0,0 +1,2 @@ +tst_qdbusmarshall +qpong/qpong diff --git a/tests/auto/dbus/qdbusmarshall/common.h b/tests/auto/dbus/qdbusmarshall/common.h new file mode 100644 index 0000000000..35fe5f1bf7 --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/common.h @@ -0,0 +1,755 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include // isnan +#include + +#ifdef Q_OS_UNIX +# include + +static bool compareFileDescriptors(int fd1, int fd2) +{ + QT_STATBUF st1, st2; + if (QT_FSTAT(fd1, &st1) == -1 || QT_FSTAT(fd2, &st2) == -1) { + perror("fstat"); + return false; + } + + return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino); +} +#endif + +Q_DECLARE_METATYPE(QVariant) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) + +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) +Q_DECLARE_METATYPE(QList >) + +typedef QMap IntStringMap; +typedef QMap StringStringMap; +typedef QMap ObjectPathStringMap; +typedef QHash LLDateTimeMap; +typedef QHash SignatureStringMap; +Q_DECLARE_METATYPE(IntStringMap) +Q_DECLARE_METATYPE(StringStringMap) +Q_DECLARE_METATYPE(ObjectPathStringMap) +Q_DECLARE_METATYPE(LLDateTimeMap) +Q_DECLARE_METATYPE(SignatureStringMap) + +static bool compare(const QDBusUnixFileDescriptor &t1, const QDBusUnixFileDescriptor &t2) +{ + int fd1 = t1.fileDescriptor(); + int fd2 = t2.fileDescriptor(); + if ((fd1 == -1 || fd2 == -1) && fd1 != fd2) { + // one is valid, the other isn't + return false; + } + +#ifdef Q_OS_UNIX + return compareFileDescriptors(fd1, fd2); +#else + return true; +#endif +} + +struct MyStruct +{ + int i; + QString s; + + inline bool operator==(const MyStruct &other) const + { return i == other.i && s == other.s; } +}; +Q_DECLARE_METATYPE(MyStruct) + +QDBusArgument &operator<<(QDBusArgument &arg, const MyStruct &ms) +{ + arg.beginStructure(); + arg << ms.i << ms.s; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, MyStruct &ms) +{ + arg.beginStructure(); + arg >> ms.i >> ms.s; + arg.endStructure(); + return arg; +} + +struct MyVariantMapStruct +{ + QString s; + QVariantMap map; + + inline bool operator==(const MyVariantMapStruct &other) const + { return s == other.s && map == other.map; } +}; +Q_DECLARE_METATYPE(MyVariantMapStruct) +Q_DECLARE_METATYPE(QList) + +QDBusArgument &operator<<(QDBusArgument &arg, const MyVariantMapStruct &ms) +{ + arg.beginStructure(); + arg << ms.s << ms.map; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, MyVariantMapStruct &ms) +{ + arg.beginStructure(); + arg >> ms.s >> ms.map; + arg.endStructure(); + return arg; +} + +struct MyFileDescriptorStruct +{ + QDBusUnixFileDescriptor fd; + + inline bool operator==(const MyFileDescriptorStruct &other) const + { return compare(fd, other.fd); } +}; +Q_DECLARE_METATYPE(MyFileDescriptorStruct) +Q_DECLARE_METATYPE(QList) + +QDBusArgument &operator<<(QDBusArgument &arg, const MyFileDescriptorStruct &ms) +{ + arg.beginStructure(); + arg << ms.fd; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, MyFileDescriptorStruct &ms) +{ + arg.beginStructure(); + arg >> ms.fd; + arg.endStructure(); + return arg; +} + + +void commonInit() +{ + qDBusRegisterMetaType >(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType > >(); + qDBusRegisterMetaType >(); + + qDBusRegisterMetaType >(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType >(); + + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType >(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType >(); +} +#ifdef USE_PRIVATE_CODE +#include "private/qdbusintrospection_p.h" + +// just to make it easier: +typedef QDBusIntrospection::Interfaces InterfaceMap; +typedef QDBusIntrospection::Objects ObjectMap; +typedef QDBusIntrospection::Arguments ArgumentList; +typedef QDBusIntrospection::Annotations AnnotationsMap; +typedef QDBusIntrospection::Methods MethodMap; +typedef QDBusIntrospection::Signals SignalMap; +typedef QDBusIntrospection::Properties PropertyMap; + +Q_DECLARE_METATYPE(QDBusIntrospection::Method) +Q_DECLARE_METATYPE(QDBusIntrospection::Signal) +Q_DECLARE_METATYPE(QDBusIntrospection::Property) +Q_DECLARE_METATYPE(MethodMap) +Q_DECLARE_METATYPE(SignalMap) +Q_DECLARE_METATYPE(PropertyMap) + +inline QDBusIntrospection::Argument arg(const char* type, const char *name = 0) +{ + QDBusIntrospection::Argument retval; + retval.type = QLatin1String(type); + retval.name = QLatin1String(name); + return retval; +} + +template +inline QMap& operator<<(QMap& map, const T& m) +{ map.insertMulti(m.name, m); return map; } + +inline const char* mapName(const MethodMap&) +{ return "MethodMap"; } + +inline const char* mapName(const SignalMap&) +{ return "SignalMap"; } + +inline const char* mapName(const PropertyMap&) +{ return "PropertyMap"; } + +QString printable(const QDBusIntrospection::Method& m) +{ + QString result = "method " + m.name + "("; + foreach (QDBusIntrospection::Argument arg, m.inputArgs) + result += QString("in %1 %2, ") + .arg(arg.type, arg.name); + foreach (QDBusIntrospection::Argument arg, m.outputArgs) + result += QString("out %1 %2, ") + .arg(arg.type, arg.name); + AnnotationsMap::const_iterator it = m.annotations.begin(); + for ( ; it != m.annotations.end(); ++it) + result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value()); + + result += ")"; + return result; +} + +QString printable(const QDBusIntrospection::Signal& s) +{ + QString result = "signal " + s.name + "("; + foreach (QDBusIntrospection::Argument arg, s.outputArgs) + result += QString("out %1 %2, ") + .arg(arg.type, arg.name); + AnnotationsMap::const_iterator it = s.annotations.begin(); + for ( ; it != s.annotations.end(); ++it) + result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value()); + + result += ")"; + return result; +} + +QString printable(const QDBusIntrospection::Property& p) +{ + QString result; + if (p.access == QDBusIntrospection::Property::Read) + result = "property read %1 %2, "; + else if (p.access == QDBusIntrospection::Property::Write) + result = "property write %1 %2, "; + else + result = "property readwrite %1 %2, "; + result = result.arg(p.type, p.name); + + AnnotationsMap::const_iterator it = p.annotations.begin(); + for ( ; it != p.annotations.end(); ++it) + result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value()); + + return result; +} + +template +char* printableMap(const QMap& map) +{ + QString contents = "\n"; + typename QMap::const_iterator it = map.begin(); + for ( ; it != map.end(); ++it) { + if (it.key() != it.value().name) + contents += it.value().name + ":"; + contents += printable(it.value()); + contents += ";\n"; + } + + QString result("%1(size = %2): {%3}"); + return qstrdup(qPrintable(result + .arg(mapName(map)) + .arg(map.size()) + .arg(contents))); +} + +QT_BEGIN_NAMESPACE +namespace QTest { + template<> + inline char* toString(const MethodMap& map) + { + return printableMap(map); + } + + template<> + inline char* toString(const SignalMap& map) + { + return printableMap(map); + } + + template<> + inline char* toString(const PropertyMap& map) + { + return printableMap(map); + } +} +QT_END_NAMESPACE + +#endif + +//bool compare(const QVariantList &l1, const QVariantList &l2); +//bool compare(const QVariantMap &m1, const QVariantMap &m2); +template +bool compare(const T &t1, const T &t2) +{ return t1 == t2; } + +template<> +bool compare(const QVariant &v1, const QVariant &v2); + +bool compare(double d1, double d2) +{ + if (isnan(d1) && isnan(d2)) + return true; + return d1 == d2; +} + +template<> +bool compare(const QString &s1, const QString &s2) +{ + if (s1.isEmpty() && s2.isEmpty()) + return true; // regardless of whether one of them is null + return s1 == s2; +} + +template<> +bool compare(const QByteArray &ba1, const QByteArray &ba2) +{ + if (ba1.isEmpty() && ba2.isEmpty()) + return true; // regardless of whether one of them is null + return ba1 == ba2; +} + +template<> +bool compare(const QDBusVariant &s1, const QDBusVariant &s2) +{ + return compare(s1.variant(), s2.variant()); +} + +template +bool compare(const QList &l1, const QList &l2) +{ + if (l1.count() != l2.count()) + return false; + + typename QList::ConstIterator it1 = l1.constBegin(); + typename QList::ConstIterator it2 = l2.constBegin(); + typename QList::ConstIterator end = l1.constEnd(); + for ( ; it1 != end; ++it1, ++it2) + if (!compare(*it1, *it2)) + return false; + return true; +} + +template +bool compare(const QMap &m1, const QMap &m2) +{ + if (m1.count() != m2.size()) + return false; + typename QMap::ConstIterator i1 = m1.constBegin(); + typename QMap::ConstIterator end = m1.constEnd(); + for ( ; i1 != end; ++i1) { + typename QMap::ConstIterator i2 = m2.find(i1.key()); + if (i2 == m2.constEnd()) + return false; + if (!compare(*i1, *i2)) + return false; + } + return true; +} + +template +bool compare(const QHash &m1, const QHash &m2) +{ + if (m1.count() != m2.size()) + return false; + typename QHash::ConstIterator i1 = m1.constBegin(); + typename QHash::ConstIterator end = m1.constEnd(); + for ( ; i1 != end; ++i1) { + typename QHash::ConstIterator i2 = m2.find(i1.key()); + if (i2 == m2.constEnd()) + return false; + if (!compare(*i1, *i2)) + return false; + } + return true; +} + +template +inline bool compare(const QDBusArgument &arg, const QVariant &v2, T * = 0) +{ + return compare(qdbus_cast(arg), qvariant_cast(v2)); +} + +bool compareToArgument(const QDBusArgument &arg, const QVariant &v2) +{ + if (arg.currentSignature() != QDBusMetaType::typeToSignature(v2.userType())) + return false; + + // try to demarshall the arg according to v2 + switch (v2.userType()) + { + case QVariant::Bool: + return compare(arg, v2); + case QMetaType::UChar: + return compare(arg, v2); + case QMetaType::Short: + return compare(arg, v2); + case QMetaType::UShort: + return compare(arg, v2); + case QVariant::Int: + return compare(arg, v2); + case QVariant::UInt: + return compare(arg, v2); + case QVariant::LongLong: + return compare(arg, v2); + case QVariant::ULongLong: + return compare(arg, v2); + case QVariant::Double: + return compare(arg, v2); + case QVariant::String: + return compare(arg, v2); + case QVariant::ByteArray: + return compare(arg, v2); + case QVariant::List: + return compare(arg, v2); + case QVariant::Map: + return compare(arg, v2); + case QVariant::Point: + return compare(arg, v2); + case QVariant::PointF: + return compare(arg, v2); + case QVariant::Size: + return compare(arg, v2); + case QVariant::SizeF: + return compare(arg, v2); + case QVariant::Line: + return compare(arg, v2); + case QVariant::LineF: + return compare(arg, v2); + case QVariant::Rect: + return compare(arg, v2); + case QVariant::RectF: + return compare(arg, v2); + case QVariant::Date: + return compare(arg, v2); + case QVariant::Time: + return compare(arg, v2); + case QVariant::DateTime: + return compare(arg, v2); + default: + register int id = v2.userType(); + if (id == qMetaTypeId()) + return compare(arg, v2); + else if (id == qMetaTypeId()) + return compare(arg, v2); + else if (id == qMetaTypeId()) + return compare(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId > >()) + return compare > >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + + else if (id == qMetaTypeId()) + return compare(arg, v2); + + else if (id == qMetaTypeId()) + return compare(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + else if (id == qMetaTypeId()) + return compare(arg, v2); + else if (id == qMetaTypeId >()) + return compare >(arg, v2); + } + + qWarning() << "Unexpected QVariant type" << v2.userType() + << QByteArray(QDBusMetaType::typeToSignature(v2.userType())) + << QVariant::typeToName(QVariant::Type(v2.userType())); + return false; +} + +template<> bool compare(const QVariant &v1, const QVariant &v2) +{ + // v1 is the one that came from the network + // v2 is the one that we sent + + if (v1.userType() == qMetaTypeId()) + // this argument has been left un-demarshalled + return compareToArgument(qvariant_cast(v1), v2); + + if (v1.userType() != v2.userType()) + return false; + + int id = v1.userType(); + if (id == QVariant::List) + return compare(v1.toList(), v2.toList()); + + else if (id == QVariant::Map) + return compare(v1.toMap(), v2.toMap()); + + else if (id == QVariant::String) + return compare(v1.toString(), v2.toString()); + + else if (id == QVariant::ByteArray) + return compare(v1.toByteArray(), v2.toByteArray()); + + else if (id < int(QVariant::UserType)) // yes, v1.type() + // QVariant can compare + return v1 == v2; + + else if (id == QMetaType::UChar) + return qvariant_cast(v1) == qvariant_cast(v2); + + else if (id == QMetaType::Short) + return qvariant_cast(v1) == qvariant_cast(v2); + + else if (id == QMetaType::UShort) + return qvariant_cast(v1) == qvariant_cast(v2); + + else if (id == qMetaTypeId()) + return qvariant_cast(v1).path() == qvariant_cast(v2).path(); + + else if (id == qMetaTypeId()) + return qvariant_cast(v1).signature() == qvariant_cast(v2).signature(); + + else if (id == qMetaTypeId()) + return compare(qvariant_cast(v1), qvariant_cast(v2)); + + else if (id == qMetaTypeId()) + return compare(qvariant_cast(v1).variant(), qvariant_cast(v2).variant()); + + else if (id == qMetaTypeId()) + return compare(qvariant_cast(v1), qvariant_cast(v2)); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v2) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return compare(qvariant_cast >(v1), qvariant_cast >(v2)); + + else if (id == qMetaTypeId()) + return compare(qvariant_cast(v1), qvariant_cast(v2)); + + else if (id == qMetaTypeId > >()) + return qvariant_cast > >(v1) == qvariant_cast > >(v2); + + else if (id == qMetaTypeId > >()) + return qvariant_cast > >(v1) == qvariant_cast > >(v2); + + else if (id == qMetaTypeId > >()) + return qvariant_cast > >(v1) == qvariant_cast > >(v2); + + else if (id == qMetaTypeId > >()) + return qvariant_cast > >(v1) == qvariant_cast > >(v2); + + else if (id == qMetaTypeId > >()) + return qvariant_cast > >(v1) == qvariant_cast > >(v2); + + else if (id == qMetaTypeId > >()) + return qvariant_cast > >(v1) == qvariant_cast > >(v2); + + else if (id == qMetaTypeId > >()) + return qvariant_cast > >(v1) == qvariant_cast > >(v2); + + else if (id == qMetaTypeId > >()) + return compare(qvariant_cast > >(v1), qvariant_cast > >(v2)); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return qvariant_cast >(v1) == qvariant_cast >(v2); + + else if (id == qMetaTypeId >()) + return compare(qvariant_cast >(v1), qvariant_cast >(v2)); + + else if (id == qMetaTypeId >()) + return compare(qvariant_cast >(v1), qvariant_cast >(v2)); + + else if (id == qMetaTypeId >()) // ssmap + return compare(qvariant_cast >(v1), qvariant_cast >(v2)); + + else if (id == qMetaTypeId >()) + return compare(qvariant_cast >(v1), qvariant_cast >(v2)); + + else if (id == qMetaTypeId >()) // lldtmap + return compare(qvariant_cast >(v1), qvariant_cast >(v2)); + + else if (id == qMetaTypeId >()) + return compare(qvariant_cast >(v1), qvariant_cast >(v2)); + + else if (id == qMetaTypeId()) // (is) + return qvariant_cast(v1) == qvariant_cast(v2); + + else { + qWarning() << "Please write a comparison case for type" << v1.typeName(); + return false; // unknown type + } +} + +#if 0 +bool compare(const QVariantList &l1, const QVariantList &l2) +{ + if (l1.count() != l2.size()) + return false; + QVariantList::ConstIterator i1 = l1.constBegin(); + QVariantList::ConstIterator i2 = l2.constBegin(); + QVariantList::ConstIterator end = l1.constEnd(); + for ( ; i1 != end; ++i1, ++i2) { + if (!compare(*i1, *i2)) + return false; + } + return true; +} + +bool compare(const QVariantMap &m1, const QVariantMap &m2) +{ + if (m1.count() != m2.size()) + return false; + QVariantMap::ConstIterator i1 = m1.constBegin(); + QVariantMap::ConstIterator end = m1.constEnd(); + for ( ; i1 != end; ++i1) { + QVariantMap::ConstIterator i2 = m2.find(i1.key()); + if (i2 == m2.constEnd()) + return false; + if (!compare(*i1, *i2)) + return false; + } + return true; +} +#endif diff --git a/tests/auto/dbus/qdbusmarshall/dummy.cpp b/tests/auto/dbus/qdbusmarshall/dummy.cpp new file mode 100644 index 0000000000..0b403c3585 --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/dummy.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include + +QTEST_NOOP_MAIN + diff --git a/tests/auto/dbus/qdbusmarshall/qdbusmarshall.pro b/tests/auto/dbus/qdbusmarshall/qdbusmarshall.pro new file mode 100644 index 0000000000..1b6408a2f9 --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/qdbusmarshall.pro @@ -0,0 +1,14 @@ +load(qttest_p4) +contains(QT_CONFIG,dbus): { + TEMPLATE = subdirs + CONFIG += ordered + SUBDIRS = qpong test + + QT += core-private + + requires(contains(QT_CONFIG,private_tests)) +} else { + SOURCES += dummy.cpp +} + + diff --git a/tests/auto/dbus/qdbusmarshall/qpong/qpong.cpp b/tests/auto/dbus/qdbusmarshall/qpong/qpong.cpp new file mode 100644 index 0000000000..fce6f59344 --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/qpong/qpong.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include + +static const char serviceName[] = "com.trolltech.autotests.qpong"; +static const char objectPath[] = "/com/trolltech/qpong"; +//static const char *interfaceName = serviceName; + +class Pong: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.qpong") +public slots: + + void ping(QDBusMessage msg) + { + msg.setDelayedReply(true); + if (!QDBusConnection::sessionBus().send(msg.createReply(msg.arguments()))) + exit(1); + } +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + QDBusConnection con = QDBusConnection::sessionBus(); + if (!con.isConnected()) + exit(1); + + if (!con.registerService(serviceName)) + exit(2); + + Pong pong; + con.registerObject(objectPath, &pong, QDBusConnection::ExportAllSlots); + + printf("ready.\n"); + + return app.exec(); +} + +#include "qpong.moc" diff --git a/tests/auto/dbus/qdbusmarshall/qpong/qpong.pro b/tests/auto/dbus/qdbusmarshall/qpong/qpong.pro new file mode 100644 index 0000000000..5cd9acdc1c --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/qpong/qpong.pro @@ -0,0 +1,6 @@ +SOURCES = qpong.cpp +TARGET = qpong +QT += dbus +QT -= gui + + diff --git a/tests/auto/dbus/qdbusmarshall/test/test.pro b/tests/auto/dbus/qdbusmarshall/test/test.pro new file mode 100644 index 0000000000..ba4d99b57d --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/test/test.pro @@ -0,0 +1,9 @@ +load(qttest_p4) +SOURCES += ../tst_qdbusmarshall.cpp +TARGET = ../tst_qdbusmarshall + +QT = core +QT += core-private dbus-private + +LIBS += $$QT_LIBS_DBUS +QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp new file mode 100644 index 0000000000..cca212e278 --- /dev/null +++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp @@ -0,0 +1,1172 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include +#include + +#include "common.h" +#include + +#include + +static const char serviceName[] = "com.trolltech.autotests.qpong"; +static const char objectPath[] = "/com/trolltech/qpong"; +static const char *interfaceName = serviceName; + +class tst_QDBusMarshall: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void sendBasic_data(); + void sendBasic(); + + void sendVariant_data(); + void sendVariant(); + + void sendArrays_data(); + void sendArrays(); + + void sendArrayOfArrays_data(); + void sendArrayOfArrays(); + + void sendMaps_data(); + void sendMaps(); + + void sendStructs_data(); + void sendStructs(); + + void sendComplex_data(); + void sendComplex(); + + void sendArgument_data(); + void sendArgument(); + + void sendSignalErrors(); + void sendCallErrors_data(); + void sendCallErrors(); + + void receiveUnknownType_data(); + void receiveUnknownType(); + +private: + int fileDescriptorForTest(); + + QProcess proc; + QTemporaryFile tempFile; + bool fileDescriptorPassing; +}; + +class QDBusMessageSpy: public QObject +{ + Q_OBJECT +public slots: + Q_SCRIPTABLE int theSlot(const QDBusMessage &msg) + { + list << msg; + return 42; + } +public: + QList list; +}; + +struct UnregisteredType { }; +Q_DECLARE_METATYPE(UnregisteredType) + +void tst_QDBusMarshall::initTestCase() +{ + commonInit(); + QDBusConnection con = QDBusConnection::sessionBus(); + fileDescriptorPassing = con.connectionCapabilities() & QDBusConnection::UnixFileDescriptorPassing; +#ifdef Q_OS_WIN + proc.start("qpong"); +#else + proc.start("./qpong/qpong"); +#endif + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)) { + QVERIFY(proc.waitForStarted()); + + QVERIFY(con.isConnected()); + con.connect("org.freedesktop.DBus", QString(), "org.freedesktop.DBus", "NameOwnerChanged", + QStringList() << serviceName << QString(""), QString(), + &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)); + con.disconnect("org.freedesktop.DBus", QString(), "org.freedesktop.DBus", "NameOwnerChanged", + QStringList() << serviceName << QString(""), QString(), + &QTestEventLoop::instance(), SLOT(exitLoop())); + } +} + +void tst_QDBusMarshall::cleanupTestCase() +{ + proc.close(); + proc.terminate(); + proc.waitForFinished(200); +} + +int tst_QDBusMarshall::fileDescriptorForTest() +{ + if (!tempFile.isOpen()) { + tempFile.setFileTemplate(QDir::tempPath() + "/qdbusmarshalltestXXXXXX.tmp"); + tempFile.open(); + } + return tempFile.handle(); +} + +void tst_QDBusMarshall::sendBasic_data() +{ + QTest::addColumn("value"); + QTest::addColumn("sig"); + QTest::addColumn("stringResult"); + + // basic types: + QTest::newRow("bool") << QVariant(false) << "b" << "false"; +#if 1 + QTest::newRow("bool2") << QVariant(true) << "b" << "true"; + QTest::newRow("byte") << qVariantFromValue(uchar(1)) << "y" << "1"; + QTest::newRow("int16") << qVariantFromValue(short(2)) << "n" << "2"; + QTest::newRow("uint16") << qVariantFromValue(ushort(3)) << "q" << "3"; + QTest::newRow("int") << QVariant(1) << "i" << "1"; + QTest::newRow("uint") << QVariant(2U) << "u" << "2"; + QTest::newRow("int64") << QVariant(Q_INT64_C(3)) << "x" << "3"; + QTest::newRow("uint64") << QVariant(Q_UINT64_C(4)) << "t" << "4"; + QTest::newRow("double") << QVariant(42.5) << "d" << "42.5"; + QTest::newRow("string") << QVariant("ping") << "s" << "\"ping\""; + QTest::newRow("objectpath") << qVariantFromValue(QDBusObjectPath("/org/kde")) << "o" << "[ObjectPath: /org/kde]"; + QTest::newRow("signature") << qVariantFromValue(QDBusSignature("g")) << "g" << "[Signature: g]"; + QTest::newRow("emptystring") << QVariant("") << "s" << "\"\""; + QTest::newRow("nullstring") << QVariant(QString()) << "s" << "\"\""; + + if (fileDescriptorPassing) + QTest::newRow("file-descriptor") << qVariantFromValue(QDBusUnixFileDescriptor(fileDescriptorForTest())) << "h" << "[Unix FD: valid]"; +#endif +} + +void tst_QDBusMarshall::sendVariant_data() +{ + sendBasic_data(); + + QTest::newRow("variant") << qVariantFromValue(QDBusVariant(1)) << "v" << "[Variant(int): 1]"; + + QDBusVariant nested(1); + QTest::newRow("variant-variant") << qVariantFromValue(QDBusVariant(qVariantFromValue(nested))) << "v" + << "[Variant(QDBusVariant): [Variant(int): 1]]"; +} + +void tst_QDBusMarshall::sendArrays_data() +{ + QTest::addColumn("value"); + QTest::addColumn("sig"); + QTest::addColumn("stringResult"); + + // arrays + QStringList strings; + QTest::newRow("emptystringlist") << QVariant(strings) << "as" << "{}"; + strings << "hello" << "world"; + QTest::newRow("stringlist") << QVariant(strings) << "as" << "{\"hello\", \"world\"}"; + + strings.clear(); + strings << "" << "" << ""; + QTest::newRow("list-of-emptystrings") << QVariant(strings) << "as" << "{\"\", \"\", \"\"}"; + + strings.clear(); + strings << QString() << QString() << QString() << QString(); + QTest::newRow("list-of-nullstrings") << QVariant(strings) << "as" << "{\"\", \"\", \"\", \"\"}"; + + QByteArray bytearray; + QTest::newRow("nullbytearray") << QVariant(bytearray) << "ay" << "{}"; + bytearray = ""; // empty, not null + QTest::newRow("emptybytearray") << QVariant(bytearray) << "ay" << "{}"; + bytearray = "foo"; + QTest::newRow("bytearray") << QVariant(bytearray) << "ay" << "{102, 111, 111}"; + + QList bools; + QTest::newRow("emptyboollist") << qVariantFromValue(bools) << "ab" << "[Argument: ab {}]"; + bools << false << true << false; + QTest::newRow("boollist") << qVariantFromValue(bools) << "ab" << "[Argument: ab {false, true, false}]"; + + QList shorts; + QTest::newRow("emptyshortlist") << qVariantFromValue(shorts) << "an" << "[Argument: an {}]"; + shorts << 42 << -43 << 44 << 45 << -32768 << 32767; + QTest::newRow("shortlist") << qVariantFromValue(shorts) << "an" + << "[Argument: an {42, -43, 44, 45, -32768, 32767}]"; + + QList ushorts; + QTest::newRow("emptyushortlist") << qVariantFromValue(ushorts) << "aq" << "[Argument: aq {}]"; + ushorts << 12u << 13u << 14u << 15 << 65535; + QTest::newRow("ushortlist") << qVariantFromValue(ushorts) << "aq" << "[Argument: aq {12, 13, 14, 15, 65535}]"; + + QList ints; + QTest::newRow("emptyintlist") << qVariantFromValue(ints) << "ai" << "[Argument: ai {}]"; + ints << 42 << -43 << 44 << 45 << 2147483647 << -2147483647-1; + QTest::newRow("intlist") << qVariantFromValue(ints) << "ai" << "[Argument: ai {42, -43, 44, 45, 2147483647, -2147483648}]"; + + QList uints; + QTest::newRow("emptyuintlist") << qVariantFromValue(uints) << "au" << "[Argument: au {}]"; + uints << uint(12) << uint(13) << uint(14) << 4294967295U; + QTest::newRow("uintlist") << qVariantFromValue(uints) << "au" << "[Argument: au {12, 13, 14, 4294967295}]"; + + QList llints; + QTest::newRow("emptyllintlist") << qVariantFromValue(llints) << "ax" << "[Argument: ax {}]"; + llints << Q_INT64_C(99) << Q_INT64_C(-100) + << Q_INT64_C(-9223372036854775807)-1 << Q_INT64_C(9223372036854775807); + QTest::newRow("llintlist") << qVariantFromValue(llints) << "ax" + << "[Argument: ax {99, -100, -9223372036854775808, 9223372036854775807}]"; + + QList ullints; + QTest::newRow("emptyullintlist") << qVariantFromValue(ullints) << "at" << "[Argument: at {}]"; + ullints << Q_UINT64_C(66) << Q_UINT64_C(67) + << Q_UINT64_C(18446744073709551615); + QTest::newRow("ullintlist") << qVariantFromValue(ullints) << "at" << "[Argument: at {66, 67, 18446744073709551615}]"; + + QList doubles; + QTest::newRow("emptydoublelist") << qVariantFromValue(doubles) << "ad" << "[Argument: ad {}]"; + doubles << 1.2 << 2.2 << 4.4 + << -std::numeric_limits::infinity() + << std::numeric_limits::infinity() + << std::numeric_limits::quiet_NaN(); + QTest::newRow("doublelist") << qVariantFromValue(doubles) << "ad" << "[Argument: ad {1.2, 2.2, 4.4, -inf, inf, nan}]"; + + QList objectPaths; + QTest::newRow("emptyobjectpathlist") << qVariantFromValue(objectPaths) << "ao" << "[Argument: ao {}]"; + objectPaths << QDBusObjectPath("/") << QDBusObjectPath("/foo"); + QTest::newRow("objectpathlist") << qVariantFromValue(objectPaths) << "ao" << "[Argument: ao {[ObjectPath: /], [ObjectPath: /foo]}]"; + + if (fileDescriptorPassing) { + QList fileDescriptors; + QTest::newRow("emptyfiledescriptorlist") << qVariantFromValue(fileDescriptors) << "ah" << "[Argument: ah {}]"; + fileDescriptors << QDBusUnixFileDescriptor(fileDescriptorForTest()) << QDBusUnixFileDescriptor(1); + QTest::newRow("filedescriptorlist") << qVariantFromValue(fileDescriptors) << "ah" << "[Argument: ah {[Unix FD: valid], [Unix FD: valid]}]"; + } + + QVariantList variants; + QTest::newRow("emptyvariantlist") << QVariant(variants) << "av" << "[Argument: av {}]"; + variants << QString("Hello") << QByteArray("World") << 42 << -43.0 << 44U << Q_INT64_C(-45) + << Q_UINT64_C(46) << true << qVariantFromValue(short(-47)) + << qVariantFromValue(QDBusSignature("av")) + << qVariantFromValue(QDBusVariant(qVariantFromValue(QDBusObjectPath("/")))); + QTest::newRow("variantlist") << QVariant(variants) << "av" + << "[Argument: av {[Variant(QString): \"Hello\"], [Variant(QByteArray): {87, 111, 114, 108, 100}], [Variant(int): 42], [Variant(double): -43], [Variant(uint): 44], [Variant(qlonglong): -45], [Variant(qulonglong): 46], [Variant(bool): true], [Variant(short): -47], [Variant: [Signature: av]], [Variant: [Variant: [ObjectPath: /]]]}]"; +} + +void tst_QDBusMarshall::sendArrayOfArrays_data() +{ + QTest::addColumn("value"); + QTest::addColumn("sig"); + QTest::addColumn("stringResult"); + + // arrays: + QList strings; + QTest::newRow("empty-list-of-stringlist") << qVariantFromValue(strings) << "aas" + << "[Argument: aas {}]"; + strings << QStringList(); + QTest::newRow("list-of-emptystringlist") << qVariantFromValue(strings) << "aas" + << "[Argument: aas {{}}]"; + strings << (QStringList() << "hello" << "world") + << (QStringList() << "hi" << "there") + << (QStringList() << QString()); + QTest::newRow("stringlist") << qVariantFromValue(strings) << "aas" + << "[Argument: aas {{}, {\"hello\", \"world\"}, {\"hi\", \"there\"}, {\"\"}}]"; + + QList bytearray; + QTest::newRow("empty-list-of-bytearray") << qVariantFromValue(bytearray) << "aay" + << "[Argument: aay {}]"; + bytearray << QByteArray(); + QTest::newRow("list-of-emptybytearray") << qVariantFromValue(bytearray) << "aay" + << "[Argument: aay {{}}]"; + bytearray << "foo" << "bar" << "baz" << "" << QByteArray(); + QTest::newRow("bytearray") << qVariantFromValue(bytearray) << "aay" + << "[Argument: aay {{}, {102, 111, 111}, {98, 97, 114}, {98, 97, 122}, {}, {}}]"; + + QList > bools; + QTest::newRow("empty-list-of-boollist") << qVariantFromValue(bools) << "aab" + << "[Argument: aab {}]"; + bools << QList(); + QTest::newRow("list-of-emptyboollist") << qVariantFromValue(bools) << "aab" + << "[Argument: aab {[Argument: ab {}]}]"; + bools << (QList() << false << true) << (QList() << false) << (QList()); + QTest::newRow("boollist") << qVariantFromValue(bools) << "aab" + << "[Argument: aab {[Argument: ab {}], [Argument: ab {false, true}], [Argument: ab {false}], [Argument: ab {}]}]"; + QList > shorts; + QTest::newRow("empty-list-of-shortlist") << qVariantFromValue(shorts) << "aan" + << "[Argument: aan {}]"; + shorts << QList(); + QTest::newRow("list-of-emptyshortlist") << qVariantFromValue(shorts) << "aan" + << "[Argument: aan {[Argument: an {}]}]"; + shorts << (QList() << 42 << -43 << 44 << 45) + << (QList() << -32768 << 32767) + << (QList()); + QTest::newRow("shortlist") << qVariantFromValue(shorts) << "aan" + << "[Argument: aan {[Argument: an {}], [Argument: an {42, -43, 44, 45}], [Argument: an {-32768, 32767}], [Argument: an {}]}]"; + + QList > ushorts; + QTest::newRow("empty-list-of-ushortlist") << qVariantFromValue(ushorts) << "aaq" + << "[Argument: aaq {}]"; + ushorts << QList(); + QTest::newRow("list-of-emptyushortlist") << qVariantFromValue(ushorts) << "aaq" + << "[Argument: aaq {[Argument: aq {}]}]"; + ushorts << (QList() << 12u << 13u << 14u << 15) + << (QList() << 65535) + << (QList()); + QTest::newRow("ushortlist") << qVariantFromValue(ushorts) << "aaq" + << "[Argument: aaq {[Argument: aq {}], [Argument: aq {12, 13, 14, 15}], [Argument: aq {65535}], [Argument: aq {}]}]"; + + QList > ints; + QTest::newRow("empty-list-of-intlist") << qVariantFromValue(ints) << "aai" + << "[Argument: aai {}]"; + ints << QList(); + QTest::newRow("list-of-emptyintlist") << qVariantFromValue(ints) << "aai" + << "[Argument: aai {[Argument: ai {}]}]"; + ints << (QList() << 42 << -43 << 44 << 45) + << (QList() << 2147483647 << -2147483647-1) + << (QList()); + QTest::newRow("intlist") << qVariantFromValue(ints) << "aai" + << "[Argument: aai {[Argument: ai {}], [Argument: ai {42, -43, 44, 45}], [Argument: ai {2147483647, -2147483648}], [Argument: ai {}]}]"; + + QList > uints; + QTest::newRow("empty-list-of-uintlist") << qVariantFromValue(uints) << "aau" + << "[Argument: aau {}]"; + uints << QList(); + QTest::newRow("list-of-emptyuintlist") << qVariantFromValue(uints) << "aau" + << "[Argument: aau {[Argument: au {}]}]"; + uints << (QList() << uint(12) << uint(13) << uint(14)) + << (QList() << 4294967295U) + << (QList()); + QTest::newRow("uintlist") << qVariantFromValue(uints) << "aau" + << "[Argument: aau {[Argument: au {}], [Argument: au {12, 13, 14}], [Argument: au {4294967295}], [Argument: au {}]}]"; + + QList > llints; + QTest::newRow("empty-list-of-llintlist") << qVariantFromValue(llints) << "aax" + << "[Argument: aax {}]"; + llints << QList(); + QTest::newRow("list-of-emptyllintlist") << qVariantFromValue(llints) << "aax" + << "[Argument: aax {[Argument: ax {}]}]"; + llints << (QList() << Q_INT64_C(99) << Q_INT64_C(-100)) + << (QList() << Q_INT64_C(-9223372036854775807)-1 << Q_INT64_C(9223372036854775807)) + << (QList()); + QTest::newRow("llintlist") << qVariantFromValue(llints) << "aax" + << "[Argument: aax {[Argument: ax {}], [Argument: ax {99, -100}], [Argument: ax {-9223372036854775808, 9223372036854775807}], [Argument: ax {}]}]"; + + QList > ullints; + QTest::newRow("empty-list-of-ullintlist") << qVariantFromValue(ullints) << "aat" + << "[Argument: aat {}]"; + ullints << QList(); + QTest::newRow("list-of-emptyullintlist") << qVariantFromValue(ullints) << "aat" + << "[Argument: aat {[Argument: at {}]}]"; + ullints << (QList() << Q_UINT64_C(66) << Q_UINT64_C(67)) + << (QList() << Q_UINT64_C(18446744073709551615)) + << (QList()); + QTest::newRow("ullintlist") << qVariantFromValue(ullints) << "aat" + << "[Argument: aat {[Argument: at {}], [Argument: at {66, 67}], [Argument: at {18446744073709551615}], [Argument: at {}]}]"; + + QList > doubles; + QTest::newRow("empty-list-ofdoublelist") << qVariantFromValue(doubles) << "aad" + << "[Argument: aad {}]"; + doubles << QList(); + QTest::newRow("list-of-emptydoublelist") << qVariantFromValue(doubles) << "aad" + << "[Argument: aad {[Argument: ad {}]}]"; + doubles << (QList() << 1.2 << 2.2 << 4.4) + << (QList() << -std::numeric_limits::infinity() + << std::numeric_limits::infinity() + << std::numeric_limits::quiet_NaN()) + << (QList()); + QTest::newRow("doublelist") << qVariantFromValue(doubles) << "aad" + << "[Argument: aad {[Argument: ad {}], [Argument: ad {1.2, 2.2, 4.4}], [Argument: ad {-inf, inf, nan}], [Argument: ad {}]}]"; + + QList variants; + QTest::newRow("emptyvariantlist") << qVariantFromValue(variants) << "aav" + << "[Argument: aav {}]"; + variants << QVariantList(); + QTest::newRow("emptyvariantlist") << qVariantFromValue(variants) << "aav" + << "[Argument: aav {[Argument: av {}]}]"; + variants << (QVariantList() << QString("Hello") << QByteArray("World")) + << (QVariantList() << 42 << -43.0 << 44U << Q_INT64_C(-45)) + << (QVariantList() << Q_UINT64_C(46) << true << qVariantFromValue(short(-47))); + QTest::newRow("variantlist") << qVariantFromValue(variants) << "aav" + << "[Argument: aav {[Argument: av {}], [Argument: av {[Variant(QString): \"Hello\"], [Variant(QByteArray): {87, 111, 114, 108, 100}]}], [Argument: av {[Variant(int): 42], [Variant(double): -43], [Variant(uint): 44], [Variant(qlonglong): -45]}], [Argument: av {[Variant(qulonglong): 46], [Variant(bool): true], [Variant(short): -47]}]}]"; +} + +void tst_QDBusMarshall::sendMaps_data() +{ + QTest::addColumn("value"); + QTest::addColumn("sig"); + QTest::addColumn("stringResult"); + + QMap ismap; + QTest::newRow("empty-is-map") << qVariantFromValue(ismap) << "a{is}" + << "[Argument: a{is} {}]"; + ismap[1] = "a"; + ismap[2000] = "b"; + ismap[-47] = "c"; + QTest::newRow("is-map") << qVariantFromValue(ismap) << "a{is}" + << "[Argument: a{is} {-47 = \"c\", 1 = \"a\", 2000 = \"b\"}]"; + + QMap ssmap; + QTest::newRow("empty-ss-map") << qVariantFromValue(ssmap) << "a{ss}" + << "[Argument: a{ss} {}]"; + ssmap["a"] = "a"; + ssmap["c"] = "b"; + ssmap["b"] = "c"; + QTest::newRow("ss-map") << qVariantFromValue(ssmap) << "a{ss}" + << "[Argument: a{ss} {\"a\" = \"a\", \"b\" = \"c\", \"c\" = \"b\"}]"; + + QVariantMap svmap; + QTest::newRow("empty-sv-map") << qVariantFromValue(svmap) << "a{sv}" + << "[Argument: a{sv} {}]"; + svmap["a"] = 1; + svmap["c"] = "b"; + svmap["b"] = QByteArray("c"); + svmap["d"] = 42U; + svmap["e"] = qVariantFromValue(short(-47)); + svmap["f"] = qVariantFromValue(QDBusVariant(0)); + QTest::newRow("sv-map1") << qVariantFromValue(svmap) << "a{sv}" + << "[Argument: a{sv} {\"a\" = [Variant(int): 1], \"b\" = [Variant(QByteArray): {99}], \"c\" = [Variant(QString): \"b\"], \"d\" = [Variant(uint): 42], \"e\" = [Variant(short): -47], \"f\" = [Variant: [Variant(int): 0]]}]"; + + QMap osmap; + QTest::newRow("empty-os-map") << qVariantFromValue(osmap) << "a{os}" + << "[Argument: a{os} {}]"; + osmap[QDBusObjectPath("/")] = "root"; + osmap[QDBusObjectPath("/foo")] = "foo"; + osmap[QDBusObjectPath("/bar/baz")] = "bar and baz"; + QTest::newRow("os-map") << qVariantFromValue(osmap) << "a{os}" + << "[Argument: a{os} {[ObjectPath: /] = \"root\", [ObjectPath: /bar/baz] = \"bar and baz\", [ObjectPath: /foo] = \"foo\"}]"; + + QHash gsmap; + QTest::newRow("empty-gs-map") << qVariantFromValue(gsmap) << "a{gs}" + << "[Argument: a{gs} {}]"; + gsmap[QDBusSignature("i")] = "int32"; + gsmap[QDBusSignature("s")] = "string"; + gsmap[QDBusSignature("a{gs}")] = "array of dict_entry of (signature, string)"; + QTest::newRow("gs-map") << qVariantFromValue(gsmap) << "a{gs}" + << "[Argument: a{gs} {[Signature: a{gs}] = \"array of dict_entry of (signature, string)\", [Signature: i] = \"int32\", [Signature: s] = \"string\"}]"; + + if (fileDescriptorPassing) { + svmap["zzfiledescriptor"] = qVariantFromValue(QDBusUnixFileDescriptor(fileDescriptorForTest())); + QTest::newRow("sv-map1-fd") << qVariantFromValue(svmap) << "a{sv}" + << "[Argument: a{sv} {\"a\" = [Variant(int): 1], \"b\" = [Variant(QByteArray): {99}], \"c\" = [Variant(QString): \"b\"], \"d\" = [Variant(uint): 42], \"e\" = [Variant(short): -47], \"f\" = [Variant: [Variant(int): 0]], \"zzfiledescriptor\" = [Variant(QDBusUnixFileDescriptor): [Unix FD: valid]]}]"; + } + + svmap.clear(); + svmap["ismap"] = qVariantFromValue(ismap); + svmap["ssmap"] = qVariantFromValue(ssmap); + svmap["osmap"] = qVariantFromValue(osmap); + svmap["gsmap"] = qVariantFromValue(gsmap); + QTest::newRow("sv-map2") << qVariantFromValue(svmap) << "a{sv}" + << "[Argument: a{sv} {\"gsmap\" = [Variant: [Argument: a{gs} {[Signature: a{gs}] = \"array of dict_entry of (signature, string)\", [Signature: i] = \"int32\", [Signature: s] = \"string\"}]], \"ismap\" = [Variant: [Argument: a{is} {-47 = \"c\", 1 = \"a\", 2000 = \"b\"}]], \"osmap\" = [Variant: [Argument: a{os} {[ObjectPath: /] = \"root\", [ObjectPath: /bar/baz] = \"bar and baz\", [ObjectPath: /foo] = \"foo\"}]], \"ssmap\" = [Variant: [Argument: a{ss} {\"a\" = \"a\", \"b\" = \"c\", \"c\" = \"b\"}]]}]"; +} + +void tst_QDBusMarshall::sendStructs_data() +{ + QTest::addColumn("value"); + QTest::addColumn("sig"); + QTest::addColumn("stringResult"); + + QTest::newRow("point") << QVariant(QPoint(1, 2)) << "(ii)" << "[Argument: (ii) 1, 2]"; + QTest::newRow("pointf") << QVariant(QPointF(1.5, -1.5)) << "(dd)" << "[Argument: (dd) 1.5, -1.5]"; + + QTest::newRow("size") << QVariant(QSize(1, 2)) << "(ii)" << "[Argument: (ii) 1, 2]"; + QTest::newRow("sizef") << QVariant(QSizeF(1.5, 1.5)) << "(dd)" << "[Argument: (dd) 1.5, 1.5]"; + + QTest::newRow("rect") << QVariant(QRect(1, 2, 3, 4)) << "(iiii)" << "[Argument: (iiii) 1, 2, 3, 4]"; + QTest::newRow("rectf") << QVariant(QRectF(0.5, 0.5, 1.5, 1.5)) << "(dddd)" << "[Argument: (dddd) 0.5, 0.5, 1.5, 1.5]"; + + QTest::newRow("line") << QVariant(QLine(1, 2, 3, 4)) << "((ii)(ii))" + << "[Argument: ((ii)(ii)) [Argument: (ii) 1, 2], [Argument: (ii) 3, 4]]"; + QTest::newRow("linef") << QVariant(QLineF(0.5, 0.5, 1.5, 1.5)) << "((dd)(dd))" + << "[Argument: ((dd)(dd)) [Argument: (dd) 0.5, 0.5], [Argument: (dd) 1.5, 1.5]]"; + + QDate date(2006, 6, 18); + QTime time(12, 25, 00); // the date I wrote this test on :-) + QTest::newRow("date") << QVariant(date) << "(iii)" << "[Argument: (iii) 2006, 6, 18]"; + QTest::newRow("time") << QVariant(time) << "(iiii)" << "[Argument: (iiii) 12, 25, 0, 0]"; + QTest::newRow("datetime") << QVariant(QDateTime(date, time)) << "((iii)(iiii)i)" + << "[Argument: ((iii)(iiii)i) [Argument: (iii) 2006, 6, 18], [Argument: (iiii) 12, 25, 0, 0], 0]"; + + MyStruct ms = { 1, "Hello, World" }; + QTest::newRow("int-string") << qVariantFromValue(ms) << "(is)" << "[Argument: (is) 1, \"Hello, World\"]"; + + MyVariantMapStruct mvms = { "Hello, World", QVariantMap() }; + QTest::newRow("string-variantmap") << qVariantFromValue(mvms) << "(sa{sv})" << "[Argument: (sa{sv}) \"Hello, World\", [Argument: a{sv} {}]]"; + + // use only basic types, otherwise comparison will fail + mvms.map["int"] = 42; + mvms.map["uint"] = 42u; + mvms.map["short"] = qVariantFromValue(-47); + mvms.map["bytearray"] = QByteArray("Hello, world"); + QTest::newRow("string-variantmap2") << qVariantFromValue(mvms) << "(sa{sv})" << "[Argument: (sa{sv}) \"Hello, World\", [Argument: a{sv} {\"bytearray\" = [Variant(QByteArray): {72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100}], \"int\" = [Variant(int): 42], \"short\" = [Variant(short): -47], \"uint\" = [Variant(uint): 42]}]]"; + + QList list; + QTest::newRow("empty-list-of-string-variantmap") << qVariantFromValue(list) << "a(sa{sv})" << "[Argument: a(sa{sv}) {}]"; + list << mvms; + QTest::newRow("list-of-string-variantmap") << qVariantFromValue(list) << "a(sa{sv})" << "[Argument: a(sa{sv}) {[Argument: (sa{sv}) \"Hello, World\", [Argument: a{sv} {\"bytearray\" = [Variant(QByteArray): {72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100}], \"int\" = [Variant(int): 42], \"short\" = [Variant(short): -47], \"uint\" = [Variant(uint): 42]}]]}]"; + + if (fileDescriptorPassing) { + MyFileDescriptorStruct fds; + fds.fd = QDBusUnixFileDescriptor(fileDescriptorForTest()); + QTest::newRow("fdstruct") << qVariantFromValue(fds) << "(h)" << "[Argument: (h) [Unix FD: valid]]"; + + QList fdlist; + QTest::newRow("empty-list-of-fdstruct") << qVariantFromValue(fdlist) << "a(h)" << "[Argument: a(h) {}]"; + + fdlist << fds; + QTest::newRow("list-of-fdstruct") << qVariantFromValue(fdlist) << "a(h)" << "[Argument: a(h) {[Argument: (h) [Unix FD: valid]]}]"; + } +} + +void tst_QDBusMarshall::sendComplex_data() +{ + QTest::addColumn("value"); + QTest::addColumn("sig"); + QTest::addColumn("stringResult"); + + QList dtlist; + QTest::newRow("empty-datetimelist") << qVariantFromValue(dtlist) << "a((iii)(iiii)i)" + << "[Argument: a((iii)(iiii)i) {}]"; + dtlist << QDateTime(); + QTest::newRow("list-of-emptydatetime") << qVariantFromValue(dtlist) << "a((iii)(iiii)i)" + << "[Argument: a((iii)(iiii)i) {[Argument: ((iii)(iiii)i) [Argument: (iii) 0, 0, 0], [Argument: (iiii) -1, -1, -1, -1], 0]}]"; + dtlist << QDateTime(QDate(1977, 9, 13), QTime(0, 0, 0)) + << QDateTime(QDate(2006, 6, 18), QTime(13, 14, 0)); + QTest::newRow("datetimelist") << qVariantFromValue(dtlist) << "a((iii)(iiii)i)" + << "[Argument: a((iii)(iiii)i) {[Argument: ((iii)(iiii)i) [Argument: (iii) 0, 0, 0], [Argument: (iiii) -1, -1, -1, -1], 0], [Argument: ((iii)(iiii)i) [Argument: (iii) 1977, 9, 13], [Argument: (iiii) 0, 0, 0, 0], 0], [Argument: ((iii)(iiii)i) [Argument: (iii) 2006, 6, 18], [Argument: (iiii) 13, 14, 0, 0], 0]}]"; + + QHash lldtmap; + QTest::newRow("empty-lldtmap") << qVariantFromValue(lldtmap) << "a{x((iii)(iiii)i)}" + << "[Argument: a{x((iii)(iiii)i)} {}]"; + lldtmap[0] = QDateTime(); + lldtmap[1] = QDateTime(QDate(1970, 1, 1), QTime(0, 0, 1), Qt::UTC); + lldtmap[1150629776] = QDateTime(QDate(2006, 6, 18), QTime(11, 22, 56), Qt::UTC); + QTest::newRow("lldtmap") << qVariantFromValue(lldtmap) << "a{x((iii)(iiii)i)}" + << "[Argument: a{x((iii)(iiii)i)} {0 = [Argument: ((iii)(iiii)i) [Argument: (iii) 0, 0, 0], [Argument: (iiii) -1, -1, -1, -1], 0], 1 = [Argument: ((iii)(iiii)i) [Argument: (iii) 1970, 1, 1], [Argument: (iiii) 0, 0, 1, 0], 1], 1150629776 = [Argument: ((iii)(iiii)i) [Argument: (iii) 2006, 6, 18], [Argument: (iiii) 11, 22, 56, 0], 1]}]"; + + + QMap ismap; + ismap[1] = "a"; + ismap[2000] = "b"; + ismap[-47] = "c"; + + QMap ssmap; + ssmap["a"] = "a"; + ssmap["c"] = "b"; + ssmap["b"] = "c"; + + QHash gsmap; + gsmap[QDBusSignature("i")] = "int32"; + gsmap[QDBusSignature("s")] = "string"; + gsmap[QDBusSignature("a{gs}")] = "array of dict_entry of (signature, string)"; + + QVariantMap svmap; + svmap["a"] = 1; + svmap["c"] = "b"; + svmap["b"] = QByteArray("c"); + svmap["d"] = 42U; + svmap["e"] = qVariantFromValue(short(-47)); + svmap["f"] = qVariantFromValue(QDBusVariant(0)); + svmap["date"] = QDate(1977, 1, 1); + svmap["time"] = QTime(8, 58, 0); + svmap["datetime"] = QDateTime(QDate(13, 9, 2008), QTime(8, 59, 31)); + svmap["pointf"] = QPointF(0.5, -0.5); + svmap["ismap"] = qVariantFromValue(ismap); + svmap["ssmap"] = qVariantFromValue(ssmap); + svmap["gsmap"] = qVariantFromValue(gsmap); + svmap["dtlist"] = qVariantFromValue(dtlist); + svmap["lldtmap"] = qVariantFromValue(lldtmap); + QTest::newRow("sv-map") << qVariantFromValue(svmap) << "a{sv}" + << "[Argument: a{sv} {\"a\" = [Variant(int): 1], \"b\" = [Variant(QByteArray): {99}], \"c\" = [Variant(QString): \"b\"], \"d\" = [Variant(uint): 42], \"date\" = [Variant: [Argument: (iii) 1977, 1, 1]], \"datetime\" = [Variant: [Argument: ((iii)(iiii)i) [Argument: (iii) 0, 0, 0], [Argument: (iiii) 8, 59, 31, 0], 0]], \"dtlist\" = [Variant: [Argument: a((iii)(iiii)i) {[Argument: ((iii)(iiii)i) [Argument: (iii) 0, 0, 0], [Argument: (iiii) -1, -1, -1, -1], 0], [Argument: ((iii)(iiii)i) [Argument: (iii) 1977, 9, 13], [Argument: (iiii) 0, 0, 0, 0], 0], [Argument: ((iii)(iiii)i) [Argument: (iii) 2006, 6, 18], [Argument: (iiii) 13, 14, 0, 0], 0]}]], \"e\" = [Variant(short): -47], \"f\" = [Variant: [Variant(int): 0]], \"gsmap\" = [Variant: [Argument: a{gs} {[Signature: a{gs}] = \"array of dict_entry of (signature, string)\", [Signature: i] = \"int32\", [Signature: s] = \"string\"}]], \"ismap\" = [Variant: [Argument: a{is} {-47 = \"c\", 1 = \"a\", 2000 = \"b\"}]], \"lldtmap\" = [Variant: [Argument: a{x((iii)(iiii)i)} {0 = [Argument: ((iii)(iiii)i) [Argument: (iii) 0, 0, 0], [Argument: (iiii) -1, -1, -1, -1], 0], 1 = [Argument: ((iii)(iiii)i) [Argument: (iii) 1970, 1, 1], [Argument: (iiii) 0, 0, 1, 0], 1], 1150629776 = [Argument: ((iii)(iiii)i) [Argument: (iii) 2006, 6, 18], [Argument: (iiii) 11, 22, 56, 0], 1]}]], \"pointf\" = [Variant: [Argument: (dd) 0.5, -0.5]], \"ssmap\" = [Variant: [Argument: a{ss} {\"a\" = \"a\", \"b\" = \"c\", \"c\" = \"b\"}]], \"time\" = [Variant: [Argument: (iiii) 8, 58, 0, 0]]}]"; +} + +void tst_QDBusMarshall::sendArgument_data() +{ + QTest::addColumn("value"); + QTest::addColumn("sig"); + QTest::addColumn("classification"); + + QDBusArgument(); + QDBusArgument arg; + + arg = QDBusArgument(); + arg << true; + QTest::newRow("bool") << qVariantFromValue(arg) << "b" << int(QDBusArgument::BasicType);; + + arg = QDBusArgument(); + arg << false; + QTest::newRow("bool2") << qVariantFromValue(arg) << "b" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << uchar(1); + QTest::newRow("byte") << qVariantFromValue(arg) << "y" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << short(2); + QTest::newRow("int16") << qVariantFromValue(arg) << "n" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << ushort(3); + QTest::newRow("uint16") << qVariantFromValue(arg) << "q" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << 1; + QTest::newRow("int32") << qVariantFromValue(arg) << "i" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << 2U; + QTest::newRow("uint32") << qVariantFromValue(arg) << "u" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << Q_INT64_C(3); + QTest::newRow("int64") << qVariantFromValue(arg) << "x" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << Q_UINT64_C(4); + QTest::newRow("uint64") << qVariantFromValue(arg) << "t" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << 42.5; + QTest::newRow("double") << qVariantFromValue(arg) << "d" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << QLatin1String("ping"); + QTest::newRow("string") << qVariantFromValue(arg) << "s" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << QDBusObjectPath("/org/kde"); + QTest::newRow("objectpath") << qVariantFromValue(arg) << "o" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << QDBusSignature("g"); + QTest::newRow("signature") << qVariantFromValue(arg) << "g" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << QLatin1String(""); + QTest::newRow("emptystring") << qVariantFromValue(arg) << "s" << int(QDBusArgument::BasicType); + + arg = QDBusArgument(); + arg << QString(); + QTest::newRow("nullstring") << qVariantFromValue(arg) << "s" << int(QDBusArgument::BasicType); + + if (fileDescriptorPassing) { + arg = QDBusArgument(); + arg << QDBusUnixFileDescriptor(fileDescriptorForTest()); + QTest::newRow("filedescriptor") << qVariantFromValue(arg) << "h" << int(QDBusArgument::BasicType); + } + + arg = QDBusArgument(); + arg << QDBusVariant(1); + QTest::newRow("variant") << qVariantFromValue(arg) << "v" << int(QDBusArgument::VariantType); + + arg = QDBusArgument(); + arg << QDBusVariant(qVariantFromValue(QDBusVariant(1))); + QTest::newRow("variant-variant") << qVariantFromValue(arg) << "v" << int(QDBusArgument::VariantType); + + arg = QDBusArgument(); + arg.beginArray(QVariant::Int); + arg << 1 << 2 << 3 << -4; + arg.endArray(); + QTest::newRow("array-of-int") << qVariantFromValue(arg) << "ai" << int(QDBusArgument::ArrayType); + + arg = QDBusArgument(); + arg.beginMap(QVariant::Int, QVariant::UInt); + arg.beginMapEntry(); + arg << 1 << 2U; + arg.endMapEntry(); + arg.beginMapEntry(); + arg << 3 << 4U; + arg.endMapEntry(); + arg.endMap(); + QTest::newRow("map") << qVariantFromValue(arg) << "a{iu}" << int(QDBusArgument::MapType); + + arg = QDBusArgument(); + arg.beginStructure(); + arg << 1 << 2U << short(-3) << ushort(4) << 5.0 << false; + arg.endStructure(); + QTest::newRow("structure") << qVariantFromValue(arg) << "(iunqdb)" << int(QDBusArgument::StructureType); + +#if 0 + // this is now unsupported + arg << 1 << 2U << short(-3) << ushort(4) << 5.0 << false; + QTest::newRow("many-args") << qVariantFromValue(arg) << "(iunqdb)iunqdb"; +#endif +} + +void tst_QDBusMarshall::sendBasic() +{ + QFETCH(QVariant, value); + QFETCH(QString, stringResult); + + QDBusConnection con = QDBusConnection::sessionBus(); + + QVERIFY(con.isConnected()); + + QDBusMessage msg = QDBusMessage::createMethodCall(serviceName, + objectPath, interfaceName, "ping"); + msg << value; + + QDBusMessage reply = con.call(msg); + QVERIFY2(reply.type() == QDBusMessage::ReplyMessage, + qPrintable(reply.errorName() + ": " + reply.errorMessage())); + //qDebug() << reply; + + QCOMPARE(reply.arguments().count(), msg.arguments().count()); + QTEST(reply.signature(), "sig"); + for (int i = 0; i < reply.arguments().count(); ++i) { + QVERIFY(compare(reply.arguments().at(i), msg.arguments().at(i))); + //printf("\n! %s\n* %s\n", qPrintable(qDBusArgumentToString(reply.arguments().at(i))), qPrintable(stringResult)); + QCOMPARE(QDBusUtil::argumentToString(reply.arguments().at(i)), stringResult); + } +} + +void tst_QDBusMarshall::sendVariant() +{ + QFETCH(QVariant, value); + + QDBusConnection con = QDBusConnection::sessionBus(); + + QVERIFY(con.isConnected()); + + QDBusMessage msg = QDBusMessage::createMethodCall(serviceName, + objectPath, interfaceName, "ping"); + msg << qVariantFromValue(QDBusVariant(value)); + + QDBusMessage reply = con.call(msg); + // qDebug() << reply; + + QCOMPARE(reply.arguments().count(), msg.arguments().count()); + QCOMPARE(reply.signature(), QString("v")); + for (int i = 0; i < reply.arguments().count(); ++i) + QVERIFY(compare(reply.arguments().at(i), msg.arguments().at(i))); +} + +void tst_QDBusMarshall::sendArrays() +{ + sendBasic(); +} + +void tst_QDBusMarshall::sendArrayOfArrays() +{ + sendBasic(); +} + +void tst_QDBusMarshall::sendMaps() +{ + sendBasic(); +} + +void tst_QDBusMarshall::sendStructs() +{ + sendBasic(); +} + +void tst_QDBusMarshall::sendComplex() +{ + sendBasic(); +} + +void tst_QDBusMarshall::sendArgument() +{ + QFETCH(QVariant, value); + QFETCH(QString, sig); + + QDBusConnection con = QDBusConnection::sessionBus(); + + QVERIFY(con.isConnected()); + + QDBusMessage msg = QDBusMessage::createMethodCall(serviceName, objectPath, + interfaceName, "ping"); + msg << value; + + QDBusMessage reply = con.call(msg); + +// QCOMPARE(reply.arguments().count(), msg.arguments().count()); + QCOMPARE(reply.signature(), sig); +// for (int i = 0; i < reply.arguments().count(); ++i) +// QVERIFY(compare(reply.arguments().at(i), msg.arguments().at(i))); + + // do it again inside a STRUCT now + QDBusArgument sendArg; + sendArg.beginStructure(); + sendArg.appendVariant(value); + sendArg.endStructure(); + msg.setArguments(QVariantList() << qVariantFromValue(sendArg)); + reply = con.call(msg); + + QCOMPARE(reply.signature(), QString("(%1)").arg(sig)); + QCOMPARE(reply.arguments().at(0).userType(), qMetaTypeId()); + + const QDBusArgument arg = qvariant_cast(reply.arguments().at(0)); + QCOMPARE(int(arg.currentType()), int(QDBusArgument::StructureType)); + + arg.beginStructure(); + QVERIFY(!arg.atEnd()); + QCOMPARE(arg.currentSignature(), sig); + QTEST(int(arg.currentType()), "classification"); + + QVariant extracted = arg.asVariant(); + QVERIFY(arg.atEnd()); + + arg.endStructure(); + QVERIFY(arg.atEnd()); + QCOMPARE(arg.currentType(), QDBusArgument::UnknownType); + + if (value.type() != QVariant::UserType) + QCOMPARE(extracted, value); +} + +void tst_QDBusMarshall::sendSignalErrors() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + + QVERIFY(con.isConnected()); + QDBusMessage msg = QDBusMessage::createSignal("/foo", "local.interfaceName", + "signalName"); + msg << qVariantFromValue(QDBusObjectPath()); + + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); + QVERIFY(!con.send(msg)); + + msg.setArguments(QVariantList()); + QDBusObjectPath path; + + QTest::ignoreMessage(QtWarningMsg, "QDBusObjectPath: invalid path \"abc\""); + path.setPath("abc"); + msg << qVariantFromValue(path); + + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); + QVERIFY(!con.send(msg)); + + QDBusSignature sig; + msg.setArguments(QVariantList() << qVariantFromValue(sig)); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); + QVERIFY(!con.send(msg)); + + QTest::ignoreMessage(QtWarningMsg, "QDBusSignature: invalid signature \"a\""); + sig.setSignature("a"); + msg.setArguments(QVariantList()); + msg << qVariantFromValue(sig); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); + QVERIFY(!con.send(msg)); +} + +void tst_QDBusMarshall::sendCallErrors_data() +{ + QTest::addColumn("service"); + QTest::addColumn("path"); + QTest::addColumn("interface"); + QTest::addColumn("method"); + QTest::addColumn("arguments"); + QTest::addColumn("errorName"); + QTest::addColumn("errorMsg"); + QTest::addColumn("ignoreMsg"); + + // this error comes from the bus server + QTest::newRow("empty-service") << "" << objectPath << interfaceName << "ping" << QVariantList() + << "org.freedesktop.DBus.Error.UnknownMethod" + << "Method \"ping\" with signature \"\" on interface \"com.trolltech.autotests.qpong\" doesn't exist\n" << (const char*)0; + + QTest::newRow("invalid-service") << "this isn't valid" << objectPath << interfaceName << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidService" + << "Invalid service name: this isn't valid" << ""; + + QTest::newRow("empty-path") << serviceName << "" << interfaceName << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidObjectPath" + << "Object path cannot be empty" << ""; + QTest::newRow("invalid-path") << serviceName << "//" << interfaceName << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidObjectPath" + << "Invalid object path: //" << ""; + + // empty interfaces are valid + QTest::newRow("invalid-interface") << serviceName << objectPath << "this isn't valid" << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidInterface" + << "Invalid interface class: this isn't valid" << ""; + + QTest::newRow("empty-method") << serviceName << objectPath << interfaceName << "" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidMember" + << "method name cannot be empty" << ""; + QTest::newRow("invalid-method") << serviceName << objectPath << interfaceName << "this isn't valid" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidMember" + << "Invalid method name: this isn't valid" << ""; + + QTest::newRow("invalid-variant1") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << QVariant()) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Variant containing QVariant::Invalid passed in arguments" + << "QDBusMarshaller: cannot add an invalid QVariant"; + QTest::newRow("invalid-variant1") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusVariant())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Variant containing QVariant::Invalid passed in arguments" + << "QDBusMarshaller: cannot add a null QDBusVariant"; + + QTest::newRow("builtin-unregistered") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << QLocale::c()) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Unregistered type QLocale passed in arguments" + << "QDBusMarshaller: type `QLocale' (18) is not registered with D-BUS. Use qDBusRegisterMetaType to register it"; + + // this type is known to the meta type system, but not registered with D-Bus + qRegisterMetaType(); + QTest::newRow("extra-unregistered") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(UnregisteredType())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Unregistered type UnregisteredType passed in arguments" + << QString("QDBusMarshaller: type `UnregisteredType' (%1) is not registered with D-BUS. Use qDBusRegisterMetaType to register it") + .arg(qMetaTypeId()); + + QTest::newRow("invalid-object-path-arg") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusObjectPath())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Invalid object path passed in arguments" + << ""; + + QTest::newRow("invalid-signature-arg") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusSignature())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Invalid signature passed in arguments" + << ""; + + // invalid file descriptor + if (fileDescriptorPassing) { + QTest::newRow("invalid-file-descriptor") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusUnixFileDescriptor(-1))) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Invalid file descriptor passed in arguments" + << ""; + } +} + +void tst_QDBusMarshall::sendCallErrors() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + QFETCH(QString, service); + QFETCH(QString, path); + QFETCH(QString, interface); + QFETCH(QString, method); + QFETCH(QVariantList, arguments); + QFETCH(QString, errorMsg); + + QFETCH(QString, ignoreMsg); + if (!ignoreMsg.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, ignoreMsg.toLatin1()); + if (!ignoreMsg.isNull()) + QTest::ignoreMessage(QtWarningMsg, + QString("QDBusConnection: error: could not send message to service \"%1\" path \"%2\" interface \"%3\" member \"%4\": %5") + .arg(service, path, interface, method, errorMsg) + .toLatin1()); + + QDBusMessage msg = QDBusMessage::createMethodCall(service, path, interface, method); + msg.setArguments(arguments); + + QDBusMessage reply = con.call(msg, QDBus::Block); + QCOMPARE(reply.type(), QDBusMessage::ErrorMessage); + QTEST(reply.errorName(), "errorName"); + QCOMPARE(reply.errorMessage(), errorMsg); +} + +void tst_QDBusMarshall::receiveUnknownType_data() +{ + QTest::addColumn("receivedTypeId"); + QTest::newRow("in-call") << qMetaTypeId(); + QTest::newRow("type-variant") << qMetaTypeId(); + QTest::newRow("type-array") << qMetaTypeId(); + QTest::newRow("type-struct") << qMetaTypeId(); + QTest::newRow("type-naked") << qMetaTypeId(); +} + +struct DisconnectRawDBus { + static void cleanup(DBusConnection *connection) + { + if (!connection) + return; + dbus_connection_close(connection); + dbus_connection_unref(connection); + } +}; +template struct GenericUnref +{ + static void cleanup(T *type) + { + if (!type) return; + unref(type); + } +}; + +// use these scoped types to avoid memory leaks if QVERIFY or QCOMPARE fails +typedef QScopedPointer ScopedDBusConnection; +typedef QScopedPointer > ScopedDBusMessage; +typedef QScopedPointer > ScopedDBusPendingCall; + +template struct SetResetValue +{ + const T oldValue; + T &value; +public: + SetResetValue(T &v, T newValue) : oldValue(v), value(v) + { + value = newValue; + } + ~SetResetValue() + { + value = oldValue; + } +}; + +void tst_QDBusMarshall::receiveUnknownType() +{ +#ifndef DBUS_TYPE_UNIX_FD + QSKIP("Your system's D-Bus library is too old for this test", SkipAll); +#else + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + // this needs to be implemented in raw + // open a new connection to the bus daemon + DBusError error; + dbus_error_init(&error); + ScopedDBusConnection rawcon(dbus_bus_get_private(DBUS_BUS_SESSION, &error)); + QVERIFY2(rawcon.data(), error.name); + + // check if this bus supports passing file descriptors + if (!dbus_connection_can_send_type(rawcon.data(), DBUS_TYPE_UNIX_FD)) + QSKIP("Your session bus does not allow sending Unix file descriptors", SkipAll); + + // make sure this QDBusConnection won't handle Unix file descriptors + QDBusConnection::ConnectionCapabilities &capabRef = QDBusConnectionPrivate::d(con)->capabilities; + SetResetValue resetter(capabRef, capabRef & ~QDBusConnection::UnixFileDescriptorPassing); + + if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) { + // create a call back to us containing a file descriptor + QDBusMessageSpy spy; + con.registerObject("/spyObject", &spy, QDBusConnection::ExportAllSlots); + ScopedDBusMessage msg(dbus_message_new_method_call(con.baseService().toLatin1(), "/spyObject", NULL, "theSlot")); + + int fd = fileno(stdout); + dbus_message_append_args(msg.data(), DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); + + // try to send to us + DBusPendingCall *pending_ptr; + dbus_connection_send_with_reply(rawcon.data(), msg.data(), &pending_ptr, 1000); + ScopedDBusPendingCall pending(pending_ptr); + + // check that it got sent + while (dbus_connection_dispatch(rawcon.data()) == DBUS_DISPATCH_DATA_REMAINS) + ; + + // now spin our event loop. We don't catch this call, so let's get the reply + QEventLoop loop; + QTimer::singleShot(200, &loop, SLOT(quit())); + loop.exec(); + + // now try to receive the reply + dbus_pending_call_block(pending.data()); + + // check that the spy received what it was supposed to receive + QCOMPARE(spy.list.size(), 1); + QCOMPARE(spy.list.at(0).arguments().size(), 1); + QFETCH(int, receivedTypeId); + QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId); + + msg.reset(dbus_pending_call_steal_reply(pending.data())); + QVERIFY(msg); + QCOMPARE(dbus_message_get_type(msg.data()), DBUS_MESSAGE_TYPE_METHOD_RETURN); + QCOMPARE(dbus_message_get_signature(msg.data()), DBUS_TYPE_INT32_AS_STRING); + + int retval; + QVERIFY(dbus_message_get_args(msg.data(), &error, DBUS_TYPE_INT32, &retval, DBUS_TYPE_INVALID)); + QCOMPARE(retval, 42); + } else { + // create a signal that we'll emit + static const char signalName[] = "signalName"; + static const char interfaceName[] = "local.interface.name"; + ScopedDBusMessage msg(dbus_message_new_signal("/", interfaceName, signalName)); + con.connect(dbus_bus_get_unique_name(rawcon.data()), QString(), interfaceName, signalName, &QTestEventLoop::instance(), SLOT(exitLoop())); + + QDBusMessageSpy spy; + con.connect(dbus_bus_get_unique_name(rawcon.data()), QString(), interfaceName, signalName, &spy, SLOT(theSlot(QDBusMessage))); + + DBusMessageIter iter; + dbus_message_iter_init_append(msg.data(), &iter); + int fd = fileno(stdout); + + if (qstrcmp(QTest::currentDataTag(), "type-naked") == 0) { + // send naked + dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd); + } else { + DBusMessageIter subiter; + if (qstrcmp(QTest::currentDataTag(), "type-variant") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, DBUS_TYPE_UNIX_FD_AS_STRING, &subiter); + else if (qstrcmp(QTest::currentDataTag(), "type-array") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_UNIX_FD_AS_STRING, &subiter); + else if (qstrcmp(QTest::currentDataTag(), "type-struct") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, 0, &subiter); + dbus_message_iter_append_basic(&subiter, DBUS_TYPE_UNIX_FD, &fd); + dbus_message_iter_close_container(&iter, &subiter); + } + + // send it + dbus_connection_send(rawcon.data(), msg.data(), 0); + + // check that it got sent + while (dbus_connection_dispatch(rawcon.data()) == DBUS_DISPATCH_DATA_REMAINS) + ; + + // now let's see what happens + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(spy.list.size(), 1); + QCOMPARE(spy.list.at(0).arguments().count(), 1); + QFETCH(int, receivedTypeId); + //qDebug() << spy.list.at(0).arguments().at(0).typeName(); + QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId); + } +#endif +} + +QTEST_MAIN(tst_QDBusMarshall) +#include "tst_qdbusmarshall.moc" -- cgit v1.2.3