#include // isnan 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) #ifdef USE_PRIVATE_CODE #include "../../qt/src/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))); } 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); } } #endif bool compare(const QVariantList &l1, const QVariantList &l2); bool compare(const QVariantMap &m1, const QVariantMap &m2); bool compare(const QVariant &v1, const QVariant &v2); bool compare(const QList &l1, const QList &l2) { if (l1.count() != l2.count()) return false; QList::ConstIterator it1 = l1.constBegin(); QList::ConstIterator it2 = l2.constBegin(); QList::ConstIterator end = l1.constEnd(); for ( ; it1 != end; ++it1, ++it2) if (isnan(*it1) && isnan(*it2)) continue; else if (*it1 != *it2) return false; return true; } 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; } 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; } bool compare(const QVariant &v1, const QVariant &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 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 return false; // unknown type } 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; }