1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28#include <qmath.h> // qIsNan
29#include <qvariant.h>
30
31#ifdef Q_OS_UNIX
32# include <private/qcore_unix_p.h>
33
34static bool compareFileDescriptors(int fd1, int fd2)
35{
36 QT_STATBUF st1, st2;
37 if (QT_FSTAT(fd: fd1, buf: &st1) == -1 || QT_FSTAT(fd: fd2, buf: &st2) == -1) {
38 perror(s: "fstat");
39 return false;
40 }
41
42 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
43}
44#endif
45
46typedef QMap<int, QString> IntStringMap;
47typedef QMap<QString, QString> StringStringMap;
48typedef QMap<QDBusObjectPath, QString> ObjectPathStringMap;
49typedef QMap<qlonglong, QDateTime> LLDateTimeMap;
50typedef QMap<QDBusSignature, QString> SignatureStringMap;
51Q_DECLARE_METATYPE(StringStringMap)
52Q_DECLARE_METATYPE(LLDateTimeMap)
53
54static bool compare(const QDBusUnixFileDescriptor &t1, const QDBusUnixFileDescriptor &t2)
55{
56 int fd1 = t1.fileDescriptor();
57 int fd2 = t2.fileDescriptor();
58 if ((fd1 == -1 || fd2 == -1) && fd1 != fd2) {
59 // one is valid, the other isn't
60 return false;
61 }
62
63#ifdef Q_OS_UNIX
64 return compareFileDescriptors(fd1, fd2);
65#else
66 return true;
67#endif
68}
69
70struct MyStruct
71{
72 int i;
73 QString s;
74
75 inline bool operator==(const MyStruct &other) const
76 { return i == other.i && s == other.s; }
77};
78Q_DECLARE_METATYPE(MyStruct)
79
80QDBusArgument &operator<<(QDBusArgument &arg, const MyStruct &ms)
81{
82 arg.beginStructure();
83 arg << ms.i << ms.s;
84 arg.endStructure();
85 return arg;
86}
87
88const QDBusArgument &operator>>(const QDBusArgument &arg, MyStruct &ms)
89{
90 arg.beginStructure();
91 arg >> ms.i >> ms.s;
92 arg.endStructure();
93 return arg;
94}
95
96struct MyVariantMapStruct
97{
98 QString s;
99 QVariantMap map;
100
101 inline bool operator==(const MyVariantMapStruct &other) const
102 { return s == other.s && map == other.map; }
103};
104Q_DECLARE_METATYPE(MyVariantMapStruct)
105
106QDBusArgument &operator<<(QDBusArgument &arg, const MyVariantMapStruct &ms)
107{
108 arg.beginStructure();
109 arg << ms.s << ms.map;
110 arg.endStructure();
111 return arg;
112}
113
114const QDBusArgument &operator>>(const QDBusArgument &arg, MyVariantMapStruct &ms)
115{
116 arg.beginStructure();
117 arg >> ms.s >> ms.map;
118 arg.endStructure();
119 return arg;
120}
121
122struct MyFileDescriptorStruct
123{
124 QDBusUnixFileDescriptor fd;
125
126 inline bool operator==(const MyFileDescriptorStruct &other) const
127 { return compare(t1: fd, t2: other.fd); }
128};
129Q_DECLARE_METATYPE(MyFileDescriptorStruct)
130
131QDBusArgument &operator<<(QDBusArgument &arg, const MyFileDescriptorStruct &ms)
132{
133 arg.beginStructure();
134 arg << ms.fd;
135 arg.endStructure();
136 return arg;
137}
138
139const QDBusArgument &operator>>(const QDBusArgument &arg, MyFileDescriptorStruct &ms)
140{
141 arg.beginStructure();
142 arg >> ms.fd;
143 arg.endStructure();
144 return arg;
145}
146
147
148void commonInit()
149{
150 qDBusRegisterMetaType<QList<QDateTime> >();
151 qDBusRegisterMetaType<QList<QStringList> >();
152 qDBusRegisterMetaType<QList<QByteArray> >();
153 qDBusRegisterMetaType<QList<QList<bool> > >();
154 qDBusRegisterMetaType<QList<QList<short> > >();
155 qDBusRegisterMetaType<QList<QList<ushort> > >();
156 qDBusRegisterMetaType<QList<QList<int> > >();
157 qDBusRegisterMetaType<QList<QList<uint> > >();
158 qDBusRegisterMetaType<QList<QList<qlonglong> > >();
159 qDBusRegisterMetaType<QList<QList<qulonglong> > >();
160 qDBusRegisterMetaType<QList<QList<double> > >();
161 qDBusRegisterMetaType<QList<QList<QDBusObjectPath> > >();
162 qDBusRegisterMetaType<QList<QList<QDBusSignature> > >();
163 qDBusRegisterMetaType<QList<QVariantList> >();
164
165 qDBusRegisterMetaType<QMap<int, QString> >();
166 qDBusRegisterMetaType<QMap<QString, QString> >();
167 qDBusRegisterMetaType<QMap<QDBusObjectPath, QString> >();
168 qDBusRegisterMetaType<QMap<qlonglong, QDateTime> >();
169 qDBusRegisterMetaType<QMap<QDBusSignature, QString> >();
170
171 qDBusRegisterMetaType<MyStruct>();
172 qDBusRegisterMetaType<MyVariantMapStruct>();
173 qDBusRegisterMetaType<QList<MyVariantMapStruct> >();
174 qDBusRegisterMetaType<MyFileDescriptorStruct>();
175 qDBusRegisterMetaType<QList<MyFileDescriptorStruct> >();
176}
177#ifdef USE_PRIVATE_CODE
178#include "private/qdbusintrospection_p.h"
179
180// just to make it easier:
181typedef QDBusIntrospection::Interfaces InterfaceMap;
182typedef QDBusIntrospection::Objects ObjectMap;
183typedef QDBusIntrospection::Arguments ArgumentList;
184typedef QDBusIntrospection::Annotations AnnotationsMap;
185typedef QDBusIntrospection::Methods MethodMap;
186typedef QDBusIntrospection::Signals SignalMap;
187typedef QDBusIntrospection::Properties PropertyMap;
188
189Q_DECLARE_METATYPE(QDBusIntrospection::Method)
190Q_DECLARE_METATYPE(QDBusIntrospection::Signal)
191Q_DECLARE_METATYPE(QDBusIntrospection::Property)
192Q_DECLARE_METATYPE(MethodMap)
193Q_DECLARE_METATYPE(SignalMap)
194Q_DECLARE_METATYPE(PropertyMap)
195
196inline QDBusIntrospection::Argument arg(const char* type, const char *name = 0)
197{
198 QDBusIntrospection::Argument retval;
199 retval.type = QLatin1String(type);
200 retval.name = QLatin1String(name);
201 return retval;
202}
203
204template<typename T>
205inline QMap<QString, T>& operator<<(QMap<QString, T>& map, const T& m)
206{ map.insertMulti(m.name, m); return map; }
207
208inline const char* mapName(const MethodMap&)
209{ return "MethodMap"; }
210
211inline const char* mapName(const SignalMap&)
212{ return "SignalMap"; }
213
214inline const char* mapName(const PropertyMap&)
215{ return "PropertyMap"; }
216
217QString printable(const QDBusIntrospection::Method& m)
218{
219 QString result = "method " + m.name + "(";
220 foreach (QDBusIntrospection::Argument arg, m.inputArgs)
221 result += QString("in %1 %2, ")
222 .arg(arg.type, arg.name);
223 foreach (QDBusIntrospection::Argument arg, m.outputArgs)
224 result += QString("out %1 %2, ")
225 .arg(arg.type, arg.name);
226 AnnotationsMap::const_iterator it = m.annotations.begin();
227 for ( ; it != m.annotations.end(); ++it)
228 result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
229
230 result += ")";
231 return result;
232}
233
234QString printable(const QDBusIntrospection::Signal& s)
235{
236 QString result = "signal " + s.name + "(";
237 foreach (QDBusIntrospection::Argument arg, s.outputArgs)
238 result += QString("out %1 %2, ")
239 .arg(arg.type, arg.name);
240 AnnotationsMap::const_iterator it = s.annotations.begin();
241 for ( ; it != s.annotations.end(); ++it)
242 result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
243
244 result += ")";
245 return result;
246}
247
248QString printable(const QDBusIntrospection::Property& p)
249{
250 QString result;
251 if (p.access == QDBusIntrospection::Property::Read)
252 result = "property read %1 %2, ";
253 else if (p.access == QDBusIntrospection::Property::Write)
254 result = "property write %1 %2, ";
255 else
256 result = "property readwrite %1 %2, ";
257 result = result.arg(p.type, p.name);
258
259 AnnotationsMap::const_iterator it = p.annotations.begin();
260 for ( ; it != p.annotations.end(); ++it)
261 result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
262
263 return result;
264}
265
266template<typename T>
267char* printableMap(const QMap<QString, T>& map)
268{
269 QString contents = "\n";
270 typename QMap<QString, T>::const_iterator it = map.begin();
271 for ( ; it != map.end(); ++it) {
272 if (it.key() != it.value().name)
273 contents += it.value().name + ":";
274 contents += printable(it.value());
275 contents += ";\n";
276 }
277
278 QString result("%1(size = %2): {%3}");
279 return qstrdup(qPrintable(result
280 .arg(mapName(map))
281 .arg(map.size())
282 .arg(contents)));
283}
284
285QT_BEGIN_NAMESPACE
286namespace QTest {
287 template<>
288 inline char* toString(const MethodMap& map)
289 {
290 return printableMap(map);
291 }
292
293 template<>
294 inline char* toString(const SignalMap& map)
295 {
296 return printableMap(map);
297 }
298
299 template<>
300 inline char* toString(const PropertyMap& map)
301 {
302 return printableMap(map);
303 }
304}
305QT_END_NAMESPACE
306
307#endif
308
309template<typename T>
310bool compare(const T &t1, const T &t2)
311{ return t1 == t2; }
312
313template<>
314bool compare(const QVariant &v1, const QVariant &v2);
315
316bool compare(double d1, double d2)
317{
318 if (qIsNaN(d: d1) && qIsNaN(d: d2))
319 return true;
320 return d1 == d2;
321}
322
323template<>
324bool compare(const QString &s1, const QString &s2)
325{
326 if (s1.isEmpty() && s2.isEmpty())
327 return true; // regardless of whether one of them is null
328 return s1 == s2;
329}
330
331template<>
332bool compare(const QByteArray &ba1, const QByteArray &ba2)
333{
334 if (ba1.isEmpty() && ba2.isEmpty())
335 return true; // regardless of whether one of them is null
336 return ba1 == ba2;
337}
338
339template<>
340bool compare(const QDBusVariant &s1, const QDBusVariant &s2)
341{
342 return compare(v1: s1.variant(), v2: s2.variant());
343}
344
345template<typename T>
346bool compare(const QList<T> &l1, const QList<T> &l2)
347{
348 if (l1.count() != l2.count())
349 return false;
350
351 typename QList<T>::ConstIterator it1 = l1.constBegin();
352 typename QList<T>::ConstIterator it2 = l2.constBegin();
353 typename QList<T>::ConstIterator end = l1.constEnd();
354 for ( ; it1 != end; ++it1, ++it2)
355 if (!compare(*it1, *it2))
356 return false;
357 return true;
358}
359
360template<typename Key, typename T>
361bool compare(const QMap<Key, T> &m1, const QMap<Key, T> &m2)
362{
363 if (m1.count() != m2.size())
364 return false;
365 typename QMap<Key, T>::ConstIterator i1 = m1.constBegin();
366 typename QMap<Key, T>::ConstIterator end = m1.constEnd();
367 for ( ; i1 != end; ++i1) {
368 typename QMap<Key, T>::ConstIterator i2 = m2.find(i1.key());
369 if (i2 == m2.constEnd())
370 return false;
371 if (!compare(*i1, *i2))
372 return false;
373 }
374 return true;
375}
376
377template<typename T>
378inline bool compare(const QDBusArgument &arg, const QVariant &v2, T * = 0)
379{
380 return compare(qdbus_cast<T>(arg), qvariant_cast<T>(v2));
381}
382
383bool compareToArgument(const QDBusArgument &arg, const QVariant &v2)
384{
385 if (arg.currentSignature() != QDBusMetaType::typeToSignature(type: v2.userType()))
386 return false;
387
388 // try to demarshall the arg according to v2
389 switch (v2.userType())
390 {
391 case QVariant::Bool:
392 return compare<bool>(arg, v2);
393 case QMetaType::UChar:
394 return compare<uchar>(arg, v2);
395 case QMetaType::Short:
396 return compare<short>(arg, v2);
397 case QMetaType::UShort:
398 return compare<ushort>(arg, v2);
399 case QVariant::Int:
400 return compare<int>(arg, v2);
401 case QVariant::UInt:
402 return compare<uint>(arg, v2);
403 case QVariant::LongLong:
404 return compare<qlonglong>(arg, v2);
405 case QVariant::ULongLong:
406 return compare<qulonglong>(arg, v2);
407 case QVariant::Double:
408 return compare<double>(arg, v2);
409 case QVariant::String:
410 return compare<QString>(arg, v2);
411 case QVariant::ByteArray:
412 return compare<QByteArray>(arg, v2);
413 case QVariant::List:
414 return compare<QVariantList>(arg, v2);
415 case QVariant::Map:
416 return compare<QVariantMap>(arg, v2);
417 case QVariant::Point:
418 return compare<QPoint>(arg, v2);
419 case QVariant::PointF:
420 return compare<QPointF>(arg, v2);
421 case QVariant::Size:
422 return compare<QSize>(arg, v2);
423 case QVariant::SizeF:
424 return compare<QSizeF>(arg, v2);
425 case QVariant::Line:
426 return compare<QLine>(arg, v2);
427 case QVariant::LineF:
428 return compare<QLineF>(arg, v2);
429 case QVariant::Rect:
430 return compare<QRect>(arg, v2);
431 case QVariant::RectF:
432 return compare<QRectF>(arg, v2);
433 case QVariant::Date:
434 return compare<QDate>(arg, v2);
435 case QVariant::Time:
436 return compare<QTime>(arg, v2);
437 case QVariant::DateTime:
438 return compare<QDateTime>(arg, v2);
439 default:
440 int id = v2.userType();
441 if (id == qMetaTypeId<QDBusObjectPath>())
442 return compare<QDBusObjectPath>(arg, v2);
443 else if (id == qMetaTypeId<QDBusSignature>())
444 return compare<QDBusSignature>(arg, v2);
445 else if (id == qMetaTypeId<QDBusVariant>())
446 return compare<QDBusVariant>(arg, v2);
447 else if (id == qMetaTypeId<QList<bool> >())
448 return compare<QList<bool> >(arg, v2);
449 else if (id == qMetaTypeId<QList<short> >())
450 return compare<QList<short> >(arg, v2);
451 else if (id == qMetaTypeId<QList<ushort> >())
452 return compare<QList<ushort> >(arg, v2);
453 else if (id == qMetaTypeId<QList<int> >())
454 return compare<QList<int> >(arg, v2);
455 else if (id == qMetaTypeId<QList<uint> >())
456 return compare<QList<uint> >(arg, v2);
457 else if (id == qMetaTypeId<QList<qlonglong> >())
458 return compare<QList<qlonglong> >(arg, v2);
459 else if (id == qMetaTypeId<QList<qulonglong> >())
460 return compare<QList<qulonglong> >(arg, v2);
461 else if (id == qMetaTypeId<QList<double> >())
462 return compare<QList<double> >(arg, v2);
463 else if (id == qMetaTypeId<QList<QDBusObjectPath> >())
464 return compare<QList<QDBusObjectPath> >(arg, v2);
465 else if (id == qMetaTypeId<QList<QDBusSignature> >())
466 return compare<QList<QDBusSignature> >(arg, v2);
467 else if (id == qMetaTypeId<QList<QDBusUnixFileDescriptor> >())
468 return compare<QList<QDBusUnixFileDescriptor> >(arg, v2);
469 else if (id == qMetaTypeId<QList<QDateTime> >())
470 return compare<QList<QDateTime> >(arg, v2);
471
472 else if (id == qMetaTypeId<QMap<int, QString> >())
473 return compare<QMap<int, QString> >(arg, v2);
474 else if (id == qMetaTypeId<QMap<QString, QString> >())
475 return compare<QMap<QString, QString> >(arg, v2);
476 else if (id == qMetaTypeId<QMap<QDBusObjectPath, QString> >())
477 return compare<QMap<QDBusObjectPath, QString> >(arg, v2);
478 else if (id == qMetaTypeId<QMap<qlonglong, QDateTime> >())
479 return compare<QMap<qlonglong, QDateTime> >(arg, v2);
480 else if (id == qMetaTypeId<QMap<QDBusSignature, QString> >())
481 return compare<QMap<QDBusSignature, QString> >(arg, v2);
482
483 else if (id == qMetaTypeId<QList<QByteArray> >())
484 return compare<QList<QByteArray> >(arg, v2);
485 else if (id == qMetaTypeId<QList<QList<bool> > >())
486 return compare<QList<QList<bool> > >(arg, v2);
487 else if (id == qMetaTypeId<QList<QList<short> > >())
488 return compare<QList<QList<short> > >(arg, v2);
489 else if (id == qMetaTypeId<QList<QList<ushort> > >())
490 return compare<QList<QList<ushort> > >(arg, v2);
491 else if (id == qMetaTypeId<QList<QList<int> > >())
492 return compare<QList<QList<int> > >(arg, v2);
493 else if (id == qMetaTypeId<QList<QList<uint> > >())
494 return compare<QList<QList<uint> > >(arg, v2);
495 else if (id == qMetaTypeId<QList<QList<qlonglong> > >())
496 return compare<QList<QList<qlonglong> > >(arg, v2);
497 else if (id == qMetaTypeId<QList<QList<qulonglong> > >())
498 return compare<QList<QList<qulonglong> > >(arg, v2);
499 else if (id == qMetaTypeId<QList<QList<double> > >())
500 return compare<QList<QList<double> > >(arg, v2);
501 else if (id == qMetaTypeId<QList<QStringList> >())
502 return compare<QList<QStringList> >(arg, v2);
503 else if (id == qMetaTypeId<QList<QVariantList> >())
504 return compare<QList<QVariantList> >(arg, v2);
505
506 else if (id == qMetaTypeId<MyStruct>())
507 return compare<MyStruct>(arg, v2);
508
509 else if (id == qMetaTypeId<MyVariantMapStruct>())
510 return compare<MyVariantMapStruct>(arg, v2);
511 else if (id == qMetaTypeId<QList<MyVariantMapStruct> >())
512 return compare<QList<MyVariantMapStruct> >(arg, v2);
513 else if (id == qMetaTypeId<MyFileDescriptorStruct>())
514 return compare<MyFileDescriptorStruct>(arg, v2);
515 else if (id == qMetaTypeId<QList<MyFileDescriptorStruct> >())
516 return compare<QList<MyFileDescriptorStruct> >(arg, v2);
517 }
518
519 qWarning() << "Unexpected QVariant type" << v2.userType()
520 << QByteArray(QDBusMetaType::typeToSignature(type: v2.userType()))
521 << QMetaType::typeName(type: v2.userType());
522 return false;
523}
524
525template<> bool compare(const QVariant &v1, const QVariant &v2)
526{
527 // v1 is the one that came from the network
528 // v2 is the one that we sent
529
530 if (v1.userType() == qMetaTypeId<QDBusArgument>())
531 // this argument has been left un-demarshalled
532 return compareToArgument(arg: qvariant_cast<QDBusArgument>(v: v1), v2);
533
534 if (v1.userType() != v2.userType())
535 return false;
536
537 int id = v1.userType();
538 if (id == QVariant::List)
539 return compare(l1: v1.toList(), l2: v2.toList());
540
541 else if (id == QVariant::Map)
542 return compare(m1: v1.toMap(), m2: v2.toMap());
543
544 else if (id == QVariant::String)
545 return compare(s1: v1.toString(), s2: v2.toString());
546
547 else if (id == QVariant::ByteArray)
548 return compare(ba1: v1.toByteArray(), ba2: v2.toByteArray());
549
550 else if (id == QMetaType::UChar)
551 return qvariant_cast<uchar>(v: v1) == qvariant_cast<uchar>(v: v2);
552
553 else if (id == QMetaType::Short)
554 return qvariant_cast<short>(v: v1) == qvariant_cast<short>(v: v2);
555
556 else if (id == QMetaType::UShort)
557 return qvariant_cast<ushort>(v: v1) == qvariant_cast<ushort>(v: v2);
558
559 else if (id == qMetaTypeId<QDBusObjectPath>())
560 return qvariant_cast<QDBusObjectPath>(v: v1).path() == qvariant_cast<QDBusObjectPath>(v: v2).path();
561
562 else if (id == qMetaTypeId<QDBusSignature>())
563 return qvariant_cast<QDBusSignature>(v: v1).signature() == qvariant_cast<QDBusSignature>(v: v2).signature();
564
565 else if (id == qMetaTypeId<QDBusUnixFileDescriptor>())
566 return compare(t1: qvariant_cast<QDBusUnixFileDescriptor>(v: v1), t2: qvariant_cast<QDBusUnixFileDescriptor>(v: v2));
567
568 else if (id == qMetaTypeId<QDBusVariant>())
569 return compare(v1: qvariant_cast<QDBusVariant>(v: v1).variant(), v2: qvariant_cast<QDBusVariant>(v: v2).variant());
570
571 else if (id == qMetaTypeId<QVariant>())
572 return compare(v1: qvariant_cast<QVariant>(v: v1), v2: qvariant_cast<QVariant>(v: v2));
573
574 else if (id == qMetaTypeId<QList<bool> >())
575 return qvariant_cast<QList<bool> >(v: v1) == qvariant_cast<QList<bool> >(v: v2);
576
577 else if (id == qMetaTypeId<QList<short> >())
578 return qvariant_cast<QList<short> >(v: v1) == qvariant_cast<QList<short> >(v: v2);
579
580 else if (id == qMetaTypeId<QList<ushort> >())
581 return qvariant_cast<QList<ushort> >(v: v1) == qvariant_cast<QList<ushort> >(v: v2);
582
583 else if (id == qMetaTypeId<QList<int> >())
584 return qvariant_cast<QList<int> >(v: v1) == qvariant_cast<QList<int> >(v: v2);
585
586 else if (id == qMetaTypeId<QList<uint> >())
587 return qvariant_cast<QList<uint> >(v: v1) == qvariant_cast<QList<uint> >(v: v2);
588
589 else if (id == qMetaTypeId<QList<qlonglong> >())
590 return qvariant_cast<QList<qlonglong> >(v: v1) == qvariant_cast<QList<qlonglong> >(v: v2);
591
592 else if (id == qMetaTypeId<QList<qulonglong> >())
593 return qvariant_cast<QList<qulonglong> >(v: v2) == qvariant_cast<QList<qulonglong> >(v: v2);
594
595 else if (id == qMetaTypeId<QList<double> >())
596 return compare(l1: qvariant_cast<QList<double> >(v: v1), l2: qvariant_cast<QList<double> >(v: v2));
597
598 else if (id == qMetaTypeId<QVariant>())
599 return compare(v1: qvariant_cast<QVariant>(v: v1), v2: qvariant_cast<QVariant>(v: v2));
600
601 else if (id == qMetaTypeId<QList<QList<bool> > >())
602 return qvariant_cast<QList<QList<bool> > >(v: v1) == qvariant_cast<QList<QList<bool> > >(v: v2);
603
604 else if (id == qMetaTypeId<QList<QList<short> > >())
605 return qvariant_cast<QList<QList<short> > >(v: v1) == qvariant_cast<QList<QList<short> > >(v: v2);
606
607 else if (id == qMetaTypeId<QList<QList<ushort> > >())
608 return qvariant_cast<QList<QList<ushort> > >(v: v1) == qvariant_cast<QList<QList<ushort> > >(v: v2);
609
610 else if (id == qMetaTypeId<QList<QList<int> > >())
611 return qvariant_cast<QList<QList<int> > >(v: v1) == qvariant_cast<QList<QList<int> > >(v: v2);
612
613 else if (id == qMetaTypeId<QList<QList<uint> > >())
614 return qvariant_cast<QList<QList<uint> > >(v: v1) == qvariant_cast<QList<QList<uint> > >(v: v2);
615
616 else if (id == qMetaTypeId<QList<QList<qlonglong> > >())
617 return qvariant_cast<QList<QList<qlonglong> > >(v: v1) == qvariant_cast<QList<QList<qlonglong> > >(v: v2);
618
619 else if (id == qMetaTypeId<QList<QList<qulonglong> > >())
620 return qvariant_cast<QList<QList<qulonglong> > >(v: v1) == qvariant_cast<QList<QList<qulonglong> > >(v: v2);
621
622 else if (id == qMetaTypeId<QList<QList<double> > >())
623 return compare(l1: qvariant_cast<QList<QList<double> > >(v: v1), l2: qvariant_cast<QList<QList<double> > >(v: v2));
624
625 else if (id == qMetaTypeId<QList<QStringList> >())
626 return qvariant_cast<QList<QStringList> >(v: v1) == qvariant_cast<QList<QStringList> >(v: v2);
627
628 else if (id == qMetaTypeId<QList<QByteArray> >())
629 return qvariant_cast<QList<QByteArray> >(v: v1) == qvariant_cast<QList<QByteArray> >(v: v2);
630
631 else if (id == qMetaTypeId<QList<QVariantList> >())
632 return compare(l1: qvariant_cast<QList<QVariantList> >(v: v1), l2: qvariant_cast<QList<QVariantList> >(v: v2));
633
634 else if (id == qMetaTypeId<QMap<int, QString> >())
635 return compare(m1: qvariant_cast<QMap<int, QString> >(v: v1), m2: qvariant_cast<QMap<int, QString> >(v: v2));
636
637 else if (id == qMetaTypeId<QMap<QString, QString> >()) // ssmap
638 return compare(m1: qvariant_cast<QMap<QString, QString> >(v: v1), m2: qvariant_cast<QMap<QString, QString> >(v: v2));
639
640 else if (id == qMetaTypeId<QMap<QDBusObjectPath, QString> >())
641 return compare(m1: qvariant_cast<QMap<QDBusObjectPath, QString> >(v: v1), m2: qvariant_cast<QMap<QDBusObjectPath, QString> >(v: v2));
642
643 else if (id == qMetaTypeId<QMap<qlonglong, QDateTime> >()) // lldtmap
644 return compare(m1: qvariant_cast<QMap<qint64, QDateTime> >(v: v1), m2: qvariant_cast<QMap<qint64, QDateTime> >(v: v2));
645
646 else if (id == qMetaTypeId<QMap<QDBusSignature, QString> >())
647 return compare(m1: qvariant_cast<QMap<QDBusSignature, QString> >(v: v1), m2: qvariant_cast<QMap<QDBusSignature, QString> >(v: v2));
648
649 else if (id == qMetaTypeId<MyStruct>()) // (is)
650 return qvariant_cast<MyStruct>(v: v1) == qvariant_cast<MyStruct>(v: v2);
651
652 else if (id < int(QVariant::UserType)) // yes, v1.type()
653 // QVariant can compare
654 return v1 == v2;
655
656 else {
657 qWarning() << "Please write a comparison case for type" << v1.typeName();
658 return false; // unknown type
659 }
660}
661

source code of qtbase/tests/auto/dbus/qdbusmarshall/common.h