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
29#include <QtTest/QtTest>
30
31#include <qobject.h>
32#include <qmetaobject.h>
33#include <qabstractproxymodel.h>
34#ifdef QT_BUILD_INTERNAL
35#undef QT_BUILD_INTERNAL // Verdigris don't test the internals
36#endif
37
38#include <wobjectimpl.h>
39
40Q_DECLARE_METATYPE(const QMetaObject *)
41
42W_REGISTER_ARGTYPE(QList<QString>)
43
44struct MyStruct
45{
46 int i;
47};
48
49class MyGadget
50{
51 W_GADGET(MyGadget)
52public:
53 MyGadget() {}
54 W_CONSTRUCTOR()
55};
56
57W_GADGET_IMPL(MyGadget)
58
59namespace MyNamespace {
60 // Used in tst_QMetaObject::checkScope
61 class MyClass : public QObject
62 {
63 W_OBJECT(MyClass)
64
65 public:
66 enum MyEnum {
67 MyEnum1,
68 MyEnum2,
69 MyEnum3
70 };
71 enum class MyScopedEnum {
72 Enum1,
73 Enum2,
74 Enum3
75 };
76 enum MyAnotherEnum {
77 MyAnotherEnum1 = 1,
78 MyAnotherEnum2 = 2,
79 MyAnotherEnum3 = -1
80 };
81 enum MyFlag {
82 MyFlag1 = 0x01,
83 MyFlag2 = 0x02,
84 MyFlag3 = 0x04
85 };
86 enum class MyScopedFlag {
87 MyFlag1 = 0x10,
88 MyFlag2 = 0x20,
89 MyFlag3 = 0x40
90 };
91 W_DECLARE_FLAGS(MyFlags, MyFlag)
92 W_DECLARE_FLAGS(MyScopedFlags, MyScopedFlag)
93
94 MyEnum myEnum() const { return m_enum; }
95 void setMyEnum(MyEnum val) { m_enum = val; }
96
97 MyFlags myFlags() const { return m_flags; }
98 void setMyFlags(MyFlags val) { m_flags = val; }
99
100 MyClass(QObject *parent = 0)
101 : QObject(parent),
102 m_enum(MyEnum1),
103 m_flags(MyFlag1|MyFlag2)
104 { }
105 private:
106 W_ENUM(MyEnum, MyEnum1, MyEnum2, MyEnum3)
107 W_ENUM(MyScopedEnum, MyScopedEnum::Enum1, MyScopedEnum::Enum2, MyScopedEnum::Enum3)
108 W_ENUM(MyAnotherEnum,MyAnotherEnum1,MyAnotherEnum2,MyAnotherEnum3)
109 W_FLAG(MyFlags,MyFlag1,MyFlag2,MyFlag3)
110 W_FLAG(MyScopedFlags, MyScopedFlag::MyFlag1, MyScopedFlag::MyFlag2, MyScopedFlag::MyFlag3)
111
112
113 MyEnum m_enum;
114 MyFlags m_flags;
115
116 W_PROPERTY(MyEnum, myEnum READ myEnum WRITE setMyEnum)
117 W_PROPERTY(MyFlags, myFlags READ myFlags WRITE setMyFlags)
118
119
120 };
121 Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::MyFlags)
122
123
124 // test the old Q_ENUMS macro
125 class MyClass2 : public QObject
126 {
127 W_OBJECT(MyClass2)
128
129 public:
130 enum MyEnum {
131 MyEnum1,
132 MyEnum2,
133 MyEnum3
134 };
135 enum MyAnotherEnum {
136 MyAnotherEnum1 = 1,
137 MyAnotherEnum2 = 2,
138 MyAnotherEnum3 = -1
139 };
140 enum MyFlag {
141 MyFlag1 = 0x01,
142 MyFlag2 = 0x02,
143 MyFlag3 = 0x04
144 };
145 Q_DECLARE_FLAGS(MyFlags, MyFlag)
146
147 MyEnum myEnum() const { return m_enum; }
148 void setMyEnum(MyEnum val) { m_enum = val; }
149
150 MyFlags myFlags() const { return m_flags; }
151 void setMyFlags(MyFlags val) { m_flags = val; }
152
153 MyClass2(QObject *parent = 0)
154 : QObject(parent),
155 m_enum(MyEnum1),
156 m_flags(MyFlag1|MyFlag2)
157 { }
158 private:
159
160 W_ENUM(MyEnum, MyEnum1, MyEnum2, MyEnum3)
161 W_ENUM(MyAnotherEnum,MyAnotherEnum1,MyAnotherEnum2,MyAnotherEnum3)
162 W_FLAG(MyFlags,MyFlag1,MyFlag2,MyFlag3)
163
164 MyEnum m_enum;
165 MyFlags m_flags;
166
167 W_PROPERTY(MyEnum, myEnum READ myEnum WRITE setMyEnum)
168 W_PROPERTY(MyFlags, myFlags READ myFlags WRITE setMyFlags)
169
170 };
171
172 // Test inherits
173 class MyClassSubclass : public MyClass
174 {
175 W_OBJECT(MyClassSubclass)
176 };
177
178 class MyClassSubclass2 : public MyClass2
179 {
180 W_OBJECT(MyClassSubclass2)
181 };
182
183 class MyClass2Subclass : public MyClass
184 {
185 W_OBJECT(MyClass2Subclass)
186 };
187
188#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
189 class ClassWithSetterGetterSignals : public QObject
190 {
191 W_OBJECT(ClassWithSetterGetterSignals)
192
193 public:
194 int value1() const { return m_value1; }
195 void setValue1(int v) {
196 if (v != m_value1) {
197 m_value1 = v;
198 Q_EMIT value1Changed();
199 }
200 }
201
202 int value2() const { return m_value2; }
203 void setValue2(int v) {
204 if (v != m_value2) {
205 m_value2 = v;
206 Q_EMIT value2Changed();
207 }
208 }
209
210 Q_SIGNALS:
211 void value1Changed() W_SIGNAL(value1Changed)
212 void value2Changed() W_SIGNAL(value2Changed)
213
214 private:
215 int m_value1 = 0;
216 int m_value2 = 0;
217 };
218
219 class ClassWithSetterGetterSignalsAddsProperties : public ClassWithSetterGetterSignals
220 {
221 W_OBJECT(ClassWithSetterGetterSignalsAddsProperties)
222 W_PROPERTY(int, value1 READ value1 WRITE setValue1 NOTIFY value1Changed)
223 W_PROPERTY(int, value2 READ value2 WRITE setValue2 NOTIFY value2Changed)
224 };
225
226 class ClassWithChangedSignal : public QObject
227 {
228 W_OBJECT(ClassWithChangedSignal)
229
230 public:
231 int value1() const { return m_value1; }
232 void setValue1(int v) {
233 if (v != m_value1) {
234 m_value1 = v;
235 Q_EMIT propertiesChanged();
236 }
237 }
238
239 void thisIsNotASignal() { }
240
241 Q_SIGNALS:
242 void propertiesChanged() W_SIGNAL(propertiesChanged)
243
244 private:
245 int m_value1 = 0;
246 };
247
248 class ClassWithChangedSignalNewValue : public ClassWithChangedSignal
249 {
250 W_OBJECT(ClassWithChangedSignalNewValue)
251
252
253 private:
254 int m_value2 = 0;
255 int m_value3 = 0;
256
257 W_PROPERTY(int, value2 MEMBER m_value2 NOTIFY propertiesChanged)
258#if 0 // With verdigris, this is a compilation error when the NOTIFY signal is not a signal
259 W_PROPERTY(int, value3 MEMBER m_value3 NOTIFY thisIsNotASignal)
260#endif
261 };
262#endif
263}
264W_OBJECT_IMPL(MyNamespace::MyClass)
265W_OBJECT_IMPL(MyNamespace::MyClass2)
266W_OBJECT_IMPL(MyNamespace::MyClassSubclass)
267W_OBJECT_IMPL(MyNamespace::MyClassSubclass2)
268W_OBJECT_IMPL(MyNamespace::MyClass2Subclass)
269#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
270W_OBJECT_IMPL(MyNamespace::ClassWithSetterGetterSignals)
271W_OBJECT_IMPL(MyNamespace::ClassWithSetterGetterSignalsAddsProperties)
272W_OBJECT_IMPL(MyNamespace::ClassWithChangedSignal)
273W_OBJECT_IMPL(MyNamespace::ClassWithChangedSignalNewValue)
274#endif
275
276class tst_QMetaObject : public QObject
277{
278 W_OBJECT(tst_QMetaObject)
279
280public:
281 enum EnumType { EnumType1 };
282 W_ENUM(EnumType,EnumType1);
283
284 void setValue(EnumType) {}
285 EnumType getValue() const { return EnumType1; }
286
287 void set_value(EnumType) {}
288 EnumType get_value() const { return EnumType1; }
289
290 void setVal3(MyStruct) {}
291 MyStruct val3() const { MyStruct s = {42}; return s; }
292
293 void setVal4(const QList<QVariant> &list) { value4 = list; }
294 QList<QVariant> val4() const { return value4; }
295
296 void setVal5(const QVariantList &list) { value5 = list; }
297 QVariantList val5() const { return value5; }
298
299 int value6() const { return 1; }
300
301 void setVal7(MyStruct) {}
302 MyStruct value7() const { MyStruct s = {42}; return s; }
303
304 int value8() const { return 1; }
305
306 int value9() const { return 1; }
307
308 int value10() const { return 1; }
309
310 QList<QVariant> value4;
311 QVariantList value5;
312
313private slots:
314#define DECLARE_TEST(NAME) void NAME(); W_SLOT(NAME)
315 DECLARE_TEST(connectSlotsByName)
316 DECLARE_TEST(invokeMetaMember)
317 DECLARE_TEST(invokePointer)
318 DECLARE_TEST(invokeQueuedMetaMember)
319 DECLARE_TEST(invokeQueuedPointer)
320 DECLARE_TEST(invokeBlockingQueuedMetaMember)
321 DECLARE_TEST(invokeBlockingQueuedPointer)
322 DECLARE_TEST(invokeCustomTypes)
323 DECLARE_TEST(invokeMetaConstructor)
324 DECLARE_TEST(invokeTypedefTypes)
325 DECLARE_TEST(invokeException)
326 DECLARE_TEST(invokeQueuedAutoRegister)
327 DECLARE_TEST(qtMetaObjectInheritance)
328 DECLARE_TEST(normalizedSignature_data)
329 DECLARE_TEST(normalizedSignature)
330 DECLARE_TEST(normalizedType_data)
331 DECLARE_TEST(normalizedType)
332 DECLARE_TEST(customPropertyType)
333 DECLARE_TEST(checkScope_data)
334 DECLARE_TEST(checkScope)
335 DECLARE_TEST(propertyNotify)
336 DECLARE_TEST(propertyConstant)
337 DECLARE_TEST(propertyFinal)
338
339 DECLARE_TEST(stdSet)
340 DECLARE_TEST(classInfo)
341
342 DECLARE_TEST(metaMethod)
343
344 DECLARE_TEST(indexOfMethod_data)
345 DECLARE_TEST(indexOfMethod)
346
347 DECLARE_TEST(indexOfMethodPMF)
348
349#ifdef QT_BUILD_INTERNAL
350 DECLARE_TEST(signalOffset_data)
351 DECLARE_TEST(signalOffset)
352 DECLARE_TEST(signalCount_data)
353 DECLARE_TEST(signalCount)
354 DECLARE_TEST(signal_data)
355 DECLARE_TEST(signal)
356 DECLARE_TEST(signalIndex_data)
357 DECLARE_TEST(signalIndex)
358#endif
359 DECLARE_TEST(enumDebugStream_data)
360 DECLARE_TEST(enumDebugStream)
361
362 DECLARE_TEST(inherits_data)
363 DECLARE_TEST(inherits)
364
365 DECLARE_TEST(notifySignalsInParentClass)
366#undef DECLARE_TEST
367
368signals:
369 void value6Changed()
370 W_SIGNAL(value6Changed)
371 void value7Changed(const QString &_)
372 W_SIGNAL(value7Changed,_)
373
374
375 W_PROPERTY(EnumType, value WRITE setValue READ getValue)
376 W_PROPERTY(EnumType, value2 WRITE set_value READ get_value)
377 W_PROPERTY(MyStruct, value3 WRITE setVal3 READ val3)
378 W_PROPERTY(QList<QVariant>, value4 WRITE setVal4 READ val4)
379 W_PROPERTY(QVariantList, value5 WRITE setVal5 READ val5)
380 W_PROPERTY(int, value6 READ value6 NOTIFY value6Changed)
381 W_PROPERTY(MyStruct, value7 READ value7 WRITE setVal7 NOTIFY value7Changed)
382 W_PROPERTY(int, value8 READ value8)
383 W_PROPERTY(int, value9 READ value9 CONSTANT)
384 W_PROPERTY(int, value10 READ value10 FINAL)
385
386};
387
388W_OBJECT_IMPL(tst_QMetaObject)
389
390
391void tst_QMetaObject::stdSet()
392{
393 QSKIP("Not supported by W_PROPERTY");
394
395 const QMetaObject *mo = metaObject();
396
397 QMetaProperty prop = mo->property(mo->indexOfProperty("value"));
398 QVERIFY(prop.isValid());
399 QVERIFY(prop.hasStdCppSet());
400
401 prop = mo->property(mo->indexOfProperty("value2"));
402 QVERIFY(prop.isValid());
403 QVERIFY(!prop.hasStdCppSet());
404}
405
406class CTestObject: public QObject
407{
408 W_OBJECT(CTestObject)
409
410public:
411 CTestObject(): QObject(), invokeCount1(0), invokeCount2(0)
412 {
413 }
414
415 void fire(const QString &name)
416 {
417 child = new QObject(this);
418 child->setObjectName(name);
419 QMetaObject::connectSlotsByName(this);
420 delete child; child = 0;
421 }
422
423 int invokeCount1;
424 int invokeCount2;
425 QObject *child;
426
427public slots:
428 void on_child1_destroyed(QObject *obj = 0)
429 {
430 ++invokeCount1;
431 if (!obj || obj != child)
432 qWarning() << "on_child1_destroyed invoked with wrong child object";
433 }
434 W_SLOT(on_child1_destroyed)
435 void on_child2_destroyed() { ++invokeCount2; }
436 W_SLOT(on_child2_destroyed)
437};
438
439W_OBJECT_IMPL(CTestObject)
440
441
442class CTestObjectOverloads: public QObject
443{
444 W_OBJECT(CTestObjectOverloads)
445
446public:
447 CTestObjectOverloads(): invokeCount1(0), invokeCount2(0) {}
448
449 int invokeCount1;
450 int invokeCount2;
451 QObject *child;
452
453 void fire(const QString &name)
454 {
455 child = new QObject(this);
456 child->setObjectName(name);
457 QMetaObject::connectSlotsByName(this);
458 delete child; child = 0;
459 }
460
461private slots:
462 void on_child1_destroyed(QObject *obj)
463 {
464 ++invokeCount1;
465 if (!obj || obj != child)
466 qWarning() << "on_child1_destroyed invoked with wrong child object";
467 }
468 W_SLOT(on_child1_destroyed,(QObject*))
469 void on_child1_destroyed() { ++invokeCount2; }
470 W_SLOT(on_child1_destroyed,())
471};
472
473W_OBJECT_IMPL(CTestObjectOverloads)
474
475#define FUNCTION(x) "QMetaObject::" x ": "
476
477void tst_QMetaObject::connectSlotsByName()
478{
479 CTestObject obj;
480 QCOMPARE(obj.invokeCount1, 0);
481 QCOMPARE(obj.invokeCount2, 0);
482
483 QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child1_destroyed(QObject*)");
484 QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()");
485 obj.fire("bubu");
486 QCOMPARE(obj.invokeCount1, 0);
487 QCOMPARE(obj.invokeCount2, 0);
488
489 QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()");
490 obj.fire("child1");
491 QCOMPARE(obj.invokeCount1, 1);
492 QCOMPARE(obj.invokeCount2, 0);
493
494 QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child1_destroyed(QObject*)");
495 obj.fire("child2");
496 QCOMPARE(obj.invokeCount1, 1);
497 QCOMPARE(obj.invokeCount2, 1);
498
499 QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()");
500 obj.fire("child1");
501 QCOMPARE(obj.invokeCount1, 2);
502 QCOMPARE(obj.invokeCount2, 1);
503
504 // now test with real overloads
505 CTestObjectOverloads obj2;
506 obj2.fire("child1");
507 QCOMPARE(obj2.invokeCount1, 1);
508 QCOMPARE(obj2.invokeCount2, 1);
509}
510
511struct MyUnregisteredType { };
512
513static int countedStructObjectsCount = 0;
514struct CountedStruct
515{
516 CountedStruct() { ++countedStructObjectsCount; }
517 CountedStruct(const CountedStruct &) { ++countedStructObjectsCount; }
518 CountedStruct &operator=(const CountedStruct &) { return *this; }
519 ~CountedStruct() { --countedStructObjectsCount; }
520};
521
522#ifndef QT_NO_EXCEPTIONS
523class ObjectException : public std::exception { };
524#endif
525
526W_REGISTER_ARGTYPE(QString&)
527W_REGISTER_ARGTYPE(QThread*)
528W_REGISTER_ARGTYPE(MyUnregisteredType)
529W_REGISTER_ARGTYPE(CountedStruct)
530
531class QtTestObject: public QObject
532{
533 friend class tst_QMetaObject;
534 W_OBJECT(QtTestObject)
535
536public:
537 QtTestObject();
538 QtTestObject(const QString &s) : slotResult(s) {}
539 QtTestObject(QObject *parent);
540 W_CONSTRUCTOR(QObject*)
541
542public slots:
543 void sl0();
544 W_SLOT(sl0)
545 QString sl1(QString s1);
546 W_SLOT(sl1)
547 void sl2(QString s1, QString s2);
548 W_SLOT(sl2)
549 void sl3(QString s1, QString s2, QString s3);
550 W_SLOT(sl3)
551 void sl4(QString s1, QString s2, QString s3, const QString s4);
552 W_SLOT(sl4)
553 void sl5(QString s1, QString s2, QString s3, QString s4, const QString &s5);
554 W_SLOT(sl5)
555 void sl6(QString s1, QString s2, QString s3, QString s4, const QString s5, QString s6);
556 W_SLOT(sl6)
557 void sl7(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7);
558 W_SLOT(sl7)
559 void sl8(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7,
560 QString s8);
561 W_SLOT(sl8)
562 void sl9(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7,
563 QString s8, QString s9);
564 W_SLOT(sl9)
565 void sl10(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7,
566 QString s8, QString s9, QString s10);
567 W_SLOT(sl10)
568 QObject *sl11();
569 W_SLOT(sl11)
570 const char *sl12();
571 W_SLOT(sl12)
572 QList<QString> sl13(QList<QString> l1);
573 W_SLOT(sl13)
574 qint64 sl14();
575 W_SLOT(sl14)
576 void testSender();
577 W_SLOT(testSender)
578
579 void testReference(QString &str);
580 W_SLOT(testReference)
581 void testLongLong(qint64 ll1, quint64 ll2);
582 W_SLOT(testLongLong)
583 void moveToThread(QThread *t)
584 { QObject::moveToThread(t); }
585 W_SLOT(moveToThread)
586
587 void slotWithUnregisteredParameterType(MyUnregisteredType);
588 W_SLOT(slotWithUnregisteredParameterType)
589
590 CountedStruct throwingSlot(const CountedStruct &, CountedStruct s2) {
591#ifndef QT_NO_EXCEPTIONS
592 throw ObjectException();
593#endif
594 return s2;
595 }
596 W_SLOT(throwingSlot)
597
598 void slotWithRegistrableArgument(QtTestObject *o1, QPointer<QtTestObject> o2,
599 QSharedPointer<QtTestObject> o3, QWeakPointer<QtTestObject> o4,
600 QVector<QtTestObject *> o5, QList<QtTestObject *> o6)
601 {
602 slotResult = QLatin1String("slotWithRegistrableArgument:") + o1->slotResult + o2->slotResult
603 + o3->slotResult + o4.data()->slotResult + QString::number(o5.size())
604 + QString::number(o6.size());
605 }
606 W_SLOT(slotWithRegistrableArgument, (QtTestObject*, QPointer<QtTestObject>,
607 QSharedPointer<QtTestObject>, QWeakPointer<QtTestObject>,
608 QVector<QtTestObject*>,QList<QtTestObject*>))
609
610public:
611 static void staticFunction0();
612 static qint64 staticFunction1();
613
614signals:
615 void sig0()
616 W_SIGNAL(sig0)
617 QString sig1(QString s1)
618 W_SIGNAL(sig1,s1)
619 void sig10(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7,
620 QString s8, QString s9, QString s10)
621 W_SIGNAL(sig10,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10)
622
623protected:
624 QtTestObject(QVariant) {}
625private:
626 QtTestObject(QVariant, QVariant) {}
627
628public:
629 QString slotResult;
630 static QString staticResult;
631};
632
633W_OBJECT_IMPL(QtTestObject)
634
635QString QtTestObject::staticResult;
636
637QtTestObject::QtTestObject()
638{
639 connect(this, SIGNAL(sig0()), this, SLOT(sl0()));
640 connect(this, SIGNAL(sig1(QString)), this, SLOT(sl1(QString)));
641}
642
643QtTestObject::QtTestObject(QObject *parent)
644 : QObject(parent)
645{
646}
647
648void QtTestObject::sl0() { slotResult = "sl0"; }
649QString QtTestObject::sl1(QString s1) { slotResult = "sl1:" + s1; return "yessir"; }
650void QtTestObject::sl2(QString s1, QString s2) { slotResult = "sl2:" + s1 + s2; }
651void QtTestObject::sl3(QString s1, QString s2, QString s3)
652{ slotResult = "sl3:" + s1 + s2 + s3; }
653void QtTestObject::sl4(QString s1, QString s2, QString s3, const QString s4)
654{ slotResult = "sl4:" + s1 + s2 + s3 + s4; }
655void QtTestObject::sl5(QString s1, QString s2, QString s3, QString s4, const QString &s5)
656{ slotResult = "sl5:" + s1 + s2 + s3 + s4 + s5; }
657void QtTestObject::sl6(QString s1, QString s2, QString s3, QString s4,
658 const QString s5, QString s6)
659{ slotResult = "sl6:" + s1 + s2 + s3 + s4 + s5 + s6; }
660void QtTestObject::sl7(QString s1, QString s2, QString s3, QString s4, QString s5,
661 QString s6, QString s7)
662{ slotResult = "sl7:" + s1 + s2 + s3 + s4 + s5 + s6 + s7; }
663void QtTestObject::sl8(QString s1, QString s2, QString s3, QString s4, QString s5,
664 QString s6, QString s7, QString s8)
665{ slotResult = "sl8:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8; }
666void QtTestObject::sl9(QString s1, QString s2, QString s3, QString s4, QString s5,
667 QString s6, QString s7, QString s8, QString s9)
668{ slotResult = "sl9:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9; }
669void QtTestObject::sl10(QString s1, QString s2, QString s3, QString s4, QString s5,
670 QString s6, QString s7, QString s8, QString s9, QString s10)
671{ slotResult = "sl10:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10; }
672QObject *QtTestObject::sl11()
673{ slotResult = "sl11"; return this; }
674const char *QtTestObject::sl12()
675{ slotResult = "sl12"; return "foo"; }
676QList<QString> QtTestObject::sl13(QList<QString> l1)
677{ slotResult = "sl13"; return l1; }
678qint64 QtTestObject::sl14()
679{ slotResult = "sl14"; return Q_INT64_C(123456789)*123456789; }
680
681void QtTestObject::testReference(QString &str)
682{ slotResult = "testReference:" + str; str = "gotcha"; }
683
684void QtTestObject::testLongLong(qint64 ll1, quint64 ll2)
685{ slotResult = "testLongLong:" + QString::number(ll1) + "," + QString::number(ll2); }
686
687void QtTestObject::testSender()
688{
689 slotResult = QString::asprintf("%p", sender());
690}
691
692void QtTestObject::slotWithUnregisteredParameterType(MyUnregisteredType)
693{ slotResult = "slotWithUnregisteredReturnType"; }
694
695void QtTestObject::staticFunction0()
696{
697 staticResult = "staticFunction0";
698}
699
700qint64 QtTestObject::staticFunction1()
701{ staticResult = "staticFunction1"; return Q_INT64_C(123456789)*123456789; }
702
703void tst_QMetaObject::invokeMetaMember()
704{
705 QtTestObject obj;
706
707 QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5");
708 QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X");
709
710 // Test nullptr
711 char *nullCharArray = nullptr;
712 const char *nullConstCharArray = nullptr;
713 QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray));
714 QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray));
715 QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0"));
716 QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray));
717 QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray));
718 QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection));
719 QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection));
720 QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection, QGenericReturnArgument()));
721 QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection, QGenericReturnArgument()));
722
723 QVERIFY(QMetaObject::invokeMethod(&obj, "sl0"));
724 QCOMPARE(obj.slotResult, QString("sl0"));
725
726 QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, t1)));
727 QCOMPARE(obj.slotResult, QString("sl1:1"));
728
729 QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Q_ARG(const QString, t1), Q_ARG(QString, t2)));
730 QCOMPARE(obj.slotResult, QString("sl2:12"));
731
732 QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3)));
733 QCOMPARE(obj.slotResult, QString("sl3:123"));
734
735 QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3),
736 Q_ARG(QString, t4)));
737 QCOMPARE(obj.slotResult, QString("sl4:1234"));
738
739 QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3),
740 Q_ARG(QString, t4), Q_ARG(QString, "5")));
741 QCOMPARE(obj.slotResult, QString("sl5:12345"));
742
743 QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3),
744 Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6)));
745 QCOMPARE(obj.slotResult, QString("sl6:123456"));
746
747 QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3),
748 Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6),
749 Q_ARG(QString, t7)));
750 QCOMPARE(obj.slotResult, QString("sl7:1234567"));
751
752 QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3),
753 Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6),
754 Q_ARG(QString, t7), Q_ARG(QString, t8)));
755 QCOMPARE(obj.slotResult, QString("sl8:12345678"));
756
757 QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3),
758 Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6),
759 Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9)));
760 QCOMPARE(obj.slotResult, QString("sl9:123456789"));
761
762 QVERIFY(QMetaObject::invokeMethod(&obj, "sl11"));
763 QCOMPARE(obj.slotResult, QString("sl11"));
764
765 QVERIFY(QMetaObject::invokeMethod(&obj, "testSender"));
766 QCOMPARE(obj.slotResult, QString("0x0"));
767
768 QString refStr("whatever");
769 QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", QGenericArgument("QString&", &refStr)));
770 QCOMPARE(obj.slotResult, QString("testReference:whatever"));
771 QCOMPARE(refStr, QString("gotcha"));
772
773 qint64 ll1 = -1;
774 quint64 ll2 = 0;
775 QVERIFY(QMetaObject::invokeMethod(&obj,
776 "testLongLong",
777 Q_ARG(qint64, ll1),
778 Q_ARG(quint64, ll2)));
779 QCOMPARE(obj.slotResult, QString("testLongLong:-1,0"));
780
781 QString exp;
782 QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_RETURN_ARG(QString, exp), Q_ARG(QString, "bubu")));
783 QCOMPARE(exp, QString("yessir"));
784 QCOMPARE(obj.slotResult, QString("sl1:bubu"));
785
786 QObject *ptr = 0;
787 QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Q_RETURN_ARG(QObject*,ptr)));
788 QCOMPARE(ptr, (QObject *)&obj);
789 QCOMPARE(obj.slotResult, QString("sl11"));
790 // try again with a space:
791 ptr = 0;
792 QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Q_RETURN_ARG(QObject * , ptr)));
793 QCOMPARE(ptr, (QObject *)&obj);
794 QCOMPARE(obj.slotResult, QString("sl11"));
795
796 const char *ptr2 = 0;
797 QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Q_RETURN_ARG(const char*, ptr2)));
798 QVERIFY(ptr2 != 0);
799 QCOMPARE(obj.slotResult, QString("sl12"));
800 // try again with a space:
801 ptr2 = 0;
802 QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Q_RETURN_ARG(char const * , ptr2)));
803 QVERIFY(ptr2 != 0);
804 QCOMPARE(obj.slotResult, QString("sl12"));
805
806 // test w/ template args
807 QList<QString> returnValue, argument;
808 argument << QString("one") << QString("two") << QString("three");
809 QVERIFY(QMetaObject::invokeMethod(&obj, "sl13",
810 Q_RETURN_ARG(QList<QString>, returnValue),
811 Q_ARG(QList<QString>, argument)));
812 QCOMPARE(returnValue, argument);
813 QCOMPARE(obj.slotResult, QString("sl13"));
814
815 // return qint64
816 qint64 return64;
817 QVERIFY(QMetaObject::invokeMethod(&obj, "sl14",
818 Q_RETURN_ARG(qint64, return64)));
819 QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
820 QCOMPARE(obj.slotResult, QString("sl14"));
821
822 //test signals
823 QVERIFY(QMetaObject::invokeMethod(&obj, "sig0"));
824 QCOMPARE(obj.slotResult, QString("sl0"));
825
826 QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_ARG(QString, "baba")));
827 QCOMPARE(obj.slotResult, QString("sl1:baba"));
828
829 exp.clear();
830 QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_RETURN_ARG(QString, exp), Q_ARG(QString, "hehe")));
831 QCOMPARE(exp, QString("yessir"));
832 QCOMPARE(obj.slotResult, QString("sl1:hehe"));
833
834 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()");
835 QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist"));
836 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
837 QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Q_ARG(QString, "arg")));
838 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
839 "Candidates are:\n sl3(QString,QString,QString)");
840 QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Q_ARG(QString, "arg")));
841 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n"
842 "Candidates are:\n sl1(QString)");
843 QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg")));
844
845 //should not have changed since last test.
846 QCOMPARE(exp, QString("yessir"));
847 QCOMPARE(obj.slotResult, QString("sl1:hehe"));
848}
849
850void testFunction(){}
851
852
853void tst_QMetaObject::invokePointer()
854{
855#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 1)
856 QtTestObject obj;
857 QtTestObject *const nullTestObject = nullptr;
858
859 QString t1("1");
860
861 // Test member functions
862 QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0));
863 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0));
864 QCOMPARE(obj.slotResult, QString("sl0"));
865
866 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender));
867 QCOMPARE(obj.slotResult, QString("0x0"));
868
869 qint64 return64 = 0;
870 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, &return64));
871 QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
872 QCOMPARE(obj.slotResult, QString("sl14"));
873
874 // signals
875 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0));
876 QCOMPARE(obj.slotResult, QString("sl0"));
877
878 // Test function pointers
879 QVERIFY(!QMetaObject::invokeMethod(0, &testFunction));
880 QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction));
881
882 QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0));
883 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0));
884 QCOMPARE(QtTestObject::staticResult, QString("staticFunction0"));
885
886 return64 = 0;
887 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, &return64));
888 QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
889 QCOMPARE(QtTestObject::staticResult, QString("staticFunction1"));
890
891 // Test lambdas
892 QCOMPARE(countedStructObjectsCount, 0);
893 {
894 CountedStruct str;
895 QVERIFY(QMetaObject::invokeMethod(&obj, [str, &t1, &obj]() { obj.sl1(t1); }));
896 QCOMPARE(obj.slotResult, QString("sl1:1"));
897 }
898 QCOMPARE(countedStructObjectsCount, 0);
899 {
900 CountedStruct str;
901 QString exp;
902 QVERIFY(QMetaObject::invokeMethod(
903 &obj, [str, &obj]() -> QString { return obj.sl1("bubu"); }, &exp));
904 QCOMPARE(exp, QString("yessir"));
905 QCOMPARE(obj.slotResult, QString("sl1:bubu"));
906 }
907 QCOMPARE(countedStructObjectsCount, 0);
908#if defined(__cpp_init_captures) && QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
909 {
910 CountedStruct str;
911 std::unique_ptr<int> ptr( new int );
912 QVERIFY(QMetaObject::invokeMethod(&obj, [str, &t1, &obj, p = std::move(ptr)]() { obj.sl1(t1); }));
913 QCOMPARE(obj.slotResult, QString("sl1:1"));
914 }
915 QCOMPARE(countedStructObjectsCount, 0);
916#endif
917#endif
918}
919
920void tst_QMetaObject::invokeQueuedMetaMember()
921{
922 QtTestObject obj;
923
924 QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection));
925 QVERIFY(obj.slotResult.isEmpty());
926 qApp->processEvents(QEventLoop::AllEvents);
927 QCOMPARE(obj.slotResult, QString("sl0"));
928 obj.slotResult = QString();
929
930 QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::QueuedConnection, Q_ARG(QString, QString("hallo"))));
931 QVERIFY(obj.slotResult.isEmpty());
932 qApp->processEvents(QEventLoop::AllEvents);
933 QCOMPARE(obj.slotResult, QString("sl1:hallo"));
934 obj.slotResult = QString();
935
936 QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::QueuedConnection, Q_ARG(QString, "1"), Q_ARG(QString, "2"),
937 Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"),
938 Q_ARG(QString, "6"), Q_ARG(QString, "7"), Q_ARG(QString, "8"),
939 Q_ARG(QString, "9")));
940 QVERIFY(obj.slotResult.isEmpty());
941 qApp->processEvents(QEventLoop::AllEvents);
942 QCOMPARE(obj.slotResult, QString("sl9:123456789"));
943
944 // signals
945
946 obj.slotResult.clear();
947 QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection));
948 QVERIFY(obj.slotResult.isEmpty());
949 qApp->processEvents(QEventLoop::AllEvents);
950 QCOMPARE(obj.slotResult, QString("sl0"));
951
952 QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, Q_ARG(QString, "gogo")));
953 qApp->processEvents(QEventLoop::AllEvents);
954 QCOMPARE(obj.slotResult, QString("sl1:gogo"));
955
956 QString exp;
957 QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to invoke methods with return values in queued connections");
958 QVERIFY(!QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, Q_RETURN_ARG(QString, exp),
959 Q_ARG(QString, "nono")));
960
961 qint64 ll1 = -1;
962 quint64 ll2 = 0;
963 QVERIFY(QMetaObject::invokeMethod(&obj,
964 "testLongLong",
965 Qt::QueuedConnection,
966 Q_ARG(qint64, ll1),
967 Q_ARG(quint64, ll2)));
968 qApp->processEvents(QEventLoop::AllEvents);
969 QCOMPARE(obj.slotResult, QString("testLongLong:-1,0"));
970
971 obj.slotResult.clear();
972 {
973 MyUnregisteredType t;
974 QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyUnregisteredType'");
975 QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithUnregisteredParameterType", Qt::QueuedConnection, Q_ARG(MyUnregisteredType, t)));
976 QVERIFY(obj.slotResult.isEmpty());
977 }
978}
979
980void tst_QMetaObject::invokeQueuedPointer()
981{
982#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 1)
983 QtTestObject obj;
984
985 // Test member function
986 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::QueuedConnection));
987 QVERIFY(obj.slotResult.isEmpty());
988 qApp->processEvents(QEventLoop::AllEvents);
989 QCOMPARE(obj.slotResult, QString("sl0"));
990
991 // signals
992 obj.slotResult.clear();
993 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::QueuedConnection));
994 QVERIFY(obj.slotResult.isEmpty());
995 qApp->processEvents(QEventLoop::AllEvents);
996 QCOMPARE(obj.slotResult, QString("sl0"));
997
998 // Test function pointers
999 QtTestObject::staticResult.clear();
1000 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::QueuedConnection));
1001 QVERIFY(QtTestObject::staticResult.isEmpty());
1002 qApp->processEvents(QEventLoop::AllEvents);
1003 QCOMPARE(QtTestObject::staticResult, QString("staticFunction0"));
1004
1005 // Test lambda
1006 QCOMPARE(countedStructObjectsCount, 0);
1007 {
1008 CountedStruct str;
1009 obj.slotResult.clear();
1010 QVERIFY(
1011 QMetaObject::invokeMethod(&obj, [str, &obj]() { obj.sl0(); }, Qt::QueuedConnection));
1012 QVERIFY(obj.slotResult.isEmpty());
1013 qApp->processEvents(QEventLoop::AllEvents);
1014 QCOMPARE(obj.slotResult, QString("sl0"));
1015 }
1016 QCOMPARE(countedStructObjectsCount, 0);
1017 {
1018 CountedStruct str;
1019 qint32 var = 0;
1020 QTest::ignoreMessage(QtWarningMsg,
1021 "QMetaObject::invokeMethod: Unable to invoke methods with return "
1022 "values in queued connections");
1023 QVERIFY(!QMetaObject::invokeMethod(&obj, [str]() -> qint32 { return 1; },
1024 Qt::QueuedConnection, &var));
1025 QCOMPARE(var, 0);
1026 }
1027 QCOMPARE(countedStructObjectsCount, 0);
1028#endif
1029}
1030
1031
1032void tst_QMetaObject::invokeBlockingQueuedMetaMember()
1033{
1034 QThread t;
1035 t.start();
1036 QtTestObject obj;
1037 obj.moveToThread(&t);
1038
1039 QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5");
1040 QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X");
1041
1042 QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, t1)));
1043 QCOMPARE(obj.slotResult, QString("sl1:1"));
1044
1045 QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Qt::BlockingQueuedConnection, Q_ARG(const QString, t1), Q_ARG(QString, t2)));
1046 QCOMPARE(obj.slotResult, QString("sl2:12"));
1047
1048 QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3)));
1049 QCOMPARE(obj.slotResult, QString("sl3:123"));
1050
1051 QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2),
1052 Q_ARG(QString, t3), Q_ARG(QString, t4)));
1053 QCOMPARE(obj.slotResult, QString("sl4:1234"));
1054
1055 QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2),
1056 Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, "5")));
1057 QCOMPARE(obj.slotResult, QString("sl5:12345"));
1058
1059 QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2),
1060 Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6)));
1061 QCOMPARE(obj.slotResult, QString("sl6:123456"));
1062
1063 QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2),
1064 Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6),
1065 Q_ARG(QString, t7)));
1066 QCOMPARE(obj.slotResult, QString("sl7:1234567"));
1067
1068 QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2),
1069 Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6),
1070 Q_ARG(QString, t7), Q_ARG(QString, t8)));
1071 QCOMPARE(obj.slotResult, QString("sl8:12345678"));
1072
1073 QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2),
1074 Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6),
1075 Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9)));
1076 QCOMPARE(obj.slotResult, QString("sl9:123456789"));
1077
1078 QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection));
1079 QCOMPARE(obj.slotResult, QString("sl11"));
1080
1081 QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection));
1082 QCOMPARE(obj.slotResult, QString("0x0"));
1083
1084 QString refStr("whatever");
1085 QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, QGenericArgument("QString&", &refStr)));
1086 QCOMPARE(obj.slotResult, QString("testReference:whatever"));
1087 QCOMPARE(refStr, QString("gotcha"));
1088
1089 qint64 ll1 = -1;
1090 quint64 ll2 = 0;
1091 QVERIFY(QMetaObject::invokeMethod(&obj,
1092 "testLongLong",
1093 Qt::BlockingQueuedConnection,
1094 Q_ARG(qint64, ll1),
1095 Q_ARG(quint64, ll2)));
1096 QCOMPARE(obj.slotResult, QString("testLongLong:-1,0"));
1097
1098 QString exp;
1099 QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "bubu")));
1100 QCOMPARE(exp, QString("yessir"));
1101 QCOMPARE(obj.slotResult, QString("sl1:bubu"));
1102
1103 QObject *ptr = 0;
1104 QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject*,ptr)));
1105 QCOMPARE(ptr, (QObject *)&obj);
1106 QCOMPARE(obj.slotResult, QString("sl11"));
1107 // try again with a space:
1108 ptr = 0;
1109 QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject * , ptr)));
1110 QCOMPARE(ptr, (QObject *)&obj);
1111 QCOMPARE(obj.slotResult, QString("sl11"));
1112
1113 const char *ptr2 = 0;
1114 QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(const char*, ptr2)));
1115 QVERIFY(ptr2 != 0);
1116 QCOMPARE(obj.slotResult, QString("sl12"));
1117 // try again with a space:
1118 ptr2 = 0;
1119 QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(char const * , ptr2)));
1120 QVERIFY(ptr2 != 0);
1121 QCOMPARE(obj.slotResult, QString("sl12"));
1122
1123 // test w/ template args
1124 QList<QString> returnValue, argument;
1125 argument << QString("one") << QString("two") << QString("three");
1126 QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", Qt::BlockingQueuedConnection,
1127 Q_RETURN_ARG(QList<QString>, returnValue),
1128 Q_ARG(QList<QString>, argument)));
1129 QCOMPARE(returnValue, argument);
1130 QCOMPARE(obj.slotResult, QString("sl13"));
1131
1132 //test signals
1133 QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection));
1134 QCOMPARE(obj.slotResult, QString("sl0"));
1135
1136 QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_ARG(QString, "baba")));
1137 QCOMPARE(obj.slotResult, QString("sl1:baba"));
1138
1139 exp.clear();
1140 QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "hehe")));
1141 QCOMPARE(exp, QString("yessir"));
1142 QCOMPARE(obj.slotResult, QString("sl1:hehe"));
1143
1144 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()");
1145 QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection));
1146 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)");
1147 QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg")));
1148 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n"
1149 "Candidates are:\n sl3(QString,QString,QString)");
1150 QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg")));
1151 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n"
1152 "Candidates are:\n sl1(QString)");
1153 QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg")));
1154
1155 //should not have changed since last test.
1156 QCOMPARE(exp, QString("yessir"));
1157 QCOMPARE(obj.slotResult, QString("sl1:hehe"));
1158
1159 QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, Q_ARG(QThread*, QThread::currentThread())));
1160 t.quit();
1161 QVERIFY(t.wait());
1162
1163}
1164
1165void tst_QMetaObject::invokeBlockingQueuedPointer()
1166{
1167#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 1)
1168 QtTestObject *const nullTestObject = nullptr;
1169
1170 QThread t;
1171 t.start();
1172 QtTestObject obj;
1173 obj.moveToThread(&t);
1174
1175 QString t1("1");
1176
1177 // Test member functions
1178 QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0, Qt::BlockingQueuedConnection));
1179 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::BlockingQueuedConnection));
1180 QCOMPARE(obj.slotResult, QString("sl0"));
1181
1182 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender, Qt::BlockingQueuedConnection));
1183 QCOMPARE(obj.slotResult, QString("0x0"));
1184
1185 // return qint64
1186 qint64 return64 = 0;
1187 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, Qt::BlockingQueuedConnection,
1188 &return64));
1189 QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
1190 QCOMPARE(obj.slotResult, QString("sl14"));
1191
1192 //test signals
1193 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::BlockingQueuedConnection));
1194 QCOMPARE(obj.slotResult, QString("sl0"));
1195
1196 // Test function pointers
1197 QVERIFY(!QMetaObject::invokeMethod(0, &testFunction, Qt::BlockingQueuedConnection));
1198 QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction, Qt::BlockingQueuedConnection));
1199
1200 QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection));
1201 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection));
1202 QCOMPARE(QtTestObject::staticResult, QString("staticFunction0"));
1203
1204 return64 = 0;
1205 QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, Qt::BlockingQueuedConnection, &return64));
1206 QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
1207 QCOMPARE(QtTestObject::staticResult, QString("staticFunction1"));
1208
1209 // Test lambdas
1210 QCOMPARE(countedStructObjectsCount, 0);
1211 {
1212 CountedStruct str;
1213 QVERIFY(QMetaObject::invokeMethod(&obj, [str, &obj, &t1]() { obj.sl1(t1); },
1214 Qt::BlockingQueuedConnection));
1215 QCOMPARE(obj.slotResult, QString("sl1:1"));
1216 }
1217 {
1218 CountedStruct str;
1219 QString exp;
1220 QVERIFY(QMetaObject::invokeMethod(&obj,
1221 [&obj, str]() -> QString { return obj.sl1("bubu"); },
1222 Qt::BlockingQueuedConnection, &exp));
1223 QCOMPARE(exp, QString("yessir"));
1224 QCOMPARE(obj.slotResult, QString("sl1:bubu"));
1225 }
1226#if defined(__cpp_init_captures) && QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
1227 {
1228 std::unique_ptr<int> ptr(new int);
1229 QVERIFY(QMetaObject::invokeMethod(&obj,
1230 [&obj, p = std::move(ptr)]() { return obj.sl1("hehe"); },
1231 Qt::BlockingQueuedConnection));
1232 QCOMPARE(obj.slotResult, QString("sl1:hehe"));
1233 }
1234#endif
1235 QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection));
1236 t.quit();
1237 QVERIFY(t.wait());
1238 QCOMPARE(countedStructObjectsCount, 0);
1239#endif
1240}
1241
1242
1243void tst_QMetaObject::qtMetaObjectInheritance()
1244{
1245 QVERIFY(!QObject::staticMetaObject.superClass());
1246 QCOMPARE(QSortFilterProxyModel::staticMetaObject.indexOfEnumerator("Qt::CaseSensitivity"), -1);
1247 QCOMPARE(QSortFilterProxyModel::staticMetaObject.indexOfEnumerator("CaseSensitivity"), -1);
1248 int indexOfSortCaseSensitivity = QSortFilterProxyModel::staticMetaObject.indexOfProperty("sortCaseSensitivity");
1249 QVERIFY(indexOfSortCaseSensitivity != -1);
1250 QMetaProperty sortCaseSensitivity = QSortFilterProxyModel::staticMetaObject.property(indexOfSortCaseSensitivity);
1251 QVERIFY(sortCaseSensitivity.isValid());
1252 QCOMPARE(sortCaseSensitivity.enumerator().name(), "CaseSensitivity");
1253}
1254
1255struct MyType
1256{
1257 int i1, i2, i3;
1258};
1259W_REGISTER_ARGTYPE(MyType)
1260
1261typedef QString CustomString;
1262
1263
1264class QtTestCustomObject: public QObject
1265{
1266 W_OBJECT(QtTestCustomObject)
1267 friend class tst_QMetaObject;
1268public:
1269 QtTestCustomObject(): QObject(), sum(0) {}
1270
1271public slots:
1272 void sl1(MyType myType);
1273 W_SLOT(sl1)
1274
1275signals:
1276 void sig_custom(const CustomString &string)
1277 W_SIGNAL(sig_custom,string)
1278
1279public:
1280 int sum;
1281};
1282
1283W_OBJECT_IMPL(QtTestCustomObject)
1284
1285void QtTestCustomObject::sl1(MyType myType)
1286{
1287 sum = myType.i1 + myType.i2 + myType.i3;
1288}
1289
1290void tst_QMetaObject::invokeCustomTypes()
1291{
1292 QtTestCustomObject obj;
1293 MyType tp = {1, 1, 1};
1294
1295 QCOMPARE(obj.sum, 0);
1296 QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(MyType, tp)));
1297 QCOMPARE(obj.sum, 3);
1298}
1299
1300namespace NamespaceWithConstructibleClass
1301{
1302
1303class ConstructibleClass : public QObject
1304{
1305 W_OBJECT(ConstructibleClass)
1306public:
1307 ConstructibleClass(QObject *parent = 0)
1308 : QObject(parent) {}
1309 W_CONSTRUCTOR(QObject*)
1310};
1311
1312}
1313
1314W_OBJECT_IMPL(NamespaceWithConstructibleClass::ConstructibleClass)
1315
1316void tst_QMetaObject::invokeMetaConstructor()
1317{
1318 const QMetaObject *mo = &QtTestObject::staticMetaObject;
1319 {
1320 QObject *obj = mo->newInstance();
1321 QVERIFY(!obj);
1322 }
1323 {
1324 QtTestObject obj;
1325 QObject *obj2 = mo->newInstance(Q_ARG(QObject*, &obj));
1326 QVERIFY(obj2 != 0);
1327 QCOMPARE(obj2->parent(), (QObject*)&obj);
1328 QVERIFY(qobject_cast<QtTestObject*>(obj2) != 0);
1329 }
1330 // class in namespace
1331 const QMetaObject *nsmo = &NamespaceWithConstructibleClass::ConstructibleClass::staticMetaObject;
1332 {
1333 QtTestObject obj;
1334 QObject *obj2 = nsmo->newInstance(Q_ARG(QObject*, &obj));
1335 QVERIFY(obj2 != 0);
1336 QCOMPARE(obj2->parent(), (QObject*)&obj);
1337 QVERIFY(qobject_cast<NamespaceWithConstructibleClass::ConstructibleClass*>(obj2) != 0);
1338 }
1339 // gadget shouldn't return a valid pointer
1340#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
1341 {
1342 QCOMPARE(MyGadget::staticMetaObject.constructorCount(), 1);
1343 QTest::ignoreMessage(QtWarningMsg, "QMetaObject::newInstance: type MyGadget does not inherit QObject");
1344 QVERIFY(!MyGadget::staticMetaObject.newInstance());
1345 }
1346#endif
1347}
1348
1349void tst_QMetaObject::invokeTypedefTypes()
1350{
1351 qRegisterMetaType<CustomString>("CustomString");
1352 QtTestCustomObject obj;
1353 QSignalSpy spy(&obj, &QtTestCustomObject::sig_custom);
1354 QVERIFY(spy.isValid());
1355
1356 QCOMPARE(spy.count(), 0);
1357 CustomString arg("hello");
1358 QVERIFY(QMetaObject::invokeMethod(&obj, "sig_custom", Q_ARG(CustomString, arg)));
1359 QCOMPARE(spy.count(), 1);
1360 QCOMPARE(spy.at(0).count(), 1);
1361 QCOMPARE(spy.at(0).at(0), QVariant(arg));
1362}
1363
1364void tst_QMetaObject::invokeException()
1365{
1366#ifndef QT_NO_EXCEPTIONS
1367 QtTestObject obj;
1368 QCOMPARE(countedStructObjectsCount, 0);
1369 try {
1370 CountedStruct s;
1371 QVERIFY(QMetaObject::invokeMethod(&obj, "throwingSlot", Q_RETURN_ARG(CountedStruct, s),
1372 Q_ARG(CountedStruct, s), Q_ARG(CountedStruct, s)));
1373 QFAIL("Did not throw");
1374 } catch(ObjectException &) {}
1375 QCOMPARE(countedStructObjectsCount, 0);
1376#else
1377 QSKIP("Needs exceptions");
1378#endif
1379}
1380
1381void tst_QMetaObject::invokeQueuedAutoRegister()
1382{
1383#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
1384 QSKIP("Bug fixed in Qt 5.9");
1385#endif
1386
1387 QtTestObject obj;
1388
1389 auto shared = QSharedPointer<QtTestObject>::create(QStringLiteral("myShared-"));
1390
1391 QVERIFY(QMetaObject::invokeMethod(
1392 &obj, "slotWithRegistrableArgument", Qt::QueuedConnection,
1393 Q_ARG(QtTestObject *, shared.data()), Q_ARG(QPointer<QtTestObject>, shared.data()),
1394 Q_ARG(QSharedPointer<QtTestObject>, shared), Q_ARG(QWeakPointer<QtTestObject>, shared),
1395 Q_ARG(QVector<QtTestObject *>, QVector<QtTestObject *>()),
1396 Q_ARG(QList<QtTestObject *>, QList<QtTestObject *>())));
1397 QVERIFY(obj.slotResult.isEmpty());
1398 qApp->processEvents(QEventLoop::AllEvents);
1399 QCOMPARE(obj.slotResult,
1400 QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00"));
1401}
1402
1403void tst_QMetaObject::normalizedSignature_data()
1404{
1405 QTest::addColumn<QString>("signature");
1406 QTest::addColumn<QString>("result");
1407
1408 QTest::newRow("function") << "void foo()" << "void foo()";
1409 QTest::newRow("spaces") << " void foo( ) " << "void foo()";
1410 QTest::newRow("void") << "void foo(void)" << "void foo()";
1411 QTest::newRow("void spaces") << "void foo( void )" << "void foo()";
1412 QTest::newRow("void*") << "void foo(void*)" << "void foo(void*)";
1413 QTest::newRow("void* spaces") << "void foo( void * )" << "void foo(void*)";
1414 QTest::newRow("function ptr") << "void foo(void(*)(void))" << "void foo(void(*)())";
1415 QTest::newRow("function ptr spaces") << "void foo( void ( * ) ( void ))" << "void foo(void(*)())";
1416 QTest::newRow("function ptr void*") << "void foo(void(*)(void*))" << "void foo(void(*)(void*))";
1417 QTest::newRow("function ptr void* spaces") << "void foo( void ( * ) ( void * ))" << "void foo(void(*)(void*))";
1418 QTest::newRow("template args") << " void foo( QMap<a, a>, QList<b>) "
1419 << "void foo(QMap<a,a>,QList<b>)";
1420 QTest::newRow("void template args") << " void foo( Foo<void>, Bar<void> ) "
1421 << "void foo(Foo<void>,Bar<void>)";
1422 QTest::newRow("void* template args") << " void foo( Foo<void*>, Bar<void *> ) "
1423 << "void foo(Foo<void*>,Bar<void*>)";
1424 QTest::newRow("rettype") << "QList<int, int> foo()" << "QList<int,int>foo()";
1425 QTest::newRow("rettype void template") << "Foo<void> foo()" << "Foo<void>foo()";
1426 QTest::newRow("const rettype") << "const QString *foo()" << "const QString*foo()";
1427 QTest::newRow("const ref") << "const QString &foo()" << "const QString&foo()";
1428 QTest::newRow("reference") << "QString &foo()" << "QString&foo()";
1429 QTest::newRow("const1") << "void foo(QString const *)" << "void foo(const QString*)";
1430 QTest::newRow("const2") << "void foo(QString * const)" << "void foo(QString*const)";
1431 QTest::newRow("const3") << "void foo(QString const &)" << "void foo(QString)";
1432 QTest::newRow("const4") << "void foo(const int)" << "void foo(int)";
1433 QTest::newRow("const5") << "void foo(const int, int const, const int &, int const &)"
1434 << "void foo(int,int,int,int)";
1435 QTest::newRow("const6") << "void foo(QList<const int>)" << "void foo(QList<const int>)";
1436 QTest::newRow("const7") << "void foo(QList<const int*>)" << "void foo(QList<const int*>)";
1437 QTest::newRow("const8") << "void foo(QList<int const*>)" << "void foo(QList<const int*>)";
1438 QTest::newRow("const9") << "void foo(const Foo<Bar>)" << "void foo(Foo<Bar>)";
1439 QTest::newRow("const10") << "void foo(Foo<Bar>const)" << "void foo(Foo<Bar>)";
1440 QTest::newRow("const11") << "void foo(Foo<Bar> *const)" << "void foo(Foo<Bar>*const)";
1441 QTest::newRow("const12") << "void foo(Foo<Bar>const*const *const)" << "void foo(Foo<Bar>*const*const)";
1442 QTest::newRow("const13") << "void foo(const Foo<Bar>&)" << "void foo(Foo<Bar>)";
1443 QTest::newRow("const14") << "void foo(Foo<Bar>const&)" << "void foo(Foo<Bar>)";
1444
1445 QTest::newRow("invalid1") << "a( b" << "a(b";
1446}
1447
1448void tst_QMetaObject::normalizedSignature()
1449{
1450 QFETCH(QString, signature);
1451 QFETCH(QString, result);
1452
1453 QCOMPARE(QMetaObject::normalizedSignature(signature.toLatin1()), result.toLatin1());
1454}
1455
1456void tst_QMetaObject::normalizedType_data()
1457{
1458 QTest::addColumn<QString>("type");
1459 QTest::addColumn<QString>("result");
1460
1461 QTest::newRow("simple") << "int" << "int";
1462 QTest::newRow("white") << " int " << "int";
1463 QTest::newRow("const1") << "int const *" << "const int*";
1464 QTest::newRow("const2") << "const int *" << "const int*";
1465 QTest::newRow("template1") << "QList<int const *>" << "QList<const int*>";
1466 QTest::newRow("template2") << "QList<const int *>" << "QList<const int*>";
1467 QTest::newRow("template3") << "QMap<QString, int>" << "QMap<QString,int>";
1468 QTest::newRow("template4") << "const QMap<QString, int> &" << "QMap<QString,int>";
1469 QTest::newRow("template5") << "QList< ::Foo::Bar>" << "QList< ::Foo::Bar>";
1470 QTest::newRow("template6") << "QList<::Foo::Bar>" << "QList<::Foo::Bar>";
1471 QTest::newRow("template7") << "QList<QList<int> >" << "QList<QList<int> >";
1472 QTest::newRow("template8") << "QMap<const int, const short*>" << "QMap<const int,const short*>";
1473 QTest::newRow("template9") << "QPair<const QPair<int, int const *> , QPair<QHash<int, const char*> > >" << "QPair<const QPair<int,const int*>,QPair<QHash<int,const char*> > >";
1474 QTest::newRow("value1") << "const QString &" << "QString";
1475 QTest::newRow("value2") << "QString const &" << "QString";
1476 QTest::newRow("constInName1") << "constconst" << "constconst";
1477 QTest::newRow("constInName2") << "constconst*" << "constconst*";
1478 QTest::newRow("constInName3") << "const constconst&" << "constconst";
1479 QTest::newRow("constInName4") << "constconst const*const" << "constconst*const";
1480 QTest::newRow("class") << "const class foo&" << "foo";
1481 QTest::newRow("struct") << "const struct foo*" << "const foo*";
1482 QTest::newRow("struct2") << "struct foo const*" << "const foo*";
1483 QTest::newRow("enum") << "enum foo" << "foo";
1484 QTest::newRow("void") << "void" << "void";
1485}
1486
1487void tst_QMetaObject::normalizedType()
1488{
1489 QFETCH(QString, type);
1490 QFETCH(QString, result);
1491
1492 QCOMPARE(QMetaObject::normalizedType(type.toLatin1()), result.toLatin1());
1493}
1494
1495void tst_QMetaObject::customPropertyType()
1496{
1497 QMetaProperty prop = metaObject()->property(metaObject()->indexOfProperty("value3"));
1498
1499 QCOMPARE(prop.type(), QVariant::UserType);
1500 QCOMPARE(prop.userType(), 0);
1501
1502 qRegisterMetaType<MyStruct>("MyStruct");
1503 QCOMPARE(prop.userType(), QMetaType::type("MyStruct"));
1504
1505 prop = metaObject()->property(metaObject()->indexOfProperty("value4"));
1506 QCOMPARE(prop.type(), QVariant::List);
1507
1508 prop = metaObject()->property(metaObject()->indexOfProperty("value5"));
1509 QCOMPARE(prop.type(), QVariant::List);
1510}
1511
1512void tst_QMetaObject::checkScope_data()
1513{
1514 QTest::addColumn<QObject *>("object");
1515 QTest::addColumn<QByteArray>("name");
1516
1517 static MyNamespace::MyClass obj1;
1518 static MyNamespace::MyClass2 obj2;
1519
1520 QTest::newRow("MyClass") << static_cast<QObject*>(&obj1) << QByteArray("MyClass");
1521 QTest::newRow("MyClass2") << static_cast<QObject*>(&obj2) << QByteArray("MyClass2");
1522
1523}
1524
1525
1526void tst_QMetaObject::checkScope()
1527{
1528 QFETCH(QObject *, object);
1529 QFETCH(QByteArray, name);
1530 QObject &obj = *object;
1531 bool ok;
1532
1533 const QMetaObject *mo = obj.metaObject();
1534 QMetaEnum me = mo->enumerator(mo->indexOfEnumerator("MyEnum"));
1535 QVERIFY(me.isValid());
1536 QVERIFY(!me.isFlag());
1537 QCOMPARE(QByteArray(me.scope()), QByteArray("MyNamespace::" + name));
1538 QCOMPARE(me.keyToValue("MyNamespace::" + name + "::MyEnum2", &ok), 1);
1539 QCOMPARE(ok, true);
1540 QCOMPARE(me.keyToValue(name + "::MyEnum2", &ok), -1);
1541 QCOMPARE(ok, false);
1542 QCOMPARE(me.keyToValue("MyNamespace::MyEnum2", &ok), -1);
1543 QCOMPARE(ok, false);
1544 QCOMPARE(me.keyToValue("MyEnum2", &ok), 1);
1545 QCOMPARE(ok, true);
1546 QCOMPARE(me.keyToValue("MyEnum", &ok), -1);
1547 QCOMPARE(ok, false);
1548 QCOMPARE(QLatin1String(me.valueToKey(1)), QLatin1String("MyEnum2"));
1549
1550 QMetaEnum me2 = mo->enumerator(mo->indexOfEnumerator("MyAnotherEnum"));
1551 QVERIFY(me2.isValid());
1552 QVERIFY(!me2.isFlag());
1553 QCOMPARE(me2.keyToValue("MyAnotherEnum1", &ok), 1);
1554 QCOMPARE(ok, true);
1555 QCOMPARE(me2.keyToValue("MyAnotherEnum2", &ok), 2);
1556 QCOMPARE(ok, true);
1557 QCOMPARE(me2.keyToValue("MyAnotherEnum3", &ok), -1);
1558 QCOMPARE(ok, true);
1559 QCOMPARE(me2.keyToValue("MyAnotherEnum", &ok), -1);
1560 QCOMPARE(ok, false);
1561
1562 QMetaEnum mf = mo->enumerator(mo->indexOfEnumerator("MyFlags"));
1563 QVERIFY(mf.isValid());
1564 QVERIFY(mf.isFlag());
1565 QCOMPARE(QByteArray(mf.scope()), QByteArray("MyNamespace::" + name));
1566 QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2", &ok), 2);
1567 QCOMPARE(ok, true);
1568 QCOMPARE(mf.keysToValue(name + "::MyFlag2", &ok), -1);
1569 QCOMPARE(ok, false);
1570 QCOMPARE(mf.keysToValue("MyNamespace::MyFlag2", &ok), -1);
1571 QCOMPARE(ok, false);
1572 QCOMPARE(mf.keysToValue("MyFlag2", &ok), 2);
1573 QCOMPARE(ok, true);
1574 QCOMPARE(mf.keysToValue("MyFlag", &ok), -1);
1575 QCOMPARE(ok, false);
1576 QCOMPARE(QLatin1String(mf.valueToKey(2)), QLatin1String("MyFlag2"));
1577 QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3);
1578 QCOMPARE(ok, true);
1579 QCOMPARE(mf.keysToValue(name + "::MyFlag1|" + name + "::MyFlag2", &ok), -1);
1580 QCOMPARE(ok, false);
1581 QCOMPARE(mf.keysToValue("MyNamespace::MyFlag1|MyNamespace::MyFlag2", &ok), -1);
1582 QCOMPARE(ok, false);
1583 QCOMPARE(mf.keysToValue("MyFlag1|MyFlag2", &ok), 3);
1584 QCOMPARE(ok, true);
1585 QCOMPARE(mf.keysToValue("MyFlag2|MyFlag2", &ok), 2);
1586 QCOMPARE(ok, true);
1587 QCOMPARE(mf.keysToValue("MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3);
1588 QCOMPARE(ok, true);
1589 QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2|MyNamespace::" + name + "::MyFlag2", &ok), 2);
1590 QCOMPARE(ok, true);
1591 QCOMPARE(QLatin1String(mf.valueToKeys(3)), QLatin1String("MyFlag1|MyFlag2"));
1592}
1593
1594void tst_QMetaObject::propertyNotify()
1595{
1596 const QMetaObject *mo = metaObject();
1597
1598 QMetaProperty prop = mo->property(mo->indexOfProperty("value6"));
1599 QVERIFY(prop.isValid());
1600 QVERIFY(prop.hasNotifySignal());
1601 QMetaMethod signal = prop.notifySignal();
1602 QCOMPARE(signal.methodSignature(), QByteArray("value6Changed()"));
1603
1604 prop = mo->property(mo->indexOfProperty("value7"));
1605 QVERIFY(prop.isValid());
1606 QVERIFY(prop.hasNotifySignal());
1607 signal = prop.notifySignal();
1608 QCOMPARE(signal.methodSignature(), QByteArray("value7Changed(QString)"));
1609
1610 prop = mo->property(mo->indexOfProperty("value8"));
1611 QVERIFY(prop.isValid());
1612 QVERIFY(!prop.hasNotifySignal());
1613 signal = prop.notifySignal();
1614 QCOMPARE(signal.methodSignature(), QByteArray());
1615
1616 prop = mo->property(mo->indexOfProperty("value"));
1617 QVERIFY(prop.isValid());
1618 QVERIFY(!prop.hasNotifySignal());
1619 signal = prop.notifySignal();
1620 QCOMPARE(signal.methodSignature(), QByteArray());
1621}
1622
1623void tst_QMetaObject::propertyConstant()
1624{
1625 const QMetaObject *mo = metaObject();
1626
1627 QMetaProperty prop = mo->property(mo->indexOfProperty("value8"));
1628 QVERIFY(prop.isValid());
1629 QVERIFY(!prop.isConstant());
1630
1631 prop = mo->property(mo->indexOfProperty("value9"));
1632 QVERIFY(prop.isValid());
1633 QVERIFY(prop.isConstant());
1634}
1635
1636void tst_QMetaObject::propertyFinal()
1637{
1638 const QMetaObject *mo = metaObject();
1639
1640 QMetaProperty prop = mo->property(mo->indexOfProperty("value10"));
1641 QVERIFY(prop.isValid());
1642 QVERIFY(prop.isFinal());
1643
1644 prop = mo->property(mo->indexOfProperty("value9"));
1645 QVERIFY(prop.isValid());
1646 QVERIFY(!prop.isFinal());
1647}
1648
1649class ClassInfoTestObjectA : public QObject
1650{
1651 W_OBJECT(ClassInfoTestObjectA)
1652 W_CLASSINFO("Author", "Christopher Pike")
1653};
1654
1655W_OBJECT_IMPL(ClassInfoTestObjectA)
1656
1657class ClassInfoTestObjectB : public ClassInfoTestObjectA
1658{
1659 W_OBJECT(ClassInfoTestObjectB)
1660};
1661
1662W_OBJECT_IMPL(ClassInfoTestObjectB)
1663
1664void tst_QMetaObject::classInfo()
1665{
1666 ClassInfoTestObjectB b;
1667 int index = b.metaObject()->indexOfClassInfo("Author");
1668 QCOMPARE(index, 0);
1669 QVERIFY(index <= b.metaObject()->classInfoOffset());
1670 QCOMPARE(QLatin1String(b.metaObject()->classInfo(index).value()), QLatin1String("Christopher Pike"));
1671}
1672
1673void tst_QMetaObject::metaMethod()
1674{
1675 QString str("foo");
1676 QString ret("bar");
1677 QMetaMethod method;
1678 QVERIFY(!method.invoke(this));
1679 QVERIFY(!method.invoke(this, Q_ARG(QString, str)));
1680 QVERIFY(!method.invoke(this, Q_RETURN_ARG(QString, ret), Q_ARG(QString, str)));
1681 QCOMPARE(str, QString("foo"));
1682 QCOMPARE(ret, QString("bar"));
1683
1684 QtTestObject obj;
1685 QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5");
1686 QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X");
1687
1688 int index = QtTestObject::staticMetaObject.indexOfMethod("sl5(QString,QString,QString,QString,QString)");
1689 QVERIFY(index > 0);
1690 method = QtTestObject::staticMetaObject.method(index);
1691 //wrong args
1692 QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4")));
1693 //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"), Q_ARG(QString, "6")));
1694 //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(int, 5)));
1695 QVERIFY(!method.invoke(&obj, Q_RETURN_ARG(QString, ret), Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5")));
1696
1697 //wrong object
1698 //QVERIFY(!method.invoke(this, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5")));
1699 QVERIFY(!method.invoke(0, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5")));
1700 QCOMPARE(ret, QString("bar"));
1701 QCOMPARE(obj.slotResult, QString());
1702
1703 QVERIFY(method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5")));
1704 QCOMPARE(obj.slotResult, QString("sl5:12345"));
1705
1706 index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList<QString>)");
1707 QVERIFY(index > 0);
1708 QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index);
1709 QList<QString> returnValue, argument;
1710 argument << QString("one") << QString("two") << QString("three");
1711 //wrong object
1712 //QVERIFY(!sl13.invoke(this, Q_RETURN_ARG(QList<QString>, returnValue), Q_ARG(QList<QString>, argument)));
1713 QVERIFY(!sl13.invoke(0, Q_RETURN_ARG(QList<QString>, returnValue), Q_ARG(QList<QString>, argument)));
1714 QCOMPARE(returnValue, QList<QString>());
1715
1716 QVERIFY(sl13.invoke(&obj, Q_RETURN_ARG(QList<QString>, returnValue), Q_ARG(QList<QString>, argument)));
1717 QCOMPARE(returnValue, argument);
1718 QCOMPARE(obj.slotResult, QString("sl13"));
1719}
1720
1721void tst_QMetaObject::indexOfMethod_data()
1722{
1723 QTest::addColumn<QObject *>("object");
1724 QTest::addColumn<QByteArray>("name");
1725 QTest::addColumn<bool>("isSignal");
1726 QTest::newRow("indexOfMethod_data") << (QObject*)this << QByteArray("indexOfMethod_data()") << false;
1727 QTest::newRow("deleteLater") << (QObject*)this << QByteArray("deleteLater()") << false;
1728 QTest::newRow("value6changed") << (QObject*)this << QByteArray("value6Changed()") << true;
1729 QTest::newRow("value7changed") << (QObject*)this << QByteArray("value7Changed(QString)") << true;
1730 QTest::newRow("destroyed") << (QObject*)this << QByteArray("destroyed()") << true;
1731 QTest::newRow("destroyed2") << (QObject*)this << QByteArray("destroyed(QObject*)") << true;
1732}
1733
1734void tst_QMetaObject::indexOfMethod()
1735{
1736 QFETCH(QObject *, object);
1737 QFETCH(QByteArray, name);
1738 QFETCH(bool, isSignal);
1739 int idx = object->metaObject()->indexOfMethod(name);
1740 QVERIFY(idx >= 0);
1741 QCOMPARE(object->metaObject()->method(idx).methodSignature(), name);
1742 QCOMPARE(object->metaObject()->indexOfSlot(name), isSignal ? -1 : idx);
1743 QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx);
1744}
1745
1746void tst_QMetaObject::indexOfMethodPMF()
1747{
1748#define INDEXOFMETHODPMF_HELPER(ObjectType, Name, Arguments) { \
1749 int idx = -1; \
1750 void (ObjectType::*signal)Arguments = &ObjectType::Name; \
1751 void *signal_p = &signal; \
1752 void *args[] = { &idx, signal_p, 0}; \
1753 ObjectType::qt_static_metacall(0, QMetaObject::IndexOfMethod, 0, args); \
1754 QCOMPARE(ObjectType::staticMetaObject.indexOfMethod(QMetaObject::normalizedSignature(#Name #Arguments)), \
1755 ObjectType::staticMetaObject.methodOffset() + idx); \
1756 }
1757
1758 INDEXOFMETHODPMF_HELPER(tst_QMetaObject, value7Changed, (const QString&))
1759 INDEXOFMETHODPMF_HELPER(QtTestObject, sig0, ())
1760 INDEXOFMETHODPMF_HELPER(QtTestObject, sig10, (QString,QString,QString,QString,QString,QString,QString,QString,QString,QString))
1761 INDEXOFMETHODPMF_HELPER(QtTestCustomObject, sig_custom, (const CustomString &))
1762}
1763
1764#ifdef QT_BUILD_INTERNAL
1765namespace SignalTestHelper
1766{
1767// These functions use the public QMetaObject/QMetaMethod API to implement
1768// the functionality of the internal API, and are used to check the results.
1769
1770static int signalCount(const QMetaObject *mo)
1771{
1772 int n = 0;
1773 for (int i = 0; i < mo->methodCount(); ++i) {
1774 QMetaMethod mm = mo->method(i);
1775 if (mm.methodType() == QMetaMethod::Signal)
1776 ++n;
1777 }
1778 return n;
1779}
1780
1781static int signalOffset(const QMetaObject *mo)
1782{
1783 return mo->superClass() ? signalCount(mo->superClass()) : 0;
1784}
1785
1786static QMetaMethod signal(const QMetaObject *mo, int index)
1787{
1788 int k = 0;
1789 for (int i = 0; i < mo->methodCount(); ++i) {
1790 QMetaMethod mm = mo->method(i);
1791 if (mm.methodType() != QMetaMethod::Signal)
1792 continue;
1793 if (k == index)
1794 return mm;
1795 ++k;
1796 }
1797 return QMetaMethod();
1798}
1799
1800static int signalIndex(const QMetaMethod &mm)
1801{
1802 int k = mm.methodIndex();
1803 const QMetaObject *mo = mm.enclosingMetaObject();
1804 for (int i = 0; i < mm.methodIndex(); ++i) {
1805 if (mo->method(i).methodType() != QMetaMethod::Signal)
1806 --k;
1807 }
1808 return k;
1809}
1810
1811} // namespace SignalTestHelper
1812
1813void tst_QMetaObject::signalOffset_data()
1814{
1815 QTest::addColumn<const QMetaObject *>("metaObject");
1816
1817 QTest::newRow("QObject") << &QObject::staticMetaObject;
1818 QTest::newRow("tst_QMetaObject") << &tst_QMetaObject::staticMetaObject;
1819 QTest::newRow("QtTestObject") << &QtTestObject::staticMetaObject;
1820}
1821
1822void tst_QMetaObject::signalOffset()
1823{
1824 QFETCH(const QMetaObject *, metaObject);
1825 QCOMPARE(QMetaObjectPrivate::signalOffset(metaObject),
1826 SignalTestHelper::signalOffset(metaObject));
1827}
1828
1829void tst_QMetaObject::signalCount_data()
1830{
1831 signalOffset_data();
1832}
1833
1834void tst_QMetaObject::signalCount()
1835{
1836 QFETCH(const QMetaObject *, metaObject);
1837 QCOMPARE(QMetaObjectPrivate::absoluteSignalCount(metaObject),
1838 SignalTestHelper::signalCount(metaObject));
1839}
1840
1841void tst_QMetaObject::signal_data()
1842{
1843 QTest::addColumn<const QMetaObject *>("metaObject");
1844 QTest::addColumn<int>("index");
1845
1846 struct SignalTestDataHelper
1847 {
1848 static void addSignals(const QMetaObject *mo)
1849 {
1850 int count = SignalTestHelper::signalCount(mo);
1851 for (int i = 0; i < count; ++i) {
1852 QMetaMethod mm = SignalTestHelper::signal(mo, i);
1853 QByteArray tag(mo->className());
1854 tag.append("::");
1855 tag.append(mm.methodSignature());
1856 QTest::newRow(tag.constData()) << mo << i;
1857 }
1858 }
1859 };
1860
1861 SignalTestDataHelper::addSignals(&QObject::staticMetaObject);
1862 SignalTestDataHelper::addSignals(&tst_QMetaObject::staticMetaObject);
1863 SignalTestDataHelper::addSignals(&QtTestObject::staticMetaObject);
1864}
1865
1866void tst_QMetaObject::signal()
1867{
1868 QFETCH(const QMetaObject *, metaObject);
1869 QFETCH(int, index);
1870
1871 QCOMPARE(QMetaObjectPrivate::signal(metaObject, index),
1872 SignalTestHelper::signal(metaObject, index));
1873}
1874
1875void tst_QMetaObject::signalIndex_data()
1876{
1877 signal_data();
1878}
1879
1880void tst_QMetaObject::signalIndex()
1881{
1882 QFETCH(const QMetaObject *, metaObject);
1883 QFETCH(int, index);
1884
1885 QMetaMethod mm = SignalTestHelper::signal(metaObject, index);
1886 QCOMPARE(QMetaObjectPrivate::signalIndex(mm),
1887 SignalTestHelper::signalIndex(mm));
1888}
1889#endif
1890
1891void tst_QMetaObject::enumDebugStream_data()
1892{
1893 QTest::addColumn<int>("verbosity");
1894 QTest::addColumn<QString>("normalEnumMsg");
1895 QTest::addColumn<QString>("scopedEnumMsg");
1896 QTest::addColumn<QString>("globalEnumMsg");
1897 QTest::addColumn<QString>("normalFlagMsg");
1898 QTest::addColumn<QString>("normalFlagsMsg");
1899 QTest::addColumn<QString>("scopedFlagMsg");
1900 QTest::addColumn<QString>("scopedFlagsMsg");
1901 QTest::addColumn<QString>("flagAsEnumMsg");
1902
1903 QTest::newRow("verbosity=0") << 0
1904 << "hello MyEnum2 world"
1905 << "hello MyScopedEnum::Enum3 scoped world"
1906 << "WindowTitleHint Window Desktop WindowSystemMenuHint"
1907 << "hello MyFlag1 world"
1908 << "MyFlag1 MyFlag2|MyFlag3"
1909 << "MyScopedFlag(MyFlag2)"
1910 << "MyScopedFlag(MyFlag2|MyFlag3)"
1911 << "MyFlag1";
1912
1913 QTest::newRow("verbosity=1") << 1
1914 << "hello MyEnum::MyEnum2 world"
1915 << "hello MyScopedEnum::Enum3 scoped world"
1916 << "WindowType::WindowTitleHint WindowType::Window WindowType::Desktop WindowType::WindowSystemMenuHint"
1917 << "hello MyFlag(MyFlag1) world"
1918 << "MyFlag(MyFlag1) MyFlag(MyFlag2|MyFlag3)"
1919 << "MyScopedFlag(MyFlag2)"
1920 << "MyScopedFlag(MyFlag2|MyFlag3)"
1921 << "MyFlag::MyFlag1";
1922
1923 QTest::newRow("verbosity=2") << 2
1924 << "hello MyNamespace::MyClass::MyEnum2 world"
1925 << "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world"
1926 << "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint"
1927 << "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world"
1928 << "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)"
1929 << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)"
1930 << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)"
1931 << "MyNamespace::MyClass::MyFlag1";
1932
1933 QTest::newRow("verbosity=3") << 3
1934 << "hello MyNamespace::MyClass::MyEnum::MyEnum2 world"
1935 << "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world"
1936 << "Qt::WindowType::WindowTitleHint Qt::WindowType::Window Qt::WindowType::Desktop Qt::WindowType::WindowSystemMenuHint"
1937 << "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world"
1938 << "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)"
1939 << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)"
1940 << "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)"
1941 << "MyNamespace::MyClass::MyFlag::MyFlag1";
1942}
1943
1944void tst_QMetaObject::enumDebugStream()
1945{
1946#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
1947 QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum(MyEnum2) world ");
1948 MyNamespace::MyClass::MyEnum e = MyNamespace::MyClass::MyEnum2;
1949 qDebug() << "hello" << e << "world";
1950
1951 QTest::ignoreMessage(QtDebugMsg, "Qt::WindowType(WindowTitleHint) Qt::WindowType(Window) Qt::WindowType(Desktop) Qt::WindowType(WindowSystemMenuHint)");
1952 qDebug() << Qt::WindowTitleHint << Qt::Window <<Qt::Desktop << Qt::WindowSystemMenuHint;
1953
1954 QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) world");
1955 MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1;
1956 qDebug() << "hello" << f1 << "world";
1957
1958 MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3;
1959 QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlags>(MyFlag2|MyFlag3)");
1960 qDebug() << f1 << f2;
1961
1962#elif QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
1963 QFETCH(int, verbosity);
1964
1965 QFETCH(QString, normalEnumMsg);
1966 QFETCH(QString, scopedEnumMsg);
1967 QFETCH(QString, globalEnumMsg);
1968
1969 QFETCH(QString, normalFlagMsg);
1970 QFETCH(QString, normalFlagsMsg);
1971 QFETCH(QString, scopedFlagMsg);
1972 QFETCH(QString, scopedFlagsMsg);
1973 QFETCH(QString, flagAsEnumMsg);
1974
1975 // Enums
1976 QTest::ignoreMessage(QtDebugMsg, qPrintable(normalEnumMsg));
1977 qDebug().verbosity(verbosity) << "hello" << MyNamespace::MyClass::MyEnum2 << "world";
1978
1979 QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedEnumMsg));
1980 qDebug().verbosity(verbosity) << "hello" << MyNamespace::MyClass::MyScopedEnum::Enum3 << "scoped world";
1981
1982 QTest::ignoreMessage(QtDebugMsg, qPrintable(globalEnumMsg));
1983 qDebug().verbosity(verbosity) << Qt::WindowTitleHint << Qt::Window << Qt::Desktop << Qt::WindowSystemMenuHint;
1984
1985 // Flags
1986 QTest::ignoreMessage(QtDebugMsg, qPrintable(normalFlagMsg));
1987 MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1;
1988 qDebug().verbosity(verbosity) << "hello" << f1 << "world";
1989
1990 MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3;
1991 QTest::ignoreMessage(QtDebugMsg, qPrintable(normalFlagsMsg));
1992 qDebug().verbosity(verbosity) << f1 << f2;
1993
1994 QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedFlagMsg));
1995 MyNamespace::MyClass::MyScopedFlags f3 = MyNamespace::MyClass::MyScopedFlag::MyFlag2;
1996 qDebug().verbosity(verbosity) << f3;
1997
1998 QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedFlagsMsg));
1999 f3 |= MyNamespace::MyClass::MyScopedFlag::MyFlag3;
2000 qDebug().verbosity(verbosity) << f3;
2001
2002 // Single flag recognized as enum:
2003 QTest::ignoreMessage(QtDebugMsg, qPrintable(flagAsEnumMsg));
2004 MyNamespace::MyClass::MyFlag f4 = MyNamespace::MyClass::MyFlag1;
2005 qDebug().verbosity(verbosity) << f4;
2006#endif
2007}
2008
2009void tst_QMetaObject::inherits_data()
2010{
2011 QTest::addColumn<const QMetaObject *>("derivedMetaObject");
2012 QTest::addColumn<const QMetaObject *>("baseMetaObject");
2013 QTest::addColumn<bool>("inheritsResult");
2014
2015 QTest::newRow("MyClass inherits QObject")
2016 << &MyNamespace::MyClass::staticMetaObject << &QObject::staticMetaObject << true;
2017 QTest::newRow("QObject inherits MyClass")
2018 << &QObject::staticMetaObject << &MyNamespace::MyClass::staticMetaObject << false;
2019 QTest::newRow("MyClass inherits MyClass")
2020 << &MyNamespace::MyClass::staticMetaObject << &MyNamespace::MyClass::staticMetaObject << true;
2021 QTest::newRow("MyClassSubclass inherits QObject")
2022 << &MyNamespace::MyClassSubclass::staticMetaObject << &QObject::staticMetaObject << true;
2023 QTest::newRow("MyClassSubclass2 inherits QObject")
2024 << &MyNamespace::MyClassSubclass2::staticMetaObject << &QObject::staticMetaObject << true;
2025 QTest::newRow("MyClassSubclass2 inherits MyClass2")
2026 << &MyNamespace::MyClassSubclass2::staticMetaObject << &MyNamespace::MyClass2Subclass::staticMetaObject << false;
2027}
2028
2029void tst_QMetaObject::inherits()
2030{
2031#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
2032 QFETCH(const QMetaObject *, derivedMetaObject);
2033 QFETCH(const QMetaObject *, baseMetaObject);
2034 QFETCH(bool, inheritsResult);
2035
2036 QCOMPARE(derivedMetaObject->inherits(baseMetaObject), inheritsResult);
2037#endif
2038}
2039
2040void tst_QMetaObject::notifySignalsInParentClass()
2041{
2042#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
2043 MyNamespace::ClassWithSetterGetterSignalsAddsProperties obj;
2044 QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value1")).notifySignal().name(), QByteArray("value1Changed"));
2045 QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("value2Changed"));
2046
2047 MyNamespace::ClassWithChangedSignalNewValue obj2;
2048 QCOMPARE(obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("propertiesChanged"));
2049#if 0 // With verdigris, this is a compilation error when the NOTIFY signal is not a signal
2050 QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::notifySignal: cannot find the NOTIFY signal thisIsNotASignal in class MyNamespace::ClassWithChangedSignalNewValue for property 'value3'");
2051 obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value3")).notifySignal();
2052#endif
2053#endif
2054}
2055
2056QTEST_MAIN(tst_QMetaObject)
2057