1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the test suite of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:GPL-EXCEPT$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU
20** General Public License version 3 as published by the Free Software
21** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30
31
32#include <QtTest/QtTest>
33#include <stdio.h>
34#include <qobject.h>
35#include <qmetaobject.h>
36#include <qjsondocument.h>
37
38#include "using-namespaces.h"
39#include "assign-namespace.h"
40#include "no-keywords.h"
41#include "single_function_keyword.h"
42#include "backslash-newlines.h"
43#include "slots-with-void-template.h"
44#include "pure-virtual-signals.h"
45#include "qinvokable.h"
46// msvc and friends crap out on it
47#if !defined(Q_CC_GNU) || defined(Q_OS_WIN)
48#define SKIP_NEWLINE_TEST
49#endif
50#if !defined(SKIP_NEWLINE_TEST)
51#include "os9-newlines.h"
52// msvc and friends crap out on this file too,
53// it seems to contain Mac 9 EOLs, and not windows EOLs.
54#include "win-newlines.h"
55#endif
56#include "escapes-in-string-literals.h"
57#include "cstyle-enums.h"
58
59#if defined(PARSE_BOOST)
60#include "parse-boost.h"
61#endif
62#include "cxx11-enums.h"
63#include "cxx11-final-classes.h"
64#include "cxx11-explicit-override-control.h"
65#include "cxx11-trailing-return.h"
66
67#include "parse-defines.h"
68#include "related-metaobjects-in-namespaces.h"
69#include "related-metaobjects-in-gadget.h"
70#include "related-metaobjects-name-conflict.h"
71
72#include "non-gadget-parent-class.h"
73#include "grand-parent-gadget-class.h"
74#include "namespace.h"
75#include "cxx17-namespaces.h"
76#include "cxx-attributes.h"
77
78#ifdef Q_MOC_RUN
79// check that moc can parse these constructs, they are being used in Windows winsock2.h header
80#define STRING_HASH_HASH(x) ("foo" ## x ## "bar")
81const char *string_hash_hash = STRING_HASH_HASH("baz");
82#endif
83
84Q_DECLARE_METATYPE(const QMetaObject*);
85
86namespace TestNonQNamespace {
87
88struct TestGadget {
89 Q_GADGET
90 Q_CLASSINFO("key", "value")
91public:
92 enum class TestGEnum1 {
93 Key1 = 11,
94 Key2
95 };
96 Q_ENUM(TestGEnum1)
97
98 enum class TestGEnum2 {
99 Key1 = 17,
100 Key2
101 };
102 Q_ENUM(TestGEnum2)
103};
104
105}
106
107namespace TestQNamespace {
108 Q_NAMESPACE
109 enum class TestEnum1 {
110 Key1 = 11,
111 Key2
112 };
113 Q_ENUM_NS(TestEnum1)
114
115 enum class TestEnum2 {
116 Key1 = 17,
117 Key2
118 };
119 Q_ENUM_NS(TestEnum2)
120
121 // try to dizzy moc by adding a struct in between
122 struct TestGadget {
123 Q_GADGET
124 public:
125 enum class TestGEnum1 {
126 Key1 = 13,
127 Key2
128 };
129 enum class TestGEnum2 {
130 Key1 = 23,
131 Key2
132 };
133 Q_ENUM(TestGEnum1)
134 Q_ENUM(TestGEnum2)
135 };
136
137 enum class TestFlag1 {
138 None = 0,
139 Flag1 = 1,
140 Flag2 = 2,
141 Any = Flag1 | Flag2
142 };
143 Q_FLAG_NS(TestFlag1)
144
145 enum class TestFlag2 {
146 None = 0,
147 Flag1 = 4,
148 Flag2 = 8,
149 Any = Flag1 | Flag2
150 };
151 Q_FLAG_NS(TestFlag2)
152}
153
154
155#define TESTEXPORTMACRO Q_DECL_EXPORT
156
157namespace TestExportNamespace {
158 Q_NAMESPACE_EXPORT(TESTEXPORTMACRO)
159 enum class MyEnum {
160 Key1, Key2
161 };
162 Q_ENUM_NS(MyEnum)
163}
164
165QT_USE_NAMESPACE
166
167template <bool b> struct QTBUG_31218 {};
168struct QTBUG_31218_Derived : QTBUG_31218<-1<0> {};
169
170#if defined(Q_MOC_RUN)
171 class QTBUG_45790 : Bug() { };
172#endif
173
174class CreatableGadget
175{
176 Q_GADGET
177public:
178 Q_INVOKABLE CreatableGadget()
179 {
180 CreatableGadget::qt_static_metacall((QObject*)this, QMetaObject::ReadProperty, -1, nullptr);
181 }
182};
183
184CreatableGadget creatableGadget; // Force the compiler to use the constructor
185
186struct MyStruct {};
187struct MyStruct2 {};
188
189struct SuperClass {};
190
191// Try to avoid inserting for instance a comment with a quote between the following line and the Q_OBJECT
192// That will make the test give a false positive.
193const char* test_multiple_number_of_escapes = "\\\"";
194namespace MyNamespace
195{
196 class TestSuperClass : public QObject
197 {
198 Q_OBJECT
199 public:
200 inline TestSuperClass() {}
201 };
202}
203
204namespace String
205{
206 typedef QString Type;
207}
208
209namespace Int
210{
211 typedef int Type;
212}
213
214typedef struct {
215 int doNotConfuseMoc;
216} OldStyleCStruct;
217
218namespace {
219
220 class GadgetInUnnamedNS
221 {
222 Q_GADGET
223 Q_PROPERTY(int x READ x WRITE setX)
224 Q_PROPERTY(int y READ y WRITE setY)
225 public:
226 explicit GadgetInUnnamedNS(int x, int y) : m_x(x), m_y(y) {}
227 int x() const { return m_x; }
228 int y() const { return m_y; }
229 void setX(int x) { m_x = x; }
230 void setY(int y) { m_y = y; }
231
232 private:
233 int m_x, m_y;
234 };
235
236 class ObjectInUnnamedNS : public QObject
237 {
238 Q_OBJECT
239 public:
240 explicit ObjectInUnnamedNS(QObject *parent = nullptr) : QObject(parent) {}
241 };
242
243}
244
245class Sender : public QObject
246{
247 Q_OBJECT
248
249public:
250 void sendValue(const String::Type& value)
251 {
252 emit send(value);
253 }
254 void sendValue(const Int::Type& value)
255 {
256 emit send(value);
257 }
258
259 bool operator< ( const Sender & ) const { /* QTBUG-36834 */ return true;}
260signals:
261 void send(const String::Type&);
262 void send(const Int::Type&);
263};
264
265class Receiver : public QObject
266{
267 Q_OBJECT
268public:
269 Receiver() : stringCallCount(0), intCallCount(0) {}
270
271 int stringCallCount;
272 int intCallCount;
273
274public slots:
275 void receive(const String::Type&) { stringCallCount++; }
276 void receive(const Int::Type&) { intCallCount++; }
277};
278
279#define MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES
280
281#define DONT_CONFUSE_MOC(klass) klass
282#define DONT_CONFUSE_MOC_EVEN_MORE(klass, dummy, dummy2) klass
283
284Q_DECLARE_METATYPE(MyStruct)
285Q_DECLARE_METATYPE(MyStruct*)
286
287namespace myNS {
288 struct Points
289 {
290 Points() : p1(0xBEEF), p2(0xBABE) { }
291 int p1, p2;
292 };
293}
294
295Q_DECLARE_METATYPE(myNS::Points)
296
297class TestClassinfoWithEscapes: public QObject
298{
299 Q_OBJECT
300 Q_CLASSINFO("escaped", "\"bar\"")
301 Q_CLASSINFO("\"escaped\"", "foo")
302 Q_CLASSINFO("cpp c*/omment", "f/*oo")
303 Q_CLASSINFO("endswith\\", "Or?\?/")
304 Q_CLASSINFO("newline\n inside\n", "Or \r")
305public slots:
306 void slotWithAReallyLongName(int)
307 { }
308};
309
310struct ForwardDeclaredStruct;
311
312struct StructQObject : public QObject
313{
314 Q_OBJECT
315public:
316 void foo(struct ForwardDeclaredStruct *);
317};
318
319void StructQObject::foo(struct ForwardDeclaredStruct *)
320{
321 struct Inner {
322 bool field;
323 };
324
325 struct Inner unusedVariable;
326}
327
328class TestClass : public MyNamespace::TestSuperClass, public DONT_CONFUSE_MOC(MyStruct),
329 public DONT_CONFUSE_MOC_EVEN_MORE(MyStruct2, dummy, ignored)
330{
331 Q_OBJECT
332 Q_CLASSINFO("help", QT_TR_NOOP("Opening this will let you configure something"))
333 Q_PROPERTY(short int shortIntProperty READ shortIntProperty)
334 Q_PROPERTY(unsigned short int unsignedShortIntProperty READ unsignedShortIntProperty)
335 Q_PROPERTY(signed short int signedShortIntProperty READ signedShortIntProperty)
336 Q_PROPERTY(long int longIntProperty READ longIntProperty)
337 Q_PROPERTY(unsigned long int unsignedLongIntProperty READ unsignedLongIntProperty)
338 Q_PROPERTY(signed long int signedLongIntProperty READ signedLongIntProperty)
339 Q_PROPERTY(long double longDoubleProperty READ longDoubleProperty)
340 Q_PROPERTY(myNS::Points points READ points WRITE setPoints)
341
342 Q_CLASSINFO("Multi"
343 "line",
344 ""
345 "This is a "
346 "multiline Q_CLASSINFO"
347 "")
348
349 // a really really long string that we have to cut into pieces in the generated stringdata
350 // table, otherwise msvc craps out
351 Q_CLASSINFO("D-Bus Introspection", ""
352" <interface name=\"org.kde.KCookieServer\" >\n"
353" <method name=\"findCookies\" >\n"
354" <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
355" <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
356" <arg direction=\"out\" type=\"s\" name=\"cookies\" />\n"
357" </method>\n"
358" <method name=\"findDomains\" >\n"
359" <arg direction=\"out\" type=\"as\" name=\"domains\" />\n"
360" </method>\n"
361" <method name=\"findCookies\" >\n"
362" <arg direction=\"in\" type=\"ai\" name=\"fields\" />\n"
363" <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
364" <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
365" <arg direction=\"in\" type=\"s\" name=\"path\" />\n"
366" <arg direction=\"in\" type=\"s\" name=\"name\" />\n"
367" <arg direction=\"out\" type=\"as\" name=\"cookies\" />\n"
368" <annotation value=\"QList&lt;int>\" name=\"com.trolltech.QtDBus.QtTypeName.In0\" />\n"
369" </method>\n"
370" <method name=\"findDOMCookies\" >\n"
371" <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
372" <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
373" <arg direction=\"out\" type=\"s\" name=\"cookies\" />\n"
374" </method>\n"
375" <method name=\"addCookies\" >\n"
376" <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
377" <arg direction=\"in\" type=\"ay\" name=\"cookieHeader\" />\n"
378" <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
379" </method>\n"
380" <method name=\"deleteCookie\" >\n"
381" <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
382" <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
383" <arg direction=\"in\" type=\"s\" name=\"path\" />\n"
384" <arg direction=\"in\" type=\"s\" name=\"name\" />\n"
385" </method>\n"
386" <method name=\"deleteCookiesFromDomain\" >\n"
387" <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
388" </method>\n"
389" <method name=\"deleteSessionCookies\" >\n"
390" <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
391" </method>\n"
392" <method name=\"deleteSessionCookiesFor\" >\n"
393" <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
394" <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
395" </method>\n"
396" <method name=\"deleteAllCookies\" />\n"
397" <method name=\"addDOMCookies\" >\n"
398" <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
399" <arg direction=\"in\" type=\"ay\" name=\"cookieHeader\" />\n"
400" <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
401" </method>\n"
402" <method name=\"setDomainAdvice\" >\n"
403" <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
404" <arg direction=\"in\" type=\"s\" name=\"advice\" />\n"
405" </method>\n"
406" <method name=\"getDomainAdvice\" >\n"
407" <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
408" <arg direction=\"out\" type=\"s\" name=\"advice\" />\n"
409" </method>\n"
410" <method name=\"reloadPolicy\" />\n"
411" <method name=\"shutdown\" />\n"
412" </interface>\n"
413 "")
414
415public:
416 inline TestClass() {}
417
418private slots:
419 inline void dummy1() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES {}
420 inline void dummy2() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES const {}
421 inline void dummy3() const MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES {}
422
423 void slotWithULongLong(unsigned long long) {}
424 void slotWithULongLongP(unsigned long long*) {}
425 void slotWithULong(unsigned long) {}
426 void slotWithLongLong(long long) {}
427 void slotWithLong(long) {}
428
429 void slotWithColonColonType(::Int::Type) {}
430
431 TestClass &slotWithReferenceReturnType() { return *this; }
432
433#if (0 && 1) || 1
434 void expressionEvaluationShortcut1() {}
435#endif
436#if (1 || 0) && 0
437#else
438 void expressionEvaluationShortcut2() {}
439#endif
440
441public slots:
442 void slotWithArray(const double[3]) {}
443 void slotWithNamedArray(const double namedArray[3]) { Q_UNUSED(namedArray); }
444 void slotWithMultiArray(const double[3][4]) {}
445
446 short int shortIntProperty() { return 0; }
447 unsigned short int unsignedShortIntProperty() { return 0; }
448 signed short int signedShortIntProperty() { return 0; }
449 long int longIntProperty() { return 0; }
450 unsigned long int unsignedLongIntProperty() { return 0; }
451 signed long int signedLongIntProperty() { return 0; }
452 long double longDoubleProperty() { return 0.0; }
453
454 myNS::Points points() { return m_points; }
455 void setPoints(myNS::Points points) { m_points = points; }
456
457signals:
458 void signalWithArray(const double[3]);
459 void signalWithNamedArray(const double namedArray[3]);
460 void signalWithIterator(QList<QUrl>::iterator);
461 void signalWithListPointer(QList<QUrl>*); //QTBUG-31002
462
463private slots:
464 // for tst_Moc::preprocessorConditionals
465#if 0
466 void invalidSlot() {}
467#else
468 void slotInElse() {}
469#endif
470
471#if 1
472 void slotInIf() {}
473#else
474 void invalidSlot() {}
475#endif
476
477#if 0
478 void invalidSlot() {}
479#elif 0
480#else
481 void slotInLastElse() {}
482#endif
483
484#if 0
485 void invalidSlot() {}
486#elif 1
487 void slotInElif() {}
488#else
489 void invalidSlot() {}
490#endif
491
492 friend class Receiver; // task #85783
493signals:
494 friend class Sender; // task #85783
495
496#define MACRO_DEFINED
497
498#if !(defined MACRO_UNDEF || defined MACRO_DEFINED) || 1
499 void signalInIf1();
500#else
501 void doNotExist();
502#endif
503#if !(!defined MACRO_UNDEF || !defined MACRO_DEFINED) && 1
504 void doNotExist();
505#else
506 void signalInIf2();
507#endif
508#if !(!defined (MACRO_DEFINED) || !defined (MACRO_UNDEF)) && 1
509 void doNotExist();
510#else
511 void signalInIf3();
512#endif
513
514# //QTBUG-22717
515 # /* */
516#
517
518 # \
519
520//
521public slots:
522 void const slotWithSillyConst() {}
523
524public:
525 Q_INVOKABLE void const slotWithSillyConst2() {}
526 Q_INVOKABLE QObject& myInvokableReturningRef()
527 { return *this; }
528 Q_INVOKABLE const QObject& myInvokableReturningConstRef() const
529 { return *this; }
530
531
532 // that one however should be fine
533public slots:
534 void slotWithVoidStar(void *) {}
535
536private:
537 myNS::Points m_points;
538
539#ifdef Q_MOC_RUN
540 int xx = 11'11; // digit separator must not confuse moc (QTBUG-59351)
541 int xx = 0b11'11; // digit separator in a binary literal must not confuse moc (QTBUG-75656)
542#endif
543
544private slots:
545 inline virtual void blub1() {}
546 virtual inline void blub2() {}
547};
548
549class PropertyTestClass : public QObject
550{
551 Q_OBJECT
552public:
553
554 enum TestEnum { One, Two, Three };
555
556 Q_ENUM(TestEnum)
557};
558
559class PropertyUseClass : public QObject
560{
561 Q_OBJECT
562 Q_PROPERTY(PropertyTestClass::TestEnum foo READ foo)
563public:
564
565 inline PropertyTestClass::TestEnum foo() const { return PropertyTestClass::One; }
566};
567
568class EnumSourceClass : public QObject
569{
570 Q_OBJECT
571
572public:
573 enum TestEnum { Value = 37 };
574
575 Q_ENUM(TestEnum)
576};
577
578class EnumUserClass : public QObject
579{
580 Q_OBJECT
581
582public:
583 Q_ENUMS(EnumSourceClass::TestEnum)
584};
585
586class CtorTestClass : public QObject
587{
588 Q_OBJECT
589public:
590 Q_INVOKABLE CtorTestClass(QObject *parent = 0);
591
592 CtorTestClass(int foo);
593
594 inline Q_INVOKABLE CtorTestClass(const QString &str)
595 { m_str = str; }
596
597 QString m_str;
598
599protected:
600 CtorTestClass(int foo, int bar, int baz);
601private:
602 CtorTestClass(float, float) {}
603};
604
605CtorTestClass::CtorTestClass(QObject *parent)
606 : QObject(parent) {}
607
608CtorTestClass::CtorTestClass(int, int, int) {}
609
610class PrivatePropertyTest;
611
612class tst_Moc : public QObject
613{
614 Q_OBJECT
615
616 Q_PROPERTY(bool user1 READ user1 USER true )
617 Q_PROPERTY(bool user2 READ user2 USER false)
618 Q_PROPERTY(bool user3 READ user3 USER userFunction())
619 Q_PROPERTY(QString member1 MEMBER sMember)
620 Q_PROPERTY(QString member2 MEMBER sMember READ member2)
621 Q_PROPERTY(QString member3 MEMBER sMember WRITE setMember3)
622 Q_PROPERTY(QString member4 MEMBER sMember NOTIFY member4Changed)
623 Q_PROPERTY(QString member5 MEMBER sMember NOTIFY member5Changed)
624 Q_PROPERTY(QString member6 MEMBER sConst CONSTANT)
625 Q_PROPERTY(QString sub1 MEMBER (sub.m_string))
626 Q_PROPERTY(QString sub2 READ (sub.string) WRITE (sub.setString))
627
628public:
629 inline tst_Moc() : sConst("const") {}
630
631private slots:
632 void initTestCase();
633
634 void slotWithException() throw(MyStruct);
635 void dontStripNamespaces();
636 void oldStyleCasts();
637 void warnOnExtraSignalSlotQualifiaction();
638 void uLongLong();
639 void inputFileNameWithDotsButNoExtension();
640 void userProperties();
641 void supportConstSignals();
642 void task87883();
643 void multilineComments();
644 void classinfoWithEscapes();
645 void trNoopInClassInfo();
646 void ppExpressionEvaluation();
647 void arrayArguments();
648 void preprocessorConditionals();
649 void blackslashNewlines();
650 void slotWithSillyConst();
651 void testExtraData();
652 void testExtraDataForEnum();
653 void namespaceTypeProperty();
654 void slotsWithVoidTemplate();
655 void structQObject();
656 void namespacedFlags();
657 void warnOnMultipleInheritance();
658 void ignoreOptionClashes();
659 void forgottenQInterface();
660 void os9Newline();
661 void winNewline();
662 void escapesInStringLiterals();
663 void frameworkSearchPath();
664 void cstyleEnums();
665 void defineMacroViaCmdline();
666 void defineMacroViaForcedInclude();
667 void defineMacroViaForcedIncludeRelative();
668 void environmentIncludePaths_data();
669 void environmentIncludePaths();
670 void specifyMetaTagsFromCmdline();
671 void invokable();
672 void singleFunctionKeywordSignalAndSlot();
673 void templateGtGt();
674 void qprivateslots();
675 void qprivateproperties();
676 void inlineSlotsWithThrowDeclaration();
677 void warnOnPropertyWithoutREAD();
678 void constructors();
679 void typenameWithUnsigned();
680 void warnOnVirtualSignal();
681 void QTBUG5590_dummyProperty();
682 void QTBUG12260_defaultTemplate();
683 void notifyError();
684 void QTBUG17635_invokableAndProperty();
685 void revisions();
686 void warnings_data();
687 void warnings();
688 void privateClass();
689 void cxx11Enums_data();
690 void cxx11Enums();
691 void cxx11TrailingReturn();
692 void returnRefs();
693 void memberProperties_data();
694 void memberProperties();
695 void memberProperties2();
696 void privateSignalConnection();
697 void finalClasses_data();
698 void finalClasses();
699 void explicitOverrideControl_data();
700 void explicitOverrideControl();
701 void overloadedAddressOperator();
702 void autoPropertyMetaTypeRegistration();
703 void autoMethodArgumentMetaTypeRegistration();
704 void autoSignalSpyMetaTypeRegistration();
705 void parseDefines();
706 void preprocessorOnly();
707 void unterminatedFunctionMacro();
708 void QTBUG32933_relatedObjectsDontIncludeItself();
709 void writeEnumFromUnrelatedClass();
710 void relatedMetaObjectsWithinNamespaces();
711 void relatedMetaObjectsInGadget();
712 void relatedMetaObjectsNameConflict_data();
713 void relatedMetaObjectsNameConflict();
714 void strignLiteralsInMacroExtension();
715 void unnamedNamespaceObjectsAndGadgets();
716 void veryLongStringData();
717 void gadgetHierarchy();
718 void optionsFileError_data();
719 void optionsFileError();
720 void testQNamespace();
721 void cxx17Namespaces();
722 void cxxAttributes();
723 void mocJsonOutput();
724 void requiredProperties();
725
726signals:
727 void sigWithUnsignedArg(unsigned foo);
728 void sigWithSignedArg(signed foo);
729 void sigWithConstSignedArg(const signed foo);
730 void sigWithVolatileConstSignedArg(volatile const signed foo);
731 void sigWithCustomType(const MyStruct);
732 void constSignal1() const;
733 void constSignal2(int arg) const;
734 void member4Changed();
735 void member5Changed(const QString &newVal);
736
737private:
738 bool user1() { return true; };
739 bool user2() { return false; };
740 bool user3() { return false; };
741 bool userFunction(){ return false; };
742 template <class T> void revisions_T();
743 QString member2() const { return sMember; }
744 void setMember3( const QString &sVal ) { sMember = sVal; }
745
746private:
747 QString m_moc;
748 QString m_sourceDirectory;
749 QString qtIncludePath;
750 class PrivateClass;
751 QString sMember;
752 const QString sConst;
753 PrivatePropertyTest *pPPTest;
754
755 struct {
756 QString m_string;
757 void setString(const QString &s) { m_string = s; }
758 QString string() { return m_string; }
759 } sub;
760
761};
762
763void tst_Moc::initTestCase()
764{
765 QString binpath = QLibraryInfo::location(QLibraryInfo::BinariesPath);
766 QString qmake = QString("%1/qmake").arg(a: binpath);
767 m_moc = QString("%1/moc").arg(a: binpath);
768
769 const QString testHeader = QFINDTESTDATA("backslash-newlines.h");
770 QVERIFY(!testHeader.isEmpty());
771 m_sourceDirectory = QFileInfo(testHeader).absolutePath();
772#if defined(Q_OS_UNIX) && QT_CONFIG(process)
773 QProcess proc;
774 proc.start(program: qmake, arguments: QStringList() << "-query" << "QT_INSTALL_HEADERS");
775 QVERIFY(proc.waitForFinished());
776 QCOMPARE(proc.exitCode(), 0);
777 QByteArray output = proc.readAllStandardOutput();
778 QVERIFY(!output.isEmpty());
779 QCOMPARE(proc.readAllStandardError(), QByteArray());
780 qtIncludePath = QString::fromLocal8Bit(str: output).trimmed();
781 QFileInfo fi(qtIncludePath);
782 QVERIFY(fi.exists());
783 QVERIFY(fi.isDir());
784#endif
785}
786
787void tst_Moc::slotWithException() throw(MyStruct)
788{
789 // be happy
790 QVERIFY(true);
791}
792
793void tst_Moc::dontStripNamespaces()
794{
795 Sender sender;
796 Receiver receiver;
797
798 connect(sender: &sender, SIGNAL(send(const String::Type &)),
799 receiver: &receiver, SLOT(receive(const String::Type &)));
800 connect(sender: &sender, SIGNAL(send(const Int::Type &)),
801 receiver: &receiver, SLOT(receive(const Int::Type &)));
802
803 sender.sendValue(value: String::Type("Hello"));
804 QCOMPARE(receiver.stringCallCount, 1);
805 QCOMPARE(receiver.intCallCount, 0);
806 sender.sendValue(value: Int::Type(42));
807 QCOMPARE(receiver.stringCallCount, 1);
808 QCOMPARE(receiver.intCallCount, 1);
809}
810
811void tst_Moc::oldStyleCasts()
812{
813#ifdef MOC_CROSS_COMPILED
814 QSKIP("Not tested when cross-compiled");
815#endif
816#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
817 QProcess proc;
818 proc.start(program: m_moc, arguments: QStringList(m_sourceDirectory + QStringLiteral("/oldstyle-casts.h")));
819 QVERIFY(proc.waitForFinished());
820 QCOMPARE(proc.exitCode(), 0);
821 QByteArray mocOut = proc.readAllStandardOutput();
822 QVERIFY(!mocOut.isEmpty());
823 QCOMPARE(proc.readAllStandardError(), QByteArray());
824
825 QStringList args;
826 args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
827 << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-";
828 proc.start(program: "gcc", arguments: args);
829 QVERIFY(proc.waitForStarted());
830 proc.write(data: mocOut);
831 proc.closeWriteChannel();
832
833 QVERIFY(proc.waitForFinished());
834 QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
835 QCOMPARE(proc.exitCode(), 0);
836#else
837 QSKIP("Only tested on linux/gcc");
838#endif
839}
840
841void tst_Moc::warnOnExtraSignalSlotQualifiaction()
842{
843#ifdef MOC_CROSS_COMPILED
844 QSKIP("Not tested when cross-compiled");
845#endif
846#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
847 QProcess proc;
848 const QString header = m_sourceDirectory + QStringLiteral("/extraqualification.h");
849 proc.start(program: m_moc, arguments: QStringList(header));
850 QVERIFY(proc.waitForFinished());
851 QCOMPARE(proc.exitCode(), 0);
852 QByteArray mocOut = proc.readAllStandardOutput();
853 QVERIFY(!mocOut.isEmpty());
854 QString mocWarning = QString::fromLocal8Bit(str: proc.readAllStandardError());
855 QCOMPARE(mocWarning, header +
856 QString(":43: Warning: Function declaration Test::badFunctionDeclaration contains extra qualification. Ignoring as signal or slot.\n") +
857 header + QString(":46: Warning: parsemaybe: Function declaration Test::anotherOne contains extra qualification. Ignoring as signal or slot.\n"));
858#else
859 QSKIP("Only tested on linux/gcc");
860#endif
861}
862
863void tst_Moc::uLongLong()
864{
865 TestClass tst;
866 const QMetaObject *mobj = tst.metaObject();
867 int idx = mobj->indexOfSlot(slot: "slotWithULong(ulong)");
868 QVERIFY(idx != -1);
869 idx = mobj->indexOfSlot(slot: "slotWithULongLong(unsigned long long)");
870 QVERIFY(idx != -1);
871 idx = mobj->indexOfSlot(slot: "slotWithULongLongP(unsigned long long*)");
872 QVERIFY(idx != -1);
873
874 idx = mobj->indexOfSlot(slot: "slotWithLong(long)");
875 QVERIFY(idx != -1);
876 idx = mobj->indexOfSlot(slot: "slotWithLongLong(long long)");
877 QVERIFY(idx != -1);
878}
879
880void tst_Moc::inputFileNameWithDotsButNoExtension()
881{
882#ifdef MOC_CROSS_COMPILED
883 QSKIP("Not tested when cross-compiled");
884#endif
885#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
886 QProcess proc;
887 proc.setWorkingDirectory(m_sourceDirectory + QStringLiteral("/task71021"));
888 proc.start(program: m_moc, arguments: QStringList("../Header"));
889 QVERIFY(proc.waitForFinished());
890 QCOMPARE(proc.exitCode(), 0);
891 QByteArray mocOut = proc.readAllStandardOutput();
892 QVERIFY(!mocOut.isEmpty());
893 QCOMPARE(proc.readAllStandardError(), QByteArray());
894
895 QStringList args;
896 args << "-c" << "-x" << "c++" << "-I" << ".."
897 << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-";
898 proc.start(program: "gcc", arguments: args);
899 QVERIFY(proc.waitForStarted());
900 proc.write(data: mocOut);
901 proc.closeWriteChannel();
902
903 QVERIFY(proc.waitForFinished());
904 QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
905 QCOMPARE(proc.exitCode(), 0);
906#else
907 QSKIP("Only tested on linux/gcc");
908#endif
909}
910
911void tst_Moc::userProperties()
912{
913 const QMetaObject *mobj = metaObject();
914 QMetaProperty property = mobj->property(index: mobj->indexOfProperty(name: "user1"));
915 QVERIFY(property.isValid());
916 QVERIFY(property.isUser());
917
918 property = mobj->property(index: mobj->indexOfProperty(name: "user2"));
919 QVERIFY(property.isValid());
920 QVERIFY(!property.isUser());
921
922 property = mobj->property(index: mobj->indexOfProperty(name: "user3"));
923 QVERIFY(property.isValid());
924 QVERIFY(!property.isUser(this));
925}
926
927void tst_Moc::supportConstSignals()
928{
929 QSignalSpy spy1(this, SIGNAL(constSignal1()));
930 QVERIFY(spy1.isEmpty());
931 emit constSignal1();
932 QCOMPARE(spy1.count(), 1);
933
934 QSignalSpy spy2(this, SIGNAL(constSignal2(int)));
935 QVERIFY(spy2.isEmpty());
936 emit constSignal2(arg: 42);
937 QCOMPARE(spy2.count(), 1);
938 QCOMPARE(spy2.at(0).at(0).toInt(), 42);
939}
940
941#include "task87883.h"
942
943void tst_Moc::task87883()
944{
945 QVERIFY(Task87883::staticMetaObject.className());
946}
947
948#include "c-comments.h"
949
950void tst_Moc::multilineComments()
951{
952 QVERIFY(IfdefedClass::staticMetaObject.className());
953}
954
955void tst_Moc::classinfoWithEscapes()
956{
957 const QMetaObject *mobj = &TestClassinfoWithEscapes::staticMetaObject;
958 QCOMPARE(mobj->methodCount() - mobj->methodOffset(), 1);
959
960 QCOMPARE(mobj->classInfoCount(), 5);
961 QCOMPARE(mobj->classInfo(2).name(), "cpp c*/omment");
962 QCOMPARE(mobj->classInfo(2).value(), "f/*oo");
963 QCOMPARE(mobj->classInfo(3).name(), "endswith\\");
964 QCOMPARE(mobj->classInfo(3).value(), "Or?\?/");
965 QCOMPARE(mobj->classInfo(4).name(), "newline\n inside\n");
966 QCOMPARE(mobj->classInfo(4).value(), "Or \r");
967
968 QMetaMethod mm = mobj->method(index: mobj->methodOffset());
969 QCOMPARE(mm.methodSignature(), QByteArray("slotWithAReallyLongName(int)"));
970}
971
972void tst_Moc::trNoopInClassInfo()
973{
974 TestClass t;
975 const QMetaObject *mobj = t.metaObject();
976 QVERIFY(mobj);
977 QCOMPARE(mobj->classInfoCount(), 3);
978 QCOMPARE(mobj->indexOfClassInfo("help"), 0);
979 QCOMPARE(QString(mobj->classInfo(0).value()), QString("Opening this will let you configure something"));
980}
981
982void tst_Moc::ppExpressionEvaluation()
983{
984 TestClass tst;
985 const QMetaObject *mobj = tst.metaObject();
986 int idx = mobj->indexOfSlot(slot: "expressionEvaluationShortcut1()");
987 QVERIFY(idx != -1);
988
989 idx = mobj->indexOfSlot(slot: "expressionEvaluationShortcut2()");
990 QVERIFY(idx != -1);
991}
992
993void tst_Moc::arrayArguments()
994{
995 TestClass tst;
996 const QMetaObject *mobj = tst.metaObject();
997 QVERIFY(mobj->indexOfSlot("slotWithArray(const double[3])") != -1);
998 QVERIFY(mobj->indexOfSlot("slotWithNamedArray(const double[3])") != -1);
999 QVERIFY(mobj->indexOfSlot("slotWithMultiArray(const double[3][4])") != -1);
1000 QVERIFY(mobj->indexOfSignal("signalWithArray(const double[3])") != -1);
1001 QVERIFY(mobj->indexOfSignal("signalWithNamedArray(const double[3])") != -1);
1002}
1003
1004void tst_Moc::preprocessorConditionals()
1005{
1006 TestClass tst;
1007 const QMetaObject *mobj = tst.metaObject();
1008 QVERIFY(mobj->indexOfSlot("slotInElse()") != -1);
1009 QVERIFY(mobj->indexOfSlot("slotInIf()") != -1);
1010 QVERIFY(mobj->indexOfSlot("slotInLastElse()") != -1);
1011 QVERIFY(mobj->indexOfSlot("slotInElif()") != -1);
1012 QVERIFY(mobj->indexOfSignal("signalInIf1()") != -1);
1013 QVERIFY(mobj->indexOfSignal("signalInIf2()") != -1);
1014 QVERIFY(mobj->indexOfSignal("signalInIf3()") != -1);
1015 QCOMPARE(mobj->indexOfSignal("doNotExist()"), -1);
1016}
1017
1018void tst_Moc::blackslashNewlines()
1019{
1020 BackslashNewlines tst;
1021 const QMetaObject *mobj = tst.metaObject();
1022 QVERIFY(mobj->indexOfSlot("works()") != -1);
1023 QCOMPARE(mobj->indexOfSlot("buggy()"), -1);
1024}
1025
1026void tst_Moc::slotWithSillyConst()
1027{
1028 TestClass tst;
1029 const QMetaObject *mobj = tst.metaObject();
1030 QVERIFY(mobj->indexOfSlot("slotWithSillyConst()") != -1);
1031 QVERIFY(mobj->indexOfMethod("slotWithSillyConst2()") != -1);
1032 QVERIFY(mobj->indexOfSlot("slotWithVoidStar(void*)") != -1);
1033}
1034
1035void tst_Moc::testExtraData()
1036{
1037 const QMetaObject *mobj = &PropertyTestClass::staticMetaObject;
1038 QCOMPARE(mobj->enumeratorCount(), 1);
1039 QCOMPARE(QByteArray(mobj->enumerator(0).name()), QByteArray("TestEnum"));
1040
1041 mobj = &PropertyUseClass::staticMetaObject;
1042 const int idx = mobj->indexOfProperty(name: "foo");
1043 QVERIFY(idx != -1);
1044 const QMetaProperty prop = mobj->property(index: idx);
1045 QVERIFY(prop.isValid());
1046 QVERIFY(prop.isEnumType());
1047 const QMetaEnum en = prop.enumerator();
1048 QCOMPARE(QByteArray(en.name()), QByteArray("TestEnum"));
1049}
1050
1051// QTBUG-20639 - Accept non-local enums for QML signal/slot parameters.
1052void tst_Moc::testExtraDataForEnum()
1053{
1054 const QMetaObject *mobjSource = &EnumSourceClass::staticMetaObject;
1055 QCOMPARE(mobjSource->enumeratorCount(), 1);
1056 QCOMPARE(QByteArray(mobjSource->enumerator(0).name()), QByteArray("TestEnum"));
1057
1058 const QMetaObject *mobjUser = &EnumUserClass::staticMetaObject;
1059 QCOMPARE(mobjUser->enumeratorCount(), 0);
1060
1061 const auto *objects = mobjUser->d.relatedMetaObjects;
1062 QVERIFY(objects);
1063 QCOMPARE(objects[0], mobjSource);
1064 QVERIFY(!objects[1]);
1065}
1066
1067void tst_Moc::namespaceTypeProperty()
1068{
1069 qRegisterMetaType<myNS::Points>(typeName: "myNS::Points");
1070 TestClass tst;
1071 QByteArray ba = QByteArray("points");
1072 QVariant v = tst.property(name: ba);
1073 QVERIFY(v.isValid());
1074 myNS::Points p = qvariant_cast<myNS::Points>(v);
1075 QCOMPARE(p.p1, 0xBEEF);
1076 QCOMPARE(p.p2, 0xBABE);
1077 p.p1 = 0xCAFE;
1078 p.p2 = 0x1EE7;
1079 QVERIFY(tst.setProperty(ba, QVariant::fromValue(p)));
1080 myNS::Points pp = qvariant_cast<myNS::Points>(v: tst.property(name: ba));
1081 QCOMPARE(p.p1, pp.p1);
1082 QCOMPARE(p.p2, pp.p2);
1083}
1084
1085void tst_Moc::slotsWithVoidTemplate()
1086{
1087 SlotsWithVoidTemplateTest test;
1088 QVERIFY(QObject::connect(&test, SIGNAL(myVoidSignal(void)),
1089 &test, SLOT(dummySlot(void))));
1090 QVERIFY(QObject::connect(&test, SIGNAL(mySignal(const TestTemplate<void> &)),
1091 &test, SLOT(anotherSlot(const TestTemplate<void> &))));
1092 QVERIFY(QObject::connect(&test, SIGNAL(myVoidSignal2()),
1093 &test, SLOT(dummySlot2())));
1094}
1095
1096void tst_Moc::structQObject()
1097{
1098 StructQObject o;
1099 QCOMPARE(QByteArray(o.metaObject()->className()), QByteArray("StructQObject"));
1100}
1101
1102#include "namespaced-flags.h"
1103
1104Q_DECLARE_METATYPE(QList<Foo::Bar::Flags>);
1105
1106void tst_Moc::namespacedFlags()
1107{
1108 Foo::Baz baz;
1109 Foo::Bar bar;
1110
1111 bar.setFlags(Foo::Bar::Read | Foo::Bar::Write);
1112 QVERIFY(baz.flags() != bar.flags());
1113
1114 const QVariant v = bar.property(name: "flags");
1115 QVERIFY(v.isValid());
1116 QVERIFY(baz.setProperty("flags", v));
1117 QCOMPARE(baz.flags(), bar.flags());
1118
1119 QList<Foo::Bar::Flags> l;
1120 l << baz.flags();
1121 QVariant v2 = baz.setProperty(name: "flagsList", value: QVariant::fromValue(value: l));
1122 QCOMPARE(l, baz.flagsList());
1123 QCOMPARE(l, qvariant_cast<QList<Foo::Bar::Flags> >(baz.property("flagsList")));
1124}
1125
1126void tst_Moc::warnOnMultipleInheritance()
1127{
1128#ifdef MOC_CROSS_COMPILED
1129 QSKIP("Not tested when cross-compiled");
1130#endif
1131#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1132 QProcess proc;
1133 QStringList args;
1134 const QString header = m_sourceDirectory + QStringLiteral("/warn-on-multiple-qobject-subclasses.h");
1135 args << "-I" << qtIncludePath + "/QtGui" << header;
1136 proc.start(program: m_moc, arguments: args);
1137 QVERIFY(proc.waitForFinished());
1138 QCOMPARE(proc.exitCode(), 0);
1139 QByteArray mocOut = proc.readAllStandardOutput();
1140 QVERIFY(!mocOut.isEmpty());
1141 QString mocWarning = QString::fromLocal8Bit(str: proc.readAllStandardError());
1142 QCOMPARE(mocWarning, header +
1143 QString(":43: Warning: Class Bar inherits from two QObject subclasses QWindow and Foo. This is not supported!\n"));
1144#else
1145 QSKIP("Only tested on linux/gcc");
1146#endif
1147}
1148
1149void tst_Moc::ignoreOptionClashes()
1150{
1151#ifdef MOC_CROSS_COMPILED
1152 QSKIP("Not tested when cross-compiled");
1153#endif
1154#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1155 QProcess proc;
1156 QStringList args;
1157 const QString header = m_sourceDirectory + QStringLiteral("/interface-from-include.h");
1158 const QString includeDir = m_sourceDirectory + "/Test.framework/Headers";
1159 // given --ignore-option-clashes, -pthread should be ignored, but the -I path should not be.
1160 args << "--ignore-option-clashes" << "-pthread" << "-I" << includeDir << "-fno-builtin" << header;
1161 proc.start(program: m_moc, arguments: args);
1162 bool finished = proc.waitForFinished();
1163 if (!finished)
1164 qWarning(msg: "waitForFinished failed. QProcess error: %d", (int)proc.error());
1165 QVERIFY(finished);
1166 if (proc.exitCode() != 0) {
1167 qDebug() << proc.readAllStandardError();
1168 }
1169 QCOMPARE(proc.exitCode(), 0);
1170 QCOMPARE(proc.readAllStandardError(), QByteArray());
1171 QByteArray mocOut = proc.readAllStandardOutput();
1172
1173 // If -pthread wasn't ignored, it was parsed as a prefix of "thread/", which breaks compilation.
1174 QStringList gccArgs;
1175 gccArgs << "-c" << "-x" << "c++" << "-I" << ".."
1176 << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null"
1177 << "-fPIC" << "-std=c++11" << "-";
1178 proc.start(program: "gcc", arguments: gccArgs);
1179 QVERIFY(proc.waitForStarted());
1180 proc.write(data: mocOut);
1181 proc.closeWriteChannel();
1182
1183 QVERIFY(proc.waitForFinished());
1184 QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
1185#else
1186 QSKIP("Only tested on linux/gcc");
1187#endif
1188}
1189
1190void tst_Moc::forgottenQInterface()
1191{
1192#ifdef MOC_CROSS_COMPILED
1193 QSKIP("Not tested when cross-compiled");
1194#endif
1195#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1196 QProcess proc;
1197 QStringList args;
1198 const QString header = m_sourceDirectory + QStringLiteral("/forgotten-qinterface.h");
1199 args << "-I" << qtIncludePath + "/QtCore" << header;
1200 proc.start(program: m_moc, arguments: args);
1201 QVERIFY(proc.waitForFinished());
1202 QCOMPARE(proc.exitCode(), 0);
1203 QByteArray mocOut = proc.readAllStandardOutput();
1204 QVERIFY(!mocOut.isEmpty());
1205 QString mocWarning = QString::fromLocal8Bit(str: proc.readAllStandardError());
1206 QCOMPARE(mocWarning, header +
1207 QString(":45: Warning: Class Test implements the interface MyInterface but does not list it in Q_INTERFACES. qobject_cast to MyInterface will not work!\n"));
1208#else
1209 QSKIP("Only tested on linux/gcc");
1210#endif
1211}
1212
1213void tst_Moc::os9Newline()
1214{
1215#if !defined(SKIP_NEWLINE_TEST)
1216 const QMetaObject &mo = Os9Newlines::staticMetaObject;
1217 QVERIFY(mo.indexOfSlot("testSlot()") != -1);
1218 QFile f(m_sourceDirectory + QStringLiteral("/os9-newlines.h"));
1219 QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
1220 QByteArray data = f.readAll();
1221 f.close();
1222 QVERIFY(!data.contains('\n'));
1223 QVERIFY(data.contains('\r'));
1224#endif
1225}
1226
1227void tst_Moc::winNewline()
1228{
1229#if !defined(SKIP_NEWLINE_TEST)
1230 const QMetaObject &mo = WinNewlines::staticMetaObject;
1231 QVERIFY(mo.indexOfSlot("testSlot()") != -1);
1232 QFile f(m_sourceDirectory + QStringLiteral("/win-newlines.h"));
1233 QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
1234 QByteArray data = f.readAll();
1235 f.close();
1236 for (int i = 0; i < data.count(); ++i) {
1237 if (data.at(i) == QLatin1Char('\r')) {
1238 QVERIFY(i < data.count() - 1);
1239 ++i;
1240 QCOMPARE(data.at(i), '\n');
1241 } else {
1242 QVERIFY(data.at(i) != '\n');
1243 }
1244 }
1245#endif
1246}
1247
1248void tst_Moc::escapesInStringLiterals()
1249{
1250 const QMetaObject &mo = StringLiterals::staticMetaObject;
1251 QCOMPARE(mo.classInfoCount(), 3);
1252
1253 int idx = mo.indexOfClassInfo(name: "Test");
1254 QVERIFY(idx != -1);
1255 QMetaClassInfo info = mo.classInfo(index: idx);
1256 QCOMPARE(QByteArray(info.value()),
1257 QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x53"));
1258
1259 QVERIFY(idx != -1);
1260 idx = mo.indexOfClassInfo(name: "Test2");
1261 info = mo.classInfo(index: idx);
1262 QCOMPARE(QByteArray(info.value()),
1263 QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\123"));
1264
1265 QVERIFY(idx != -1);
1266 idx = mo.indexOfClassInfo(name: "Test3");
1267 info = mo.classInfo(index: idx);
1268 QCOMPARE(QByteArray(info.value()),
1269 QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\nb"));
1270}
1271
1272void tst_Moc::frameworkSearchPath()
1273{
1274#ifdef MOC_CROSS_COMPILED
1275 QSKIP("Not tested when cross-compiled");
1276#endif
1277#if defined(Q_OS_UNIX) && QT_CONFIG(process)
1278 QStringList args;
1279 args << "-F" << m_sourceDirectory + QStringLiteral("/.")
1280 << m_sourceDirectory + QStringLiteral("/interface-from-framework.h")
1281 ;
1282
1283 QProcess proc;
1284 proc.start(program: m_moc, arguments: args);
1285 bool finished = proc.waitForFinished();
1286 if (!finished)
1287 qWarning(msg: "waitForFinished failed. QProcess error: %d", (int)proc.error());
1288 QVERIFY(finished);
1289 if (proc.exitCode() != 0) {
1290 qDebug() << proc.readAllStandardError();
1291 }
1292 QCOMPARE(proc.exitCode(), 0);
1293 QCOMPARE(proc.readAllStandardError(), QByteArray());
1294#else
1295 QSKIP("Only tested/relevant on unixy platforms");
1296#endif
1297}
1298
1299void tst_Moc::cstyleEnums()
1300{
1301 const QMetaObject &obj = CStyleEnums::staticMetaObject;
1302 QCOMPARE(obj.enumeratorCount(), 2);
1303 QMetaEnum metaEnum = obj.enumerator(index: 0);
1304 QCOMPARE(metaEnum.name(), "Baz");
1305 QCOMPARE(metaEnum.keyCount(), 2);
1306 QCOMPARE(metaEnum.key(0), "Foo");
1307 QCOMPARE(metaEnum.key(1), "Bar");
1308
1309 QMetaEnum metaEnum2 = obj.enumerator(index: 1);
1310 QCOMPARE(metaEnum2.name(), "Baz2");
1311 QCOMPARE(metaEnum2.keyCount(), 2);
1312 QCOMPARE(metaEnum2.key(0), "Foo2");
1313 QCOMPARE(metaEnum2.key(1), "Bar2");
1314}
1315
1316void tst_Moc::templateGtGt()
1317{
1318#ifdef MOC_CROSS_COMPILED
1319 QSKIP("Not tested when cross-compiled");
1320#endif
1321#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1322 QProcess proc;
1323 proc.start(program: m_moc, arguments: QStringList(m_sourceDirectory + QStringLiteral("/template-gtgt.h")));
1324 QVERIFY(proc.waitForFinished());
1325 QCOMPARE(proc.exitCode(), 0);
1326 QByteArray mocOut = proc.readAllStandardOutput();
1327 QVERIFY(!mocOut.isEmpty());
1328 QString mocWarning = QString::fromLocal8Bit(str: proc.readAllStandardError());
1329 QVERIFY(mocWarning.isEmpty());
1330#else
1331 QSKIP("Only tested on linux/gcc");
1332#endif
1333}
1334
1335void tst_Moc::defineMacroViaCmdline()
1336{
1337#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1338 QProcess proc;
1339
1340 QStringList args;
1341 args << "-DFOO";
1342 args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
1343
1344 proc.start(program: m_moc, arguments: args);
1345 QVERIFY(proc.waitForFinished());
1346 QCOMPARE(proc.exitCode(), 0);
1347 QCOMPARE(proc.readAllStandardError(), QByteArray());
1348 QByteArray mocOut = proc.readAllStandardOutput();
1349 QVERIFY(!mocOut.isEmpty());
1350#else
1351 QSKIP("Only tested on linux/gcc");
1352#endif
1353}
1354
1355void tst_Moc::defineMacroViaForcedInclude()
1356{
1357#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1358 QProcess proc;
1359
1360 QStringList args;
1361 args << "--include" << m_sourceDirectory + QLatin1String("/subdir/extradefines.h");
1362 args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
1363
1364 proc.start(program: m_moc, arguments: args);
1365 QVERIFY(proc.waitForFinished());
1366 QCOMPARE(proc.exitCode(), 0);
1367 QCOMPARE(proc.readAllStandardError(), QByteArray());
1368 QByteArray mocOut = proc.readAllStandardOutput();
1369 QVERIFY(!mocOut.isEmpty());
1370#else
1371 QSKIP("Only tested on linux/gcc");
1372#endif
1373}
1374
1375void tst_Moc::defineMacroViaForcedIncludeRelative()
1376{
1377#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1378 QProcess proc;
1379
1380 QStringList args;
1381 args << "--include" << QStringLiteral("extradefines.h") << "-I" + m_sourceDirectory + "/subdir";
1382 args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
1383
1384 proc.start(program: m_moc, arguments: args);
1385 QVERIFY(proc.waitForFinished());
1386 QCOMPARE(proc.exitCode(), 0);
1387 QCOMPARE(proc.readAllStandardError(), QByteArray());
1388 QByteArray mocOut = proc.readAllStandardOutput();
1389 QVERIFY(!mocOut.isEmpty());
1390#else
1391 QSKIP("Only tested on linux/gcc");
1392#endif
1393}
1394
1395
1396void tst_Moc::environmentIncludePaths_data()
1397{
1398#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1399 QTest::addColumn<QString>(name: "cmdline");
1400 QTest::addColumn<QString>(name: "varname");
1401
1402 QTest::newRow(dataTag: "INCLUDE") << "--compiler-flavor=msvc" << "INCLUDE";
1403 QTest::newRow(dataTag: "CPATH1") << QString() << "CPATH";
1404 QTest::newRow(dataTag: "CPATH2") << "--compiler-flavor=unix" << "CPATH";
1405 QTest::newRow(dataTag: "CPLUS_INCLUDE_PATH1") << QString() << "CPLUS_INCLUDE_PATH";
1406 QTest::newRow(dataTag: "CPLUS_INCLUDE_PATH2") << "--compiler-flavor=unix" << "CPLUS_INCLUDE_PATH";
1407#endif
1408}
1409
1410void tst_Moc::environmentIncludePaths()
1411{
1412#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1413 QFETCH(QString, cmdline);
1414 QFETCH(QString, varname);
1415
1416 QStringList args;
1417 if (!cmdline.isEmpty())
1418 args << cmdline;
1419 args << "--include" << QStringLiteral("extradefines.h")
1420 << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
1421
1422 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
1423 env.remove(name: "INCLUDE");
1424 env.remove(name: "CPATH");
1425 env.remove(name: "CPLUS_INCLUDE_PATH");
1426 env.insert(name: varname, value: m_sourceDirectory + "/subdir");
1427
1428 QProcess proc;
1429 proc.setProcessEnvironment(env);
1430 proc.start(program: m_moc, arguments: args);
1431 QVERIFY(proc.waitForFinished());
1432 QCOMPARE(proc.exitCode(), 0);
1433 QCOMPARE(proc.readAllStandardError(), QByteArray());
1434 QByteArray mocOut = proc.readAllStandardOutput();
1435 QVERIFY(!mocOut.isEmpty());
1436#else
1437 QSKIP("Only tested on linux/gcc");
1438#endif
1439}
1440
1441// tst_Moc::specifyMetaTagsFromCmdline()
1442// plugin_metadata.h contains a plugin which we register here. Since we're not building this
1443// application as a plugin, we need top copy some of the initializer code found in qplugin.h:
1444extern "C" QObject *qt_plugin_instance();
1445#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1446extern "C" QPluginMetaData qt_plugin_query_metadata();
1447class StaticPluginInstance{
1448public:
1449 StaticPluginInstance() {
1450 QStaticPlugin plugin(qt_plugin_instance, qt_plugin_query_metadata);
1451 qRegisterStaticPluginFunction(plugin);
1452 }
1453};
1454#else
1455extern "C" const char *qt_plugin_query_metadata();
1456class StaticPluginInstance{
1457public:
1458 StaticPluginInstance() {
1459 QStaticPlugin plugin = { .instance: &qt_plugin_instance, .rawMetaData: &qt_plugin_query_metadata };
1460 qRegisterStaticPluginFunction(staticPlugin: plugin);
1461 }
1462};
1463#endif
1464static StaticPluginInstance staticInstance;
1465
1466void tst_Moc::specifyMetaTagsFromCmdline() {
1467 foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) {
1468 const QString iid = plugin.metaData().value(key: QLatin1String("IID")).toString();
1469 if (iid == QLatin1String("test.meta.tags")) {
1470 const QJsonArray metaTagsUriList = plugin.metaData().value(key: "uri").toArray();
1471 QCOMPARE(metaTagsUriList.size(), 2);
1472
1473 // The following uri-s are set in the pro file using
1474 // -Muri=com.company.app -Muri=com.company.app.private
1475 QCOMPARE(metaTagsUriList[0].toString(), QLatin1String("com.company.app"));
1476 QCOMPARE(metaTagsUriList[1].toString(), QLatin1String("com.company.app.private"));
1477 return;
1478 }
1479 }
1480 QFAIL("Could not find plugin with IID 'test.meta.tags'");
1481}
1482
1483void tst_Moc::invokable()
1484{
1485 {
1486 const QMetaObject &mobj = InvokableBeforeReturnType::staticMetaObject;
1487 QCOMPARE(mobj.methodCount(), 6);
1488 QCOMPARE(mobj.method(5).methodSignature(), QByteArray("foo()"));
1489 }
1490
1491 {
1492 const QMetaObject &mobj = InvokableBeforeInline::staticMetaObject;
1493 QCOMPARE(mobj.methodCount(), 7);
1494 QCOMPARE(mobj.method(5).methodSignature(), QByteArray("foo()"));
1495 QCOMPARE(mobj.method(6).methodSignature(), QByteArray("bar()"));
1496 }
1497}
1498
1499void tst_Moc::singleFunctionKeywordSignalAndSlot()
1500{
1501 {
1502 const QMetaObject &mobj = SingleFunctionKeywordBeforeReturnType::staticMetaObject;
1503 QCOMPARE(mobj.methodCount(), 7);
1504 QCOMPARE(mobj.method(5).methodSignature(), QByteArray("mySignal()"));
1505 QCOMPARE(mobj.method(6).methodSignature(), QByteArray("mySlot()"));
1506 }
1507
1508 {
1509 const QMetaObject &mobj = SingleFunctionKeywordBeforeInline::staticMetaObject;
1510 QCOMPARE(mobj.methodCount(), 7);
1511 QCOMPARE(mobj.method(5).methodSignature(), QByteArray("mySignal()"));
1512 QCOMPARE(mobj.method(6).methodSignature(), QByteArray("mySlot()"));
1513 }
1514
1515 {
1516 const QMetaObject &mobj = SingleFunctionKeywordAfterInline::staticMetaObject;
1517 QCOMPARE(mobj.methodCount(), 7);
1518 QCOMPARE(mobj.method(5).methodSignature(), QByteArray("mySignal()"));
1519 QCOMPARE(mobj.method(6).methodSignature(), QByteArray("mySlot()"));
1520 }
1521}
1522
1523#include "qprivateslots.h"
1524
1525void tst_Moc::qprivateslots()
1526{
1527 TestQPrivateSlots tst;
1528 const QMetaObject *mobj = tst.metaObject();
1529 QVERIFY(mobj->indexOfSlot("_q_privateslot()") != -1);
1530 QVERIFY(mobj->indexOfMethod("method1()") != -1); //tast204730
1531}
1532
1533class PrivatePropertyTest : public QObject
1534{
1535 Q_OBJECT
1536 Q_PROPERTY(int foo READ foo WRITE setFoo)
1537 Q_PRIVATE_PROPERTY(d, int bar READ bar WRITE setBar)
1538 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, int plop READ plop WRITE setPlop)
1539 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d_func(), int baz READ baz WRITE setBaz)
1540 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub MEMBER mBlub)
1541 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub2 MEMBER mBlub READ blub)
1542 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub3 MEMBER mBlub WRITE setBlub)
1543 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub4 MEMBER mBlub NOTIFY blub4Changed)
1544 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub5 MEMBER mBlub NOTIFY blub5Changed)
1545 Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub6 MEMBER mConst CONSTANT)
1546 class MyDPointer {
1547 public:
1548 MyDPointer() : mConst("const"), mBar(0), mPlop(0) {}
1549 int bar() { return mBar ; }
1550 void setBar(int value) { mBar = value; }
1551 int plop() { return mPlop ; }
1552 void setPlop(int value) { mPlop = value; }
1553 int baz() { return mBaz ; }
1554 void setBaz(int value) { mBaz = value; }
1555 QString blub() const { return mBlub; }
1556 void setBlub(const QString &value) { mBlub = value; }
1557 QString mBlub;
1558 const QString mConst;
1559 private:
1560 int mBar;
1561 int mPlop;
1562 int mBaz;
1563 };
1564public:
1565 PrivatePropertyTest(QObject *parent = 0) : QObject(parent), mFoo(0), d (new MyDPointer) {}
1566 int foo() { return mFoo ; }
1567 void setFoo(int value) { mFoo = value; }
1568 MyDPointer *d_func() {return d.data();}
1569signals:
1570 void blub4Changed();
1571 void blub5Changed(const QString &newBlub);
1572private:
1573 int mFoo;
1574 QScopedPointer<MyDPointer> d;
1575};
1576
1577
1578void tst_Moc::qprivateproperties()
1579{
1580 PrivatePropertyTest test;
1581
1582 test.setProperty(name: "foo", value: 1);
1583 QCOMPARE(test.property("foo"), QVariant::fromValue(1));
1584
1585 test.setProperty(name: "bar", value: 2);
1586 QCOMPARE(test.property("bar"), QVariant::fromValue(2));
1587
1588 test.setProperty(name: "plop", value: 3);
1589 QCOMPARE(test.property("plop"), QVariant::fromValue(3));
1590
1591 test.setProperty(name: "baz", value: 4);
1592 QCOMPARE(test.property("baz"), QVariant::fromValue(4));
1593
1594}
1595
1596#include "task189996.h"
1597
1598void InlineSlotsWithThrowDeclaration::c() throw() {}
1599
1600void tst_Moc::inlineSlotsWithThrowDeclaration()
1601{
1602 InlineSlotsWithThrowDeclaration tst;
1603 const QMetaObject *mobj = tst.metaObject();
1604 QVERIFY(mobj->indexOfSlot("a()") != -1);
1605 QVERIFY(mobj->indexOfSlot("b()") != -1);
1606 QVERIFY(mobj->indexOfSlot("c()") != -1);
1607 QVERIFY(mobj->indexOfSlot("d()") != -1);
1608 QVERIFY(mobj->indexOfSlot("e()") != -1);
1609}
1610
1611void tst_Moc::warnOnPropertyWithoutREAD()
1612{
1613#ifdef MOC_CROSS_COMPILED
1614 QSKIP("Not tested when cross-compiled");
1615#endif
1616#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1617 QProcess proc;
1618 const QString header = m_sourceDirectory + QStringLiteral("/warn-on-property-without-read.h");
1619 proc.start(program: m_moc, arguments: QStringList(header));
1620 QVERIFY(proc.waitForFinished());
1621 QCOMPARE(proc.exitCode(), 0);
1622 QByteArray mocOut = proc.readAllStandardOutput();
1623 QVERIFY(!mocOut.isEmpty());
1624 QString mocWarning = QString::fromLocal8Bit(str: proc.readAllStandardError());
1625 QCOMPARE(mocWarning, header +
1626 QString(":36: Warning: Property declaration foo has no READ accessor function or associated MEMBER variable. The property will be invalid.\n"));
1627#else
1628 QSKIP("Only tested on linux/gcc");
1629#endif
1630}
1631
1632void tst_Moc::constructors()
1633{
1634 const QMetaObject *mo = &CtorTestClass::staticMetaObject;
1635 QCOMPARE(mo->constructorCount(), 3);
1636 {
1637 QMetaMethod mm = mo->constructor(index: 0);
1638 QCOMPARE(mm.access(), QMetaMethod::Public);
1639 QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1640 QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass(QObject*)"));
1641 QCOMPARE(mm.typeName(), "");
1642 QList<QByteArray> paramNames = mm.parameterNames();
1643 QCOMPARE(paramNames.size(), 1);
1644 QCOMPARE(paramNames.at(0), QByteArray("parent"));
1645 QList<QByteArray> paramTypes = mm.parameterTypes();
1646 QCOMPARE(paramTypes.size(), 1);
1647 QCOMPARE(paramTypes.at(0), QByteArray("QObject*"));
1648 }
1649 {
1650 QMetaMethod mm = mo->constructor(index: 1);
1651 QCOMPARE(mm.access(), QMetaMethod::Public);
1652 QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1653 QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass()"));
1654 QCOMPARE(mm.typeName(), "");
1655 QCOMPARE(mm.parameterNames().size(), 0);
1656 QCOMPARE(mm.parameterTypes().size(), 0);
1657 }
1658 {
1659 QMetaMethod mm = mo->constructor(index: 2);
1660 QCOMPARE(mm.access(), QMetaMethod::Public);
1661 QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1662 QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass(QString)"));
1663 QCOMPARE(mm.typeName(), "");
1664 QList<QByteArray> paramNames = mm.parameterNames();
1665 QCOMPARE(paramNames.size(), 1);
1666 QCOMPARE(paramNames.at(0), QByteArray("str"));
1667 QList<QByteArray> paramTypes = mm.parameterTypes();
1668 QCOMPARE(paramTypes.size(), 1);
1669 QCOMPARE(paramTypes.at(0), QByteArray("QString"));
1670 }
1671
1672 QCOMPARE(mo->indexOfConstructor("CtorTestClass(QObject*)"), 0);
1673 QCOMPARE(mo->indexOfConstructor("CtorTestClass()"), 1);
1674 QCOMPARE(mo->indexOfConstructor("CtorTestClass(QString)"), 2);
1675 QCOMPARE(mo->indexOfConstructor("CtorTestClass2(QObject*)"), -1);
1676 QCOMPARE(mo->indexOfConstructor("CtorTestClass(float,float)"), -1);
1677
1678 QScopedPointer<QObject> o1(mo->newInstance());
1679 QVERIFY(o1 != 0);
1680 QCOMPARE(o1->parent(), (QObject*)0);
1681 QVERIFY(qobject_cast<CtorTestClass*>(o1.data()) != 0);
1682
1683 QObject *o2 = mo->newInstance(Q_ARG(QObject*, o1.data()));
1684 QVERIFY(o2 != 0);
1685 QCOMPARE(o2->parent(), o1.data());
1686
1687 QString str = QString::fromLatin1(str: "hello");
1688 QScopedPointer<QObject> o3(mo->newInstance(Q_ARG(QString, str)));
1689 QVERIFY(o3 != 0);
1690 QCOMPARE(qobject_cast<CtorTestClass*>(o3.data())->m_str, str);
1691
1692 {
1693 //explicit constructor
1694 QObject *o = QObject::staticMetaObject.newInstance();
1695 QVERIFY(o);
1696 delete o;
1697 }
1698}
1699
1700#include "task234909.h"
1701
1702#include "task240368.h"
1703
1704void tst_Moc::typenameWithUnsigned()
1705{
1706 TypenameWithUnsigned tst;
1707 const QMetaObject *mobj = tst.metaObject();
1708 QVERIFY(mobj->indexOfSlot("a(uint)") != -1);
1709 QVERIFY(mobj->indexOfSlot("b(uint)") != -1);
1710 QVERIFY(mobj->indexOfSlot("c(uint*)") != -1);
1711 QVERIFY(mobj->indexOfSlot("d(uint*)") != -1);
1712 QVERIFY(mobj->indexOfSlot("e(uint&)") != -1);
1713 QVERIFY(mobj->indexOfSlot("f(uint&)") != -1);
1714 QVERIFY(mobj->indexOfSlot("g(unsigned1)") != -1);
1715 QVERIFY(mobj->indexOfSlot("h(unsigned1)") != -1);
1716 QVERIFY(mobj->indexOfSlot("i(uint,unsigned1)") != -1);
1717 QVERIFY(mobj->indexOfSlot("j(unsigned1,uint)") != -1);
1718 QVERIFY(mobj->indexOfSlot("k(unsignedQImage)") != -1);
1719 QVERIFY(mobj->indexOfSlot("l(unsignedQImage)") != -1);
1720}
1721
1722void tst_Moc::warnOnVirtualSignal()
1723{
1724#ifdef MOC_CROSS_COMPILED
1725 QSKIP("Not tested when cross-compiled");
1726#endif
1727#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1728 QProcess proc;
1729 const QString header = m_sourceDirectory + QStringLiteral("/pure-virtual-signals.h");
1730 proc.start(program: m_moc, arguments: QStringList(header));
1731 QVERIFY(proc.waitForFinished());
1732 QCOMPARE(proc.exitCode(), 0);
1733 QByteArray mocOut = proc.readAllStandardOutput();
1734 QVERIFY(!mocOut.isEmpty());
1735 QString mocWarning = QString::fromLocal8Bit(str: proc.readAllStandardError());
1736 QCOMPARE(mocWarning, header + QString(":38: Warning: Signals cannot be declared virtual\n") +
1737 header + QString(":40: Warning: Signals cannot be declared virtual\n"));
1738#else
1739 QSKIP("Only tested on linux/gcc");
1740#endif
1741}
1742
1743class QTBUG5590_DummyObject: public QObject
1744{
1745 Q_OBJECT
1746 Q_PROPERTY(bool dummy)
1747};
1748
1749class QTBUG5590_PropertyObject: public QTBUG5590_DummyObject
1750{
1751 Q_OBJECT
1752 Q_PROPERTY(int value READ value WRITE setValue)
1753 Q_PROPERTY(int value2 READ value2 WRITE setValue2)
1754
1755 public:
1756 QTBUG5590_PropertyObject() : m_value(85), m_value2(40) { }
1757 int value() const { return m_value; }
1758 void setValue(int value) { m_value = value; }
1759 int value2() const { return m_value2; }
1760 void setValue2(int value) { m_value2 = value; }
1761 private:
1762 int m_value, m_value2;
1763};
1764
1765void tst_Moc::QTBUG5590_dummyProperty()
1766{
1767 QTBUG5590_PropertyObject o;
1768 QCOMPARE(o.property("value").toInt(), 85);
1769 QCOMPARE(o.property("value2").toInt(), 40);
1770 o.setProperty(name: "value", value: 32);
1771 QCOMPARE(o.value(), 32);
1772 o.setProperty(name: "value2", value: 82);
1773 QCOMPARE(o.value2(), 82);
1774}
1775
1776class QTBUG7421_ReturnConstTemplate: public QObject
1777{ Q_OBJECT
1778public slots:
1779 const QList<int> returnConstTemplate1() { return QList<int>(); }
1780 QList<int> const returnConstTemplate2() { return QList<int>(); }
1781 const int returnConstInt() { return 0; }
1782 const QString returnConstString(const QString s) { return s; }
1783 QString const returnConstString2( QString const s) { return s; }
1784};
1785
1786class QTBUG9354_constInName: public QObject
1787{ Q_OBJECT
1788public slots:
1789 void slotChooseScientificConst0(struct science_constant const &) {};
1790 void foo(struct science_const const &) {};
1791 void foo(struct constconst const &) {};
1792 void foo(struct constconst *) {};
1793 void foo(struct const_ *) {};
1794};
1795
1796
1797template<typename T1, typename T2>
1798class TestTemplate2
1799{
1800};
1801
1802class QTBUG11647_constInTemplateParameter : public QObject
1803{ Q_OBJECT
1804public slots:
1805 void testSlot(TestTemplate2<const int, const short*>) {}
1806 void testSlot2(TestTemplate2<int, short const * const >) {}
1807 void testSlot3(TestTemplate2<TestTemplate2 < const int, const short* > const *,
1808 TestTemplate2< TestTemplate2 < void, int > , unsigned char *> > ) {}
1809
1810signals:
1811 void testSignal(TestTemplate2<const int, const short*>);
1812};
1813
1814class QTBUG12260_defaultTemplate_Object : public QObject
1815{ Q_OBJECT
1816public slots:
1817#if !(defined(Q_CC_GNU) && __GNUC__ == 4 && __GNUC_MINOR__ <= 3) || defined(Q_MOC_RUN)
1818 void doSomething(QHash<QString, QVariant> values = QHash<QString, QVariant>() ) { Q_UNUSED(values); }
1819 void doSomethingElse(QSharedPointer<QVarLengthArray<QString, (16 >> 2)> > val
1820 = QSharedPointer<QVarLengthArray<QString, (16 >> 2)> >() )
1821 { Q_UNUSED(val); }
1822#else
1823 // we want to test the previous function, but gcc < 4.4 seemed to have a bug similar to the one moc has.
1824 typedef QHash<QString, QVariant> WorkaroundGCCBug;
1825 void doSomething(QHash<QString, QVariant> values = WorkaroundGCCBug() ) { Q_UNUSED(values); }
1826 void doSomethingElse(QSharedPointer<QVarLengthArray<QString, (16 >> 2)> > val
1827 = (QSharedPointer<QVarLengthArray<QString, (16 >> 2)> >()) )
1828 { Q_UNUSED(val); }
1829#endif
1830
1831 void doAnotherThing(bool a = (1 < 3), bool b = (1 > 4)) { Q_UNUSED(a); Q_UNUSED(b); }
1832
1833#if defined(Q_MOC_RUN) || (defined(Q_COMPILER_AUTO_TYPE) && !(defined(Q_CC_CLANG) && Q_CC_CLANG < 304))
1834 // There is no Q_COMPILER_>> but if compiler support auto, it should also support >>
1835 void performSomething(QVector<QList<QString>> e = QVector<QList<QString>>(8 < 1),
1836 QHash<int, QVector<QString>> h = QHash<int, QVector<QString>>())
1837 { Q_UNUSED(e); Q_UNUSED(h); }
1838#else
1839 void performSomething(QVector<QList<QString> > e = QVector<QList<QString> >(),
1840 QHash<int, QVector<QString> > h = (QHash<int, QVector<QString> >()))
1841 { Q_UNUSED(e); Q_UNUSED(h); }
1842#endif
1843};
1844
1845
1846void tst_Moc::QTBUG12260_defaultTemplate()
1847{
1848 QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomething(QHash<QString,QVariant>)") != -1);
1849 QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doAnotherThing(bool,bool)") != -1);
1850 QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomethingElse(QSharedPointer<QVarLengthArray<QString,(16>>2)> >)") != -1);
1851 QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("performSomething(QVector<QList<QString> >,QHash<int,QVector<QString> >)") != -1);
1852}
1853
1854void tst_Moc::notifyError()
1855{
1856#ifdef MOC_CROSS_COMPILED
1857 QSKIP("Not tested when cross-compiled");
1858#endif
1859#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
1860 QProcess proc;
1861 const QString header = m_sourceDirectory + QStringLiteral("/error-on-wrong-notify.h");
1862 proc.start(program: m_moc, arguments: QStringList(header));
1863 QVERIFY(proc.waitForFinished());
1864 QCOMPARE(proc.exitCode(), 0);
1865 QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
1866 QByteArray mocOut = proc.readAllStandardOutput();
1867 QVERIFY(!mocOut.isEmpty());
1868 QCOMPARE(proc.readAllStandardError(), QByteArray());
1869
1870 QStringList args;
1871 args << "-c" << "-x" << "c++" << "-I" << "."
1872 << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-";
1873 proc.start(program: "gcc", arguments: args);
1874 QVERIFY(proc.waitForStarted());
1875 proc.write(data: mocOut);
1876 proc.closeWriteChannel();
1877
1878 QVERIFY(proc.waitForFinished());
1879 QCOMPARE(proc.exitCode(), 1);
1880 const QString gccOutput = QString::fromLocal8Bit(str: proc.readAllStandardError());
1881 QVERIFY(gccOutput.contains(QLatin1String("error")));
1882 QVERIFY(gccOutput.contains(QLatin1String("fooChanged")));
1883#else
1884 QSKIP("Only tested on linux/gcc");
1885#endif
1886}
1887
1888class QTBUG_17635_InvokableAndProperty : public QObject
1889{
1890 Q_OBJECT
1891public:
1892 Q_PROPERTY(int numberOfEggs READ numberOfEggs)
1893 Q_PROPERTY(int numberOfChickens READ numberOfChickens)
1894 Q_INVOKABLE QString getEgg(int index) { Q_UNUSED(index); return QString::fromLatin1(str: "Egg"); }
1895 Q_INVOKABLE QString getChicken(int index) { Q_UNUSED(index); return QString::fromLatin1(str: "Chicken"); }
1896 int numberOfEggs() { return 2; }
1897 int numberOfChickens() { return 4; }
1898};
1899
1900void tst_Moc::QTBUG17635_invokableAndProperty()
1901{
1902 //Moc used to fail parsing Q_INVOKABLE if they were dirrectly following a Q_PROPERTY;
1903 QTBUG_17635_InvokableAndProperty mc;
1904 QString val;
1905 QMetaObject::invokeMethod(obj: &mc, member: "getEgg", Q_RETURN_ARG(QString, val), Q_ARG(int, 10));
1906 QCOMPARE(val, QString::fromLatin1("Egg"));
1907 QMetaObject::invokeMethod(obj: &mc, member: "getChicken", Q_RETURN_ARG(QString, val), Q_ARG(int, 10));
1908 QCOMPARE(val, QString::fromLatin1("Chicken"));
1909 QVERIFY(mc.metaObject()->indexOfProperty("numberOfEggs") != -1);
1910 QVERIFY(mc.metaObject()->indexOfProperty("numberOfChickens") != -1);
1911}
1912
1913// If changed, update VersionTestNotify below
1914class VersionTest : public QObject
1915{
1916 Q_OBJECT
1917 Q_PROPERTY(int prop1 READ foo)
1918 Q_PROPERTY(int prop2 READ foo REVISION 2)
1919
1920public:
1921 int foo() const { return 0; }
1922
1923 Q_INVOKABLE void method1() {}
1924 Q_INVOKABLE Q_REVISION(4) void method2() {}
1925
1926 enum TestEnum { One, Two };
1927 Q_ENUM(TestEnum);
1928
1929
1930public slots:
1931 void slot1() {}
1932 Q_REVISION(3) void slot2() {}
1933
1934signals:
1935 void signal1();
1936 Q_REVISION(5) void signal2();
1937
1938public slots Q_REVISION(6):
1939 void slot3() {}
1940 void slot4() {}
1941
1942signals Q_REVISION(7):
1943 void signal3();
1944 void signal4();
1945};
1946
1947// If changed, update VersionTest above
1948class VersionTestNotify : public QObject
1949{
1950 Q_OBJECT
1951 Q_PROPERTY(int prop1 READ foo NOTIFY fooChanged)
1952 Q_PROPERTY(int prop2 READ foo REVISION 2)
1953
1954public:
1955 int foo() const { return 0; }
1956
1957 Q_INVOKABLE void method1() {}
1958 Q_INVOKABLE Q_REVISION(4) void method2() {}
1959
1960 enum TestEnum { One, Two };
1961 Q_ENUM(TestEnum);
1962
1963public slots:
1964 void slot1() {}
1965 Q_REVISION(3) void slot2() {}
1966
1967signals:
1968 void fooChanged();
1969 void signal1();
1970 Q_REVISION(5) void signal2();
1971
1972public slots Q_REVISION(6):
1973 void slot3() {}
1974 void slot4() {}
1975
1976signals Q_REVISION(7):
1977 void signal3();
1978 void signal4();
1979};
1980
1981template <class T>
1982void tst_Moc::revisions_T()
1983{
1984 int idx = T::staticMetaObject.indexOfProperty("prop1");
1985 QCOMPARE(T::staticMetaObject.property(idx).revision(), 0);
1986 idx = T::staticMetaObject.indexOfProperty("prop2");
1987 QCOMPARE(T::staticMetaObject.property(idx).revision(), 2);
1988
1989 idx = T::staticMetaObject.indexOfMethod("method1()");
1990 QCOMPARE(T::staticMetaObject.method(idx).revision(), 0);
1991 idx = T::staticMetaObject.indexOfMethod("method2()");
1992 QCOMPARE(T::staticMetaObject.method(idx).revision(), 4);
1993
1994 idx = T::staticMetaObject.indexOfSlot("slot1()");
1995 QCOMPARE(T::staticMetaObject.method(idx).revision(), 0);
1996 idx = T::staticMetaObject.indexOfSlot("slot2()");
1997 QCOMPARE(T::staticMetaObject.method(idx).revision(), 3);
1998
1999 idx = T::staticMetaObject.indexOfSlot("slot3()");
2000 QCOMPARE(T::staticMetaObject.method(idx).revision(), 6);
2001 idx = T::staticMetaObject.indexOfSlot("slot4()");
2002 QCOMPARE(T::staticMetaObject.method(idx).revision(), 6);
2003
2004 idx = T::staticMetaObject.indexOfSignal("signal1()");
2005 QCOMPARE(T::staticMetaObject.method(idx).revision(), 0);
2006 idx = T::staticMetaObject.indexOfSignal("signal2()");
2007 QCOMPARE(T::staticMetaObject.method(idx).revision(), 5);
2008
2009 idx = T::staticMetaObject.indexOfSignal("signal3()");
2010 QCOMPARE(T::staticMetaObject.method(idx).revision(), 7);
2011 idx = T::staticMetaObject.indexOfSignal("signal4()");
2012 QCOMPARE(T::staticMetaObject.method(idx).revision(), 7);
2013
2014 idx = T::staticMetaObject.indexOfEnumerator("TestEnum");
2015 QCOMPARE(T::staticMetaObject.enumerator(idx).keyCount(), 2);
2016 QCOMPARE(T::staticMetaObject.enumerator(idx).key(0), "One");
2017}
2018
2019// test using both class that has properties with and without NOTIFY signals
2020void tst_Moc::revisions()
2021{
2022 revisions_T<VersionTest>();
2023 revisions_T<VersionTestNotify>();
2024}
2025
2026void tst_Moc::warnings_data()
2027{
2028 QTest::addColumn<QByteArray>(name: "input");
2029 QTest::addColumn<QStringList>(name: "args");
2030 QTest::addColumn<int>(name: "exitCode");
2031 QTest::addColumn<QString>(name: "expectedStdOut");
2032 QTest::addColumn<QString>(name: "expectedStdErr");
2033
2034 // empty input should result in "no relevant classes" note
2035 QTest::newRow(dataTag: "No relevant classes")
2036 << QByteArray(" ")
2037 << QStringList()
2038 << 0
2039 << QString()
2040 << QString("standard input:0: Note: No relevant classes found. No output generated.");
2041
2042 // passing "-nn" should suppress "no relevant classes" note
2043 QTest::newRow(dataTag: "-nn")
2044 << QByteArray(" ")
2045 << (QStringList() << "-nn")
2046 << 0
2047 << QString()
2048 << QString();
2049
2050 // passing "-nw" should also suppress "no relevant classes" note
2051 QTest::newRow(dataTag: "-nw")
2052 << QByteArray(" ")
2053 << (QStringList() << "-nw")
2054 << 0
2055 << QString()
2056 << QString();
2057
2058 // This should output a warning
2059 QTest::newRow(dataTag: "Invalid property warning")
2060 << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };")
2061 << QStringList()
2062 << 0
2063 << QString("IGNORE_ALL_STDOUT")
2064 << QString("standard input:1: Warning: Property declaration x has no READ accessor function or associated MEMBER variable. The property will be invalid.");
2065
2066 // This should output a warning
2067 QTest::newRow(dataTag: "Duplicate property warning")
2068 << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x READ x) Q_PROPERTY(int x READ y) };")
2069 << QStringList()
2070 << 0
2071 << QString("IGNORE_ALL_STDOUT")
2072 << QString("standard input:1: Warning: The property 'x' is defined multiple times in class X.");
2073
2074 // Passing "-nn" should NOT suppress the warning
2075 QTest::newRow(dataTag: "Invalid property warning with -nn")
2076 << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };")
2077 << (QStringList() << "-nn")
2078 << 0
2079 << QString("IGNORE_ALL_STDOUT")
2080 << QString("standard input:1: Warning: Property declaration x has no READ accessor function or associated MEMBER variable. The property will be invalid.");
2081
2082 // Passing "-nw" should suppress the warning
2083 QTest::newRow(dataTag: "Invalid property warning with -nw")
2084 << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };")
2085 << (QStringList() << "-nw")
2086 << 0
2087 << QString("IGNORE_ALL_STDOUT")
2088 << QString();
2089
2090 // This should output an error
2091 QTest::newRow(dataTag: "Does not inherit QObject")
2092 << QByteArray("class X { Q_OBJECT };")
2093 << QStringList()
2094 << 1
2095 << QString()
2096 << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject");
2097
2098 // "-nn" should not suppress the error
2099 QTest::newRow(dataTag: "Does not inherit QObject with -nn")
2100 << QByteArray("class X { Q_OBJECT };")
2101 << (QStringList() << "-nn")
2102 << 1
2103 << QString()
2104 << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject");
2105
2106 // "-nw" should not suppress the error
2107 QTest::newRow(dataTag: "Does not inherit QObject with -nw")
2108 << QByteArray("class X { Q_OBJECT };")
2109 << (QStringList() << "-nw")
2110 << 1
2111 << QString()
2112 << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject");
2113
2114 QTest::newRow(dataTag: "Warning on invalid macro")
2115 << QByteArray("#define Foo(a, b)\n class X : public QObject { Q_OBJECT }; \n Foo(a) \n Foo(a,b,c) \n")
2116 << QStringList()
2117 << 0
2118 << QString("IGNORE_ALL_STDOUT")
2119 << QString();
2120
2121 QTest::newRow(dataTag: "Class declaration lacks Q_OBJECT macro.")
2122 << QByteArray("class X : public QObject \n { \n public slots: \n void foo() {} \n };")
2123 << QStringList()
2124 << 1
2125 << QString()
2126 << QString("standard input:5: Error: Class declaration lacks Q_OBJECT macro.");
2127
2128 QTest::newRow(dataTag: "Namespace declaration lacks Q_NAMESPACE macro.")
2129 << QByteArray("namespace X {\nQ_CLASSINFO(\"key\",\"value\")\nenum class MyEnum {Key1 = 1}\nQ_ENUMS(MyEnum)\n}\n")
2130 << QStringList()
2131 << 1
2132 << QString()
2133 << QString("standard input:1: Error: Namespace declaration lacks Q_NAMESPACE macro.");
2134
2135 QTest::newRow(dataTag: "Wrong Q_ENUM context.")
2136 << QByteArray("namespace X {\nQ_NAMESPACE\n\nenum class MyEnum {Key1 = 1}\nQ_ENUM(MyEnum)\n}\n")
2137 << QStringList()
2138 << 1
2139 << QString()
2140 << QString("standard input:5: Error: Q_ENUM can't be used in a Q_NAMESPACE, use Q_ENUM_NS instead");
2141
2142 QTest::newRow(dataTag: "Wrong Q_FLAG context.")
2143 << QByteArray("namespace X {\nQ_NAMESPACE\n\nenum class MyEnum {Key1 = 1}\nQ_FLAG(MyEnum)\n}\n")
2144 << QStringList()
2145 << 1
2146 << QString()
2147 << QString("standard input:5: Error: Q_FLAG can't be used in a Q_NAMESPACE, use Q_FLAG_NS instead");
2148
2149 QTest::newRow(dataTag: "Wrong Q_ENUM_NS context.")
2150 << QByteArray("class X {\nQ_GADGET\n\nenum class MyEnum {Key1 = 1}\nQ_ENUM_NS(MyEnum)\n};\n")
2151 << QStringList()
2152 << 1
2153 << QString()
2154 << QString("standard input:5: Error: Q_ENUM_NS can't be used in a Q_OBJECT/Q_GADGET, use Q_ENUM instead");
2155
2156 QTest::newRow(dataTag: "Wrong Q_FLAG_NS context.")
2157 << QByteArray("class X {\nQ_GADGET\n\nenum class MyEnum {Key1 = 1}\nQ_FLAG_NS(MyEnum)\n};\n")
2158 << QStringList()
2159 << 1
2160 << QString()
2161 << QString("standard input:5: Error: Q_FLAG_NS can't be used in a Q_OBJECT/Q_GADGET, use Q_FLAG instead");
2162
2163 QTest::newRow(dataTag: "Invalid macro definition")
2164 << QByteArray("#define Foo(a, b, c) a b c #a #b #c a##b##c #d\n Foo(45, 42, 39);")
2165 << QStringList()
2166 << 1
2167 << QString("IGNORE_ALL_STDOUT")
2168 << QString(":2: Error: '#' is not followed by a macro parameter");
2169
2170 QTest::newRow(dataTag: "QTBUG-46210: crash on invalid macro invocation")
2171 << QByteArray("#define Foo(a, b, c) a b c #a #b #c a##b##c\n Foo(45);")
2172 << QStringList()
2173 << 1
2174 << QString("IGNORE_ALL_STDOUT")
2175 << QString(":2: Error: Macro invoked with too few parameters for a use of '#'");
2176
2177 QTest::newRow(dataTag: "QTBUG-54609: crash on invalid input")
2178 << QByteArray::fromBase64(base64: "EAkJCQkJbGFzcyBjbGFzcyBiYWkcV2kgTUEKcGYjZGVmaW5lIE1BKFEs/4D/FoQ=")
2179 << QStringList()
2180 << 1
2181 << QString("IGNORE_ALL_STDOUT")
2182 << QString(":-1: Error: Unexpected character in macro argument list.");
2183
2184 QTest::newRow(dataTag: "Missing header warning")
2185 << QByteArray("class X : public QObject { Q_OBJECT };")
2186 << (QStringList() << QStringLiteral("--include") << QStringLiteral("doesnotexist.h"))
2187 << 0
2188 << QString("IGNORE_ALL_STDOUT")
2189 << QStringLiteral("Warning: Failed to resolve include \"doesnotexist.h\" for moc file <standard input>");
2190
2191 QTest::newRow(dataTag: "QTBUG-54815: Crash on invalid input")
2192 << QByteArray("class M{(})F<{}d000000000000000#0")
2193 << QStringList()
2194 << 0
2195 << QString()
2196 << QString("standard input:1: Note: No relevant classes found. No output generated.");
2197
2198 QTest::newRow(dataTag: "Q_PLUGIN_METADATA: invalid file")
2199 << QByteArray("class X { \n Q_PLUGIN_METADATA(FILE \"does.not.exists\") \n };")
2200 << QStringList()
2201 << 1
2202 << QString()
2203 << QString("standard input:2: Error: Plugin Metadata file \"does.not.exists\" does not exist. Declaration will be ignored");
2204
2205 QTest::newRow(dataTag: "Auto-declared, missing trailing return")
2206 << QByteArray("class X { \n public slots: \n auto fun() { return 1; } };")
2207 << QStringList()
2208 << 1
2209 << QString()
2210 << QString("standard input:3: Error: Function declared with auto as return type but missing trailing return type. Return type deduction is not supported.");
2211
2212 QTest::newRow(dataTag: "Auto-declared, volatile auto as trailing return type")
2213 << QByteArray("class X { \n public slots: \n auto fun() -> volatile auto { return 1; } };")
2214 << QStringList()
2215 << 1
2216 << QString()
2217 << QString("standard input:3: Error: Function declared with auto as return type but missing trailing return type. Return type deduction is not supported.");
2218
2219 // We don't currently support the decltype keyword, so it's not the same error as above.
2220 // The test is just here to make sure this keeps generating an error until return type deduction
2221 // is supported.
2222 QTest::newRow(dataTag: "Auto-declared, decltype in trailing return type")
2223 << QByteArray("class X { \n public slots: \n auto fun() -> decltype(0+1) { return 1; } };")
2224 << QStringList()
2225 << 1
2226 << QString()
2227 << QString("standard input:3: Parse error at \"decltype\"");
2228
2229#ifdef Q_OS_LINUX // Limit to Linux because the error message is platform-dependent
2230 QTest::newRow(dataTag: "Q_PLUGIN_METADATA: unreadable file")
2231 << QByteArray("class X { \n Q_PLUGIN_METADATA(FILE \".\") \n };")
2232 << QStringList()
2233 << 1
2234 << QString()
2235 << QString("standard input:2: Error: Plugin Metadata file \".\" could not be opened: file to open is a directory");
2236#endif
2237}
2238
2239void tst_Moc::warnings()
2240{
2241#ifdef MOC_CROSS_COMPILED
2242 QSKIP("Not tested when cross-compiled");
2243#endif
2244 QFETCH(QByteArray, input);
2245 QFETCH(QStringList, args);
2246 QFETCH(int, exitCode);
2247 QFETCH(QString, expectedStdOut);
2248 QFETCH(QString, expectedStdErr);
2249
2250#ifdef Q_CC_MSVC
2251 // for some reasons, moc compiled with MSVC uses a different output format
2252 QRegExp lineNumberRe(":(-?\\d+):");
2253 lineNumberRe.setMinimal(true);
2254 expectedStdErr.replace(lineNumberRe, "(\\1):");
2255#endif
2256
2257#if QT_CONFIG(process)
2258 QProcess proc;
2259
2260 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2261 env.insert(name: "QT_MESSAGE_PATTERN", value: "no qDebug or qWarning please");
2262 proc.setProcessEnvironment(env);
2263
2264 proc.start(program: m_moc, arguments: args);
2265 QVERIFY(proc.waitForStarted());
2266
2267 QCOMPARE(proc.write(input), qint64(input.size()));
2268
2269 proc.closeWriteChannel();
2270
2271 QVERIFY(proc.waitForFinished());
2272
2273 QCOMPARE(proc.exitCode(), exitCode);
2274 QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
2275
2276 // magic value "IGNORE_ALL_STDOUT" ignores stdout
2277 if (expectedStdOut != "IGNORE_ALL_STDOUT")
2278 QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardOutput()).trimmed(), expectedStdOut);
2279 QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()).trimmed().remove('\r'), expectedStdErr);
2280#else
2281 QSKIP("Only tested if QProcess is available");
2282#endif
2283}
2284
2285class tst_Moc::PrivateClass : public QObject {
2286 Q_PROPERTY(int someProperty READ someSlot WRITE someSlot2)
2287Q_OBJECT
2288Q_SIGNALS:
2289 void someSignal();
2290public Q_SLOTS:
2291 int someSlot() { return 1; }
2292 void someSlot2(int) {}
2293public:
2294 Q_INVOKABLE PrivateClass() {}
2295};
2296
2297void tst_Moc::privateClass()
2298{
2299 QCOMPARE(PrivateClass::staticMetaObject.indexOfConstructor("PrivateClass()"), 0);
2300 QVERIFY(PrivateClass::staticMetaObject.indexOfSignal("someSignal()") > 0);
2301}
2302
2303void tst_Moc::cxx11Enums_data()
2304{
2305 QTest::addColumn<const QMetaObject *>(name: "meta");
2306 QTest::addColumn<QByteArray>(name: "typeName");
2307 QTest::addColumn<QByteArray>(name: "enumName");
2308 QTest::addColumn<char>(name: "prefix");
2309 QTest::addColumn<bool>(name: "isScoped");
2310
2311 const QMetaObject *meta1 = &CXX11Enums::staticMetaObject;
2312 const QMetaObject *meta2 = &CXX11Enums2::staticMetaObject;
2313
2314 QTest::newRow(dataTag: "EnumClass") << meta1 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
2315 QTest::newRow(dataTag: "EnumClass 2") << meta2 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
2316 QTest::newRow(dataTag: "TypedEnum") << meta1 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
2317 QTest::newRow(dataTag: "TypedEnum 2") << meta2 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
2318 QTest::newRow(dataTag: "TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
2319 QTest::newRow(dataTag: "TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
2320 QTest::newRow(dataTag: "NormalEnum") << meta1 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
2321 QTest::newRow(dataTag: "NormalEnum 2") << meta2 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
2322 QTest::newRow(dataTag: "ClassFlags") << meta1 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
2323 QTest::newRow(dataTag: "ClassFlags 2") << meta2 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
2324 QTest::newRow(dataTag: "EnumStruct") << meta1 << QByteArray("EnumStruct") << QByteArray("EnumStruct") << 'G' << true;
2325 QTest::newRow(dataTag: "TypedEnumStruct") << meta1 << QByteArray("TypedEnumStruct") << QByteArray("TypedEnumStruct") << 'H' << true;
2326 QTest::newRow(dataTag: "StructFlags") << meta1 << QByteArray("StructFlags") << QByteArray("StructFlag") << 'I' << true;
2327}
2328
2329void tst_Moc::cxx11Enums()
2330{
2331 QFETCH(const QMetaObject *,meta);
2332 QCOMPARE(meta->enumeratorOffset(), 0);
2333
2334 QFETCH(QByteArray, typeName);
2335 QFETCH(QByteArray, enumName);
2336 QFETCH(char, prefix);
2337 QFETCH(bool, isScoped);
2338
2339 int idx = meta->indexOfEnumerator(name: typeName);
2340 QVERIFY(idx != -1);
2341 QCOMPARE(meta->indexOfEnumerator(enumName), idx);
2342
2343 QCOMPARE(meta->enumerator(idx).enclosingMetaObject(), meta);
2344 QCOMPARE(meta->enumerator(idx).isValid(), true);
2345 QCOMPARE(meta->enumerator(idx).keyCount(), 4);
2346 QCOMPARE(meta->enumerator(idx).name(), typeName.constData());
2347 QCOMPARE(meta->enumerator(idx).enumName(), enumName.constData());
2348 bool isFlag = meta->enumerator(index: idx).isFlag();
2349 for (int i = 0; i < 4; i++) {
2350 QByteArray v = prefix + QByteArray::number(i);
2351 const int value = isFlag ? (1 << i) : i;
2352 QCOMPARE(meta->enumerator(idx).keyToValue(v), value);
2353 QCOMPARE(meta->enumerator(idx).valueToKey(value), v.constData());
2354 }
2355 QCOMPARE(meta->enumerator(idx).isScoped(), isScoped);
2356}
2357
2358void tst_Moc::cxx11TrailingReturn()
2359{
2360 CXX11TrailingReturn retClass;
2361 const QMetaObject *mobj = retClass.metaObject();
2362 QVERIFY(mobj->indexOfSlot("fun()") != -1);
2363 QVERIFY(mobj->indexOfSlot("arguments(int,char)") != -1);
2364 QVERIFY(mobj->indexOfSlot("inlineFunc(int)") != -1);
2365 QVERIFY(mobj->indexOfSlot("constRefReturn()") != -1);
2366 QVERIFY(mobj->indexOfSlot("constConstRefReturn()") != -1);
2367 QVERIFY(mobj->indexOfSignal("trailingSignalReturn(int)") != -1);
2368}
2369
2370void tst_Moc::returnRefs()
2371{
2372 TestClass tst;
2373 const QMetaObject *mobj = tst.metaObject();
2374 QVERIFY(mobj->indexOfMethod("myInvokableReturningRef()") != -1);
2375 QVERIFY(mobj->indexOfMethod("myInvokableReturningConstRef()") != -1);
2376 // Those two functions are copied from the qscriptextqobject test in qtscript
2377 // they used to cause miscompilation of the moc generated file.
2378}
2379
2380void tst_Moc::memberProperties_data()
2381{
2382 QTest::addColumn<int>(name: "object");
2383 QTest::addColumn<QString>(name: "property");
2384 QTest::addColumn<QString>(name: "signal");
2385 QTest::addColumn<QString>(name: "writeValue");
2386 QTest::addColumn<bool>(name: "expectedWriteResult");
2387 QTest::addColumn<QString>(name: "expectedReadResult");
2388
2389 pPPTest = new PrivatePropertyTest( this );
2390
2391 QTest::newRow(dataTag: "MEMBER property")
2392 << 0 << "member1" << "" << "abc" << true << "abc";
2393 QTest::newRow(dataTag: "MEMBER property with READ function")
2394 << 0 << "member2" << "" << "def" << true << "def";
2395 QTest::newRow(dataTag: "MEMBER property with WRITE function")
2396 << 0 << "member3" << "" << "ghi" << true << "ghi";
2397 QTest::newRow(dataTag: "MEMBER property with NOTIFY")
2398 << 0 << "member4" << "member4Changed()" << "lmn" << true << "lmn";
2399 QTest::newRow(dataTag: "MEMBER property with NOTIFY(value)")
2400 << 0 << "member5" << "member5Changed(const QString&)" << "opq" << true << "opq";
2401 QTest::newRow(dataTag: "MEMBER property with CONSTANT")
2402 << 0 << "member6" << "" << "test" << false << "const";
2403 QTest::newRow(dataTag: "private MEMBER property")
2404 << 1 << "blub" << "" << "abc" << true << "abc";
2405 QTest::newRow(dataTag: "private MEMBER property with READ function")
2406 << 1 << "blub2" << "" << "def" << true << "def";
2407 QTest::newRow(dataTag: "private MEMBER property with WRITE function")
2408 << 1 << "blub3" << "" << "ghi" << true << "ghi";
2409 QTest::newRow(dataTag: "private MEMBER property with NOTIFY")
2410 << 1 << "blub4" << "blub4Changed()" << "jkl" << true << "jkl";
2411 QTest::newRow(dataTag: "private MEMBER property with NOTIFY(value)")
2412 << 1 << "blub5" << "blub5Changed(const QString&)" << "mno" << true << "mno";
2413 QTest::newRow(dataTag: "private MEMBER property with CONSTANT")
2414 << 1 << "blub6" << "" << "test" << false << "const";
2415 QTest::newRow(dataTag: "sub1")
2416 << 0 << "sub1" << "" << "helloSub1" << true << "helloSub1";
2417 QTest::newRow(dataTag: "sub2")
2418 << 0 << "sub2" << "" << "helloSub2" << true << "helloSub2";
2419}
2420
2421void tst_Moc::memberProperties()
2422{
2423 QFETCH(int, object);
2424 QFETCH(QString, property);
2425 QFETCH(QString, signal);
2426 QFETCH(QString, writeValue);
2427 QFETCH(bool, expectedWriteResult);
2428 QFETCH(QString, expectedReadResult);
2429
2430 QObject *pObj = (object == 0) ? this : static_cast<QObject*>(pPPTest);
2431
2432 QString sSignalDeclaration;
2433 if (!signal.isEmpty())
2434 sSignalDeclaration = QString(SIGNAL(%1)).arg(a: signal);
2435 else
2436 QTest::ignoreMessage(type: QtWarningMsg, message: "QSignalSpy: Not a valid signal, use the SIGNAL macro");
2437 QSignalSpy notifySpy(pObj, sSignalDeclaration.toLatin1().constData());
2438
2439 int index = pObj->metaObject()->indexOfProperty(name: property.toLatin1().constData());
2440 QVERIFY(index != -1);
2441 QMetaProperty prop = pObj->metaObject()->property(index);
2442
2443 QCOMPARE(prop.write(pObj, writeValue), expectedWriteResult);
2444
2445 QVariant readValue = prop.read(obj: pObj);
2446 QCOMPARE(readValue.toString(), expectedReadResult);
2447
2448 if (!signal.isEmpty())
2449 {
2450 QCOMPARE(notifySpy.count(), 1);
2451 if (prop.notifySignal().parameterNames().size() > 0) {
2452 QList<QVariant> arguments = notifySpy.takeFirst();
2453 QCOMPARE(arguments.size(), 1);
2454 QCOMPARE(arguments.at(0).toString(), expectedReadResult);
2455 }
2456
2457 notifySpy.clear();
2458 // a second write with the same value should not cause the signal to be emitted again
2459 QCOMPARE(prop.write(pObj, writeValue), expectedWriteResult);
2460 QCOMPARE(notifySpy.count(), 0);
2461 }
2462}
2463
2464//this used to fail to compile
2465class ClassWithOneMember : public QObject {
2466 Q_PROPERTY(int member MEMBER member)
2467 Q_OBJECT
2468public:
2469 int member;
2470};
2471
2472void tst_Moc::memberProperties2()
2473{
2474 ClassWithOneMember o;
2475 o.member = 442;
2476 QCOMPARE(o.property("member").toInt(), 442);
2477 QVERIFY(o.setProperty("member", 6666));
2478 QCOMPARE(o.member, 6666);
2479}
2480
2481class SignalConnectionTester : public QObject
2482{
2483 Q_OBJECT
2484public:
2485 SignalConnectionTester(QObject *parent = 0)
2486 : QObject(parent), testPassed(false)
2487 {
2488
2489 }
2490
2491public Q_SLOTS:
2492 void testSlot()
2493 {
2494 testPassed = true;
2495 }
2496 void testSlotWith1Arg(int i)
2497 {
2498 testPassed = i == 42;
2499 }
2500 void testSlotWith2Args(int i, const QString &s)
2501 {
2502 testPassed = i == 42 && s == "Hello";
2503 }
2504
2505public:
2506 bool testPassed;
2507};
2508
2509class ClassWithPrivateSignals : public QObject
2510{
2511 Q_OBJECT
2512public:
2513 ClassWithPrivateSignals(QObject *parent = 0)
2514 : QObject(parent)
2515 {
2516
2517 }
2518
2519 void emitPrivateSignals()
2520 {
2521 emit privateSignal1(QPrivateSignal());
2522 emit privateSignalWith1Arg(arg1: 42, QPrivateSignal());
2523 emit privateSignalWith2Args(arg1: 42, arg2: "Hello", QPrivateSignal());
2524
2525 emit privateOverloadedSignal(QPrivateSignal());
2526 emit privateOverloadedSignal(42, QPrivateSignal());
2527
2528 emit overloadedMaybePrivate();
2529 emit overloadedMaybePrivate(42, QPrivateSignal());
2530 }
2531
2532Q_SIGNALS:
2533 void privateSignal1(QPrivateSignal);
2534 void privateSignalWith1Arg(int arg1, QPrivateSignal);
2535 void privateSignalWith2Args(int arg1, const QString &arg2, QPrivateSignal);
2536
2537 void privateOverloadedSignal(QPrivateSignal);
2538 void privateOverloadedSignal(int, QPrivateSignal);
2539
2540 void overloadedMaybePrivate();
2541 void overloadedMaybePrivate(int, QPrivateSignal);
2542
2543};
2544
2545class SubClassFromPrivateSignals : public ClassWithPrivateSignals
2546{
2547 Q_OBJECT
2548public:
2549 SubClassFromPrivateSignals(QObject *parent = 0)
2550 : ClassWithPrivateSignals(parent)
2551 {
2552
2553 }
2554
2555 void emitProtectedSignals()
2556 {
2557 // Compile test: All of this intentionally does not compile:
2558// emit privateSignal1();
2559// emit privateSignalWith1Arg(42);
2560// emit privateSignalWith2Args(42, "Hello");
2561//
2562// emit privateSignal1(QPrivateSignal());
2563// emit privateSignalWith1Arg(42, QPrivateSignal());
2564// emit privateSignalWith2Args(42, "Hello", QPrivateSignal());
2565//
2566// emit privateSignal1(ClassWithPrivateSignals::QPrivateSignal());
2567// emit privateSignalWith1Arg(42, ClassWithPrivateSignals::QPrivateSignal());
2568// emit privateSignalWith2Args(42, "Hello", ClassWithPrivateSignals::QPrivateSignal());
2569
2570// emit privateOverloadedSignal();
2571// emit privateOverloadedSignal(42);
2572
2573// emit overloadedMaybePrivate();
2574// emit overloadedMaybePrivate(42);
2575
2576
2577 }
2578};
2579
2580void tst_Moc::privateSignalConnection()
2581{
2582 // Function pointer connects. Matching signals and slots
2583 {
2584 ClassWithPrivateSignals classWithPrivateSignals;
2585 SignalConnectionTester tester;
2586 QObject::connect(sender: &classWithPrivateSignals, signal: &ClassWithPrivateSignals::privateSignal1, receiver: &tester, slot: &SignalConnectionTester::testSlot);
2587
2588 QVERIFY(!tester.testPassed);
2589
2590 classWithPrivateSignals.emitPrivateSignals();
2591
2592 QVERIFY(tester.testPassed);
2593 tester.testPassed = false;
2594 QMetaObject::invokeMethod(obj: &classWithPrivateSignals, member: "privateSignal1");
2595 QVERIFY(tester.testPassed);
2596 }
2597 {
2598 SubClassFromPrivateSignals subClassFromPrivateSignals;
2599 SignalConnectionTester tester;
2600 QObject::connect(sender: &subClassFromPrivateSignals, signal: &ClassWithPrivateSignals::privateSignal1, receiver: &tester, slot: &SignalConnectionTester::testSlot);
2601
2602 QVERIFY(!tester.testPassed);
2603
2604 subClassFromPrivateSignals.emitPrivateSignals();
2605
2606 QVERIFY(tester.testPassed);
2607 tester.testPassed = false;
2608 QMetaObject::invokeMethod(obj: &subClassFromPrivateSignals, member: "privateSignal1");
2609 QVERIFY(tester.testPassed);
2610 }
2611 {
2612 ClassWithPrivateSignals classWithPrivateSignals;
2613 SignalConnectionTester tester;
2614 QObject::connect(sender: &classWithPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlotWith1Arg);
2615
2616 QVERIFY(!tester.testPassed);
2617
2618 classWithPrivateSignals.emitPrivateSignals();
2619
2620 QVERIFY(tester.testPassed);
2621 tester.testPassed = false;
2622 QMetaObject::invokeMethod(obj: &classWithPrivateSignals, member: "privateSignalWith1Arg", Q_ARG(int, 42));
2623 QVERIFY(tester.testPassed);
2624 }
2625 {
2626 SubClassFromPrivateSignals subClassFromPrivateSignals;
2627 SignalConnectionTester tester;
2628 QObject::connect(sender: &subClassFromPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlotWith1Arg);
2629
2630 QVERIFY(!tester.testPassed);
2631
2632 subClassFromPrivateSignals.emitPrivateSignals();
2633
2634 QVERIFY(tester.testPassed);
2635 tester.testPassed = false;
2636 QMetaObject::invokeMethod(obj: &subClassFromPrivateSignals, member: "privateSignalWith1Arg", Q_ARG(int, 42));
2637 QVERIFY(tester.testPassed);
2638 }
2639 {
2640 ClassWithPrivateSignals classWithPrivateSignals;
2641 SignalConnectionTester tester;
2642 QObject::connect(sender: &classWithPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith2Args, receiver: &tester, slot: &SignalConnectionTester::testSlotWith2Args);
2643
2644 QVERIFY(!tester.testPassed);
2645
2646 classWithPrivateSignals.emitPrivateSignals();
2647
2648 QVERIFY(tester.testPassed);
2649 tester.testPassed = false;
2650 QMetaObject::invokeMethod(obj: &classWithPrivateSignals, member: "privateSignalWith2Args", Q_ARG(int, 42), Q_ARG(QString, "Hello"));
2651 QVERIFY(tester.testPassed);
2652 }
2653 {
2654 SubClassFromPrivateSignals subClassFromPrivateSignals;
2655 SignalConnectionTester tester;
2656 QObject::connect(sender: &subClassFromPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith2Args, receiver: &tester, slot: &SignalConnectionTester::testSlotWith2Args);
2657
2658 QVERIFY(!tester.testPassed);
2659
2660 subClassFromPrivateSignals.emitPrivateSignals();
2661
2662 QVERIFY(tester.testPassed);
2663 tester.testPassed = false;
2664 QMetaObject::invokeMethod(obj: &subClassFromPrivateSignals, member: "privateSignalWith2Args", Q_ARG(int, 42), Q_ARG(QString, "Hello"));
2665 QVERIFY(tester.testPassed);
2666 }
2667
2668
2669 // String based connects. Matching signals and slots
2670 {
2671 ClassWithPrivateSignals classWithPrivateSignals;
2672 SignalConnectionTester tester;
2673 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateSignal1()), receiver: &tester, SLOT(testSlot()));
2674
2675 QVERIFY(!tester.testPassed);
2676
2677 classWithPrivateSignals.emitPrivateSignals();
2678
2679 QVERIFY(tester.testPassed);
2680 }
2681 {
2682 SubClassFromPrivateSignals subClassFromPrivateSignals;
2683 SignalConnectionTester tester;
2684 QObject::connect(sender: &subClassFromPrivateSignals, SIGNAL(privateSignal1()), receiver: &tester, SLOT(testSlot()));
2685
2686 QVERIFY(!tester.testPassed);
2687
2688 subClassFromPrivateSignals.emitPrivateSignals();
2689
2690 QVERIFY(tester.testPassed);
2691 }
2692 {
2693 ClassWithPrivateSignals classWithPrivateSignals;
2694 SignalConnectionTester tester;
2695 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), receiver: &tester, SLOT(testSlotWith1Arg(int)));
2696
2697 QVERIFY(!tester.testPassed);
2698
2699 classWithPrivateSignals.emitPrivateSignals();
2700
2701 QVERIFY(tester.testPassed);
2702 }
2703 {
2704 SubClassFromPrivateSignals subClassFromPrivateSignals;
2705 SignalConnectionTester tester;
2706 QObject::connect(sender: &subClassFromPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), receiver: &tester, SLOT(testSlotWith1Arg(int)));
2707
2708 QVERIFY(!tester.testPassed);
2709
2710 subClassFromPrivateSignals.emitPrivateSignals();
2711
2712 QVERIFY(tester.testPassed);
2713 }
2714 {
2715 ClassWithPrivateSignals classWithPrivateSignals;
2716 SignalConnectionTester tester;
2717 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), receiver: &tester, SLOT(testSlotWith2Args(int,QString)));
2718 QVERIFY(!tester.testPassed);
2719
2720 classWithPrivateSignals.emitPrivateSignals();
2721
2722 QVERIFY(tester.testPassed);
2723 }
2724 {
2725 SubClassFromPrivateSignals subClassFromPrivateSignals;
2726 SignalConnectionTester tester;
2727 QObject::connect(sender: &subClassFromPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), receiver: &tester, SLOT(testSlotWith2Args(int,QString)));
2728
2729 QVERIFY(!tester.testPassed);
2730
2731 subClassFromPrivateSignals.emitPrivateSignals();
2732
2733 QVERIFY(tester.testPassed);
2734 }
2735
2736 // Function pointer connects. Decayed slot arguments
2737 {
2738 ClassWithPrivateSignals classWithPrivateSignals;
2739 SignalConnectionTester tester;
2740 QObject::connect(sender: &classWithPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlot);
2741
2742 QVERIFY(!tester.testPassed);
2743
2744 classWithPrivateSignals.emitPrivateSignals();
2745
2746 QVERIFY(tester.testPassed);
2747 }
2748 {
2749 SubClassFromPrivateSignals subClassFromPrivateSignals;
2750 SignalConnectionTester tester;
2751 QObject::connect(sender: &subClassFromPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlot);
2752
2753 QVERIFY(!tester.testPassed);
2754
2755 subClassFromPrivateSignals.emitPrivateSignals();
2756
2757 QVERIFY(tester.testPassed);
2758 }
2759 {
2760 ClassWithPrivateSignals classWithPrivateSignals;
2761 SignalConnectionTester tester;
2762 QObject::connect(sender: &classWithPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlotWith1Arg);
2763 QVERIFY(!tester.testPassed);
2764
2765 classWithPrivateSignals.emitPrivateSignals();
2766
2767 QVERIFY(tester.testPassed);
2768 }
2769 {
2770 SubClassFromPrivateSignals subClassFromPrivateSignals;
2771 SignalConnectionTester tester;
2772 QObject::connect(sender: &subClassFromPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlotWith1Arg);
2773
2774 QVERIFY(!tester.testPassed);
2775
2776 subClassFromPrivateSignals.emitPrivateSignals();
2777
2778 QVERIFY(tester.testPassed);
2779 }
2780 {
2781 ClassWithPrivateSignals classWithPrivateSignals;
2782 SignalConnectionTester tester;
2783 QObject::connect(sender: &classWithPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlot);
2784 QVERIFY(!tester.testPassed);
2785
2786 classWithPrivateSignals.emitPrivateSignals();
2787
2788 QVERIFY(tester.testPassed);
2789 }
2790 {
2791 SubClassFromPrivateSignals subClassFromPrivateSignals;
2792 SignalConnectionTester tester;
2793 QObject::connect(sender: &subClassFromPrivateSignals, signal: &ClassWithPrivateSignals::privateSignalWith1Arg, receiver: &tester, slot: &SignalConnectionTester::testSlot);
2794
2795 QVERIFY(!tester.testPassed);
2796
2797 subClassFromPrivateSignals.emitPrivateSignals();
2798
2799 QVERIFY(tester.testPassed);
2800 }
2801
2802 // String based connects. Decayed slot arguments
2803 {
2804 ClassWithPrivateSignals classWithPrivateSignals;
2805 SignalConnectionTester tester;
2806 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), receiver: &tester, SLOT(testSlot()));
2807
2808 QVERIFY(!tester.testPassed);
2809
2810 classWithPrivateSignals.emitPrivateSignals();
2811
2812 QVERIFY(tester.testPassed);
2813 }
2814 {
2815 SubClassFromPrivateSignals subClassFromPrivateSignals;
2816 SignalConnectionTester tester;
2817 QObject::connect(sender: &subClassFromPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), receiver: &tester, SLOT(testSlot()));
2818
2819 QVERIFY(!tester.testPassed);
2820
2821 subClassFromPrivateSignals.emitPrivateSignals();
2822
2823 QVERIFY(tester.testPassed);
2824 }
2825 {
2826 ClassWithPrivateSignals classWithPrivateSignals;
2827 SignalConnectionTester tester;
2828 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), receiver: &tester, SLOT(testSlotWith1Arg(int)));
2829 QVERIFY(!tester.testPassed);
2830
2831 classWithPrivateSignals.emitPrivateSignals();
2832
2833 QVERIFY(tester.testPassed);
2834 }
2835 {
2836 SubClassFromPrivateSignals subClassFromPrivateSignals;
2837 SignalConnectionTester tester;
2838 QObject::connect(sender: &subClassFromPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), receiver: &tester, SLOT(testSlotWith1Arg(int)));
2839
2840 QVERIFY(!tester.testPassed);
2841
2842 subClassFromPrivateSignals.emitPrivateSignals();
2843
2844 QVERIFY(tester.testPassed);
2845 }
2846 {
2847 ClassWithPrivateSignals classWithPrivateSignals;
2848 SignalConnectionTester tester;
2849 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), receiver: &tester, SLOT(testSlot()));
2850 QVERIFY(!tester.testPassed);
2851
2852 classWithPrivateSignals.emitPrivateSignals();
2853
2854 QVERIFY(tester.testPassed);
2855 }
2856 {
2857 SubClassFromPrivateSignals subClassFromPrivateSignals;
2858 SignalConnectionTester tester;
2859 QObject::connect(sender: &subClassFromPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), receiver: &tester, SLOT(testSlot()));
2860
2861 QVERIFY(!tester.testPassed);
2862
2863 subClassFromPrivateSignals.emitPrivateSignals();
2864
2865 QVERIFY(tester.testPassed);
2866 }
2867
2868 // Overloaded private signals
2869 {
2870
2871 ClassWithPrivateSignals classWithPrivateSignals;
2872 SignalConnectionTester tester;
2873 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateOverloadedSignal()), receiver: &tester, SLOT(testSlot()));
2874 QVERIFY(!tester.testPassed);
2875
2876 classWithPrivateSignals.emitPrivateSignals();
2877
2878 QVERIFY(tester.testPassed);
2879 }
2880 {
2881
2882 ClassWithPrivateSignals classWithPrivateSignals;
2883 SignalConnectionTester tester;
2884 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateOverloadedSignal(int)), receiver: &tester, SLOT(testSlotWith1Arg(int)));
2885 QVERIFY(!tester.testPassed);
2886
2887 classWithPrivateSignals.emitPrivateSignals();
2888
2889 QVERIFY(tester.testPassed);
2890 }
2891 // We can't use function pointer connections to private signals which are overloaded because we would have to cast in this case to:
2892 // static_cast<void (ClassWithPrivateSignals::*)(int, ClassWithPrivateSignals::QPrivateSignal)>(&ClassWithPrivateSignals::privateOverloadedSignal)
2893 // Which doesn't work as ClassWithPrivateSignals::QPrivateSignal is private.
2894
2895 // Overload with either private or not private signals
2896 {
2897
2898 ClassWithPrivateSignals classWithPrivateSignals;
2899 SignalConnectionTester tester;
2900 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(overloadedMaybePrivate()), receiver: &tester, SLOT(testSlot()));
2901 QVERIFY(!tester.testPassed);
2902
2903 classWithPrivateSignals.emitPrivateSignals();
2904
2905 QVERIFY(tester.testPassed);
2906 }
2907 {
2908
2909 ClassWithPrivateSignals classWithPrivateSignals;
2910 SignalConnectionTester tester;
2911 QObject::connect(sender: &classWithPrivateSignals, SIGNAL(privateOverloadedSignal(int)), receiver: &tester, SLOT(testSlotWith1Arg(int)));
2912 QVERIFY(!tester.testPassed);
2913
2914 classWithPrivateSignals.emitPrivateSignals();
2915
2916 QVERIFY(tester.testPassed);
2917 }
2918 {
2919
2920 ClassWithPrivateSignals classWithPrivateSignals;
2921 SignalConnectionTester tester;
2922 QObject::connect(sender: &classWithPrivateSignals,
2923 signal: static_cast<void (ClassWithPrivateSignals::*)()>(&ClassWithPrivateSignals::overloadedMaybePrivate),
2924 receiver: &tester, slot: &SignalConnectionTester::testSlot);
2925 QVERIFY(!tester.testPassed);
2926
2927 classWithPrivateSignals.emitPrivateSignals();
2928
2929 QVERIFY(tester.testPassed);
2930 }
2931 // We can't use function pointer connections to private signals which are overloaded because we would have to cast in this case to:
2932 // static_cast<void (ClassWithPrivateSignals::*)(int, ClassWithPrivateSignals::QPrivateSignal)>(&ClassWithPrivateSignals::overloadedMaybePrivate)
2933 // Which doesn't work as ClassWithPrivateSignals::QPrivateSignal is private.
2934
2935 // Connecting from one private signal to another
2936 {
2937 ClassWithPrivateSignals classWithPrivateSignals1;
2938 ClassWithPrivateSignals classWithPrivateSignals2;
2939 SignalConnectionTester tester;
2940 QObject::connect(sender: &classWithPrivateSignals1, signal: &ClassWithPrivateSignals::privateSignal1,
2941 receiver: &classWithPrivateSignals2, slot: &ClassWithPrivateSignals::privateSignal1);
2942 QObject::connect(sender: &classWithPrivateSignals2, signal: &ClassWithPrivateSignals::privateSignal1,
2943 receiver: &tester, slot: &SignalConnectionTester::testSlot);
2944
2945 QVERIFY(!tester.testPassed);
2946 classWithPrivateSignals1.emitPrivateSignals();
2947 QVERIFY(tester.testPassed);
2948 }
2949}
2950
2951void tst_Moc::finalClasses_data()
2952{
2953 QTest::addColumn<QString>(name: "className");
2954 QTest::addColumn<QString>(name: "expected");
2955
2956 QTest::newRow(dataTag: "FinalTestClassQt") << FinalTestClassQt::staticMetaObject.className() << "FinalTestClassQt";
2957 QTest::newRow(dataTag: "ExportedFinalTestClassQt") << ExportedFinalTestClassQt::staticMetaObject.className() << "ExportedFinalTestClassQt";
2958 QTest::newRow(dataTag: "ExportedFinalTestClassQtX") << ExportedFinalTestClassQtX::staticMetaObject.className() << "ExportedFinalTestClassQtX";
2959
2960 QTest::newRow(dataTag: "FinalTestClassCpp11") << FinalTestClassCpp11::staticMetaObject.className() << "FinalTestClassCpp11";
2961 QTest::newRow(dataTag: "ExportedFinalTestClassCpp11") << ExportedFinalTestClassCpp11::staticMetaObject.className() << "ExportedFinalTestClassCpp11";
2962 QTest::newRow(dataTag: "ExportedFinalTestClassCpp11X") << ExportedFinalTestClassCpp11X::staticMetaObject.className() << "ExportedFinalTestClassCpp11X";
2963
2964 QTest::newRow(dataTag: "SealedTestClass") << SealedTestClass::staticMetaObject.className() << "SealedTestClass";
2965 QTest::newRow(dataTag: "ExportedSealedTestClass") << ExportedSealedTestClass::staticMetaObject.className() << "ExportedSealedTestClass";
2966 QTest::newRow(dataTag: "ExportedSealedTestClassX") << ExportedSealedTestClassX::staticMetaObject.className() << "ExportedSealedTestClassX";
2967}
2968
2969void tst_Moc::finalClasses()
2970{
2971 QFETCH(QString, className);
2972 QFETCH(QString, expected);
2973
2974 QCOMPARE(className, expected);
2975}
2976
2977void tst_Moc::explicitOverrideControl_data()
2978{
2979 QTest::addColumn<const QMetaObject*>(name: "mo");
2980
2981#define ADD(x) QTest::newRow(#x) << &x::staticMetaObject
2982 ADD(ExplicitOverrideControlFinalQt);
2983 ADD(ExplicitOverrideControlFinalCxx11);
2984 ADD(ExplicitOverrideControlSealed);
2985 ADD(ExplicitOverrideControlOverrideQt);
2986 ADD(ExplicitOverrideControlOverrideCxx11);
2987 ADD(ExplicitOverrideControlFinalQtOverrideQt);
2988 ADD(ExplicitOverrideControlFinalCxx11OverrideCxx11);
2989 ADD(ExplicitOverrideControlSealedOverride);
2990#undef ADD
2991}
2992
2993void tst_Moc::explicitOverrideControl()
2994{
2995 QFETCH(const QMetaObject*, mo);
2996
2997 QVERIFY(mo);
2998 QCOMPARE(mo->indexOfMethod("pureSlot0()"), mo->methodOffset() + 0);
2999 QCOMPARE(mo->indexOfMethod("pureSlot1()"), mo->methodOffset() + 1);
3000 QCOMPARE(mo->indexOfMethod("pureSlot2()"), mo->methodOffset() + 2);
3001 QCOMPARE(mo->indexOfMethod("pureSlot3()"), mo->methodOffset() + 3);
3002#if 0 // moc doesn't support volatile slots
3003 QCOMPARE(mo->indexOfMethod("pureSlot4()"), mo->methodOffset() + 4);
3004 QCOMPARE(mo->indexOfMethod("pureSlot5()"), mo->methodOffset() + 5);
3005 QCOMPARE(mo->indexOfMethod("pureSlot6()"), mo->methodOffset() + 6);
3006 QCOMPARE(mo->indexOfMethod("pureSlot7()"), mo->methodOffset() + 7);
3007 QCOMPARE(mo->indexOfMethod("pureSlot8()"), mo->methodOffset() + 8);
3008 QCOMPARE(mo->indexOfMethod("pureSlot9()"), mo->methodOffset() + 9);
3009#endif
3010}
3011
3012class OverloadedAddressOperator : public QObject
3013{
3014 Q_OBJECT
3015public:
3016 void* operator&() { return nullptr; }
3017signals:
3018 void self(OverloadedAddressOperator&);
3019public slots:
3020 void assertSelf(OverloadedAddressOperator &o)
3021 {
3022 QCOMPARE(std::addressof(o), this);
3023 testResult = (std::addressof(r&: o) == this);
3024 }
3025public:
3026 bool testResult = false;
3027};
3028
3029void tst_Moc::overloadedAddressOperator()
3030{
3031 OverloadedAddressOperator o;
3032 OverloadedAddressOperator *p = std::addressof(r&: o);
3033 QCOMPARE(&o, nullptr);
3034 QVERIFY(p);
3035 QObject::connect(sender: p, signal: &OverloadedAddressOperator::self, receiver: p, slot: &OverloadedAddressOperator::assertSelf);
3036 emit o.self(o);
3037 QVERIFY(o.testResult);
3038}
3039
3040class CustomQObject : public QObject
3041{
3042 Q_OBJECT
3043 Q_ENUMS(Number)
3044public:
3045 enum Number {
3046 Zero,
3047 One,
3048 Two
3049 };
3050 explicit CustomQObject(QObject *parent = 0)
3051 : QObject(parent)
3052 {
3053 }
3054};
3055
3056Q_DECLARE_METATYPE(CustomQObject::Number)
3057
3058typedef CustomQObject* CustomQObjectStar;
3059Q_DECLARE_METATYPE(CustomQObjectStar);
3060
3061namespace SomeNamespace {
3062
3063class NamespacedQObject : public QObject
3064{
3065 Q_OBJECT
3066public:
3067 explicit NamespacedQObject(QObject *parent = 0)
3068 : QObject(parent)
3069 {
3070
3071 }
3072};
3073
3074struct NamespacedNonQObject {};
3075}
3076Q_DECLARE_METATYPE(SomeNamespace::NamespacedNonQObject)
3077
3078// Need different types for the invokable method tests because otherwise the registration
3079// done in the property test would interfere.
3080
3081class CustomQObject2 : public QObject
3082{
3083 Q_OBJECT
3084 Q_ENUMS(Number)
3085public:
3086 enum Number {
3087 Zero,
3088 One,
3089 Two
3090 };
3091 explicit CustomQObject2(QObject *parent = 0)
3092 : QObject(parent)
3093 {
3094 }
3095};
3096
3097Q_DECLARE_METATYPE(CustomQObject2::Number)
3098
3099typedef CustomQObject2* CustomQObject2Star;
3100Q_DECLARE_METATYPE(CustomQObject2Star);
3101
3102namespace SomeNamespace2 {
3103
3104class NamespacedQObject2 : public QObject
3105{
3106 Q_OBJECT
3107public:
3108 explicit NamespacedQObject2(QObject *parent = 0)
3109 : QObject(parent)
3110 {
3111
3112 }
3113};
3114
3115struct NamespacedNonQObject2 {};
3116}
3117Q_DECLARE_METATYPE(SomeNamespace2::NamespacedNonQObject2)
3118
3119
3120struct CustomObject3 {};
3121struct CustomObject4 {};
3122struct CustomObject5 {};
3123struct CustomObject6 {};
3124struct CustomObject7 {};
3125struct CustomObject8 {};
3126struct CustomObject9 {};
3127struct CustomObject10 {};
3128struct CustomObject11 {};
3129struct CustomObject12 {};
3130
3131Q_DECLARE_METATYPE(CustomObject3)
3132Q_DECLARE_METATYPE(CustomObject4)
3133Q_DECLARE_METATYPE(CustomObject5)
3134Q_DECLARE_METATYPE(CustomObject6)
3135Q_DECLARE_METATYPE(CustomObject7)
3136Q_DECLARE_METATYPE(CustomObject8)
3137Q_DECLARE_METATYPE(CustomObject9)
3138Q_DECLARE_METATYPE(CustomObject10)
3139Q_DECLARE_METATYPE(CustomObject11)
3140Q_DECLARE_METATYPE(CustomObject12)
3141
3142class AutoRegistrationObject : public QObject
3143{
3144 Q_OBJECT
3145 Q_PROPERTY(QObject* object READ object CONSTANT)
3146 Q_PROPERTY(CustomQObject* customObject READ customObject CONSTANT)
3147 Q_PROPERTY(QSharedPointer<CustomQObject> customObjectP READ customObjectP CONSTANT)
3148 Q_PROPERTY(QWeakPointer<CustomQObject> customObjectWP READ customObjectWP CONSTANT)
3149 Q_PROPERTY(QPointer<CustomQObject> customObjectTP READ customObjectTP CONSTANT)
3150 Q_PROPERTY(QList<int> listInt READ listInt CONSTANT)
3151 Q_PROPERTY(QVector<QVariant> vectorVariant READ vectorVariant CONSTANT)
3152 Q_PROPERTY(QList<CustomQObject*> listObject READ listObject CONSTANT)
3153 Q_PROPERTY(QVector<QList<int>> vectorListInt READ vectorListInt CONSTANT)
3154 Q_PROPERTY(QVector<QList<CustomQObject*>> vectorListObject READ vectorListObject CONSTANT)
3155 Q_PROPERTY(CustomQObject::Number enumValue READ enumValue CONSTANT)
3156 Q_PROPERTY(CustomQObjectStar customObjectTypedef READ customObjectTypedef CONSTANT)
3157 Q_PROPERTY(SomeNamespace::NamespacedQObject* customObjectNamespaced READ customObjectNamespaced CONSTANT)
3158 Q_PROPERTY(SomeNamespace::NamespacedNonQObject customNonQObjectNamespaced READ customNonQObjectNamespaced CONSTANT)
3159public:
3160 AutoRegistrationObject(QObject *parent = 0)
3161 : QObject(parent)
3162 {
3163 }
3164
3165 QObject* object() const
3166 {
3167 return 0;
3168 }
3169
3170 QSharedPointer<CustomQObject> customObjectP() const
3171 {
3172 return QSharedPointer<CustomQObject>();
3173 }
3174
3175 QWeakPointer<CustomQObject> customObjectWP() const
3176 {
3177 return QWeakPointer<CustomQObject>();
3178 }
3179
3180 QPointer<CustomQObject> customObjectTP() const
3181 {
3182 return QPointer<CustomQObject>();
3183 }
3184
3185 CustomQObject* customObject() const
3186 {
3187 return 0;
3188 }
3189
3190 QList<int> listInt() const
3191 {
3192 return QList<int>();
3193 }
3194
3195 QVector<QVariant> vectorVariant() const
3196 {
3197 return QVector<QVariant>();
3198 }
3199
3200 QList<CustomQObject*> listObject() const
3201 {
3202 return QList<CustomQObject*>();
3203 }
3204
3205 QVector<QList<int> > vectorListInt() const
3206 {
3207 return QVector<QList<int> >();
3208 }
3209
3210 QVector<QList<CustomQObject*> > vectorListObject() const
3211 {
3212 return QVector<QList<CustomQObject*> >();
3213 }
3214
3215 CustomQObject::Number enumValue() const
3216 {
3217 return CustomQObject::Zero;
3218 }
3219
3220 CustomQObjectStar customObjectTypedef() const
3221 {
3222 return 0;
3223 }
3224
3225 SomeNamespace::NamespacedQObject* customObjectNamespaced() const
3226 {
3227 return 0;
3228 }
3229
3230 SomeNamespace::NamespacedNonQObject customNonQObjectNamespaced() const
3231 {
3232 return SomeNamespace::NamespacedNonQObject();
3233 }
3234
3235public slots:
3236 void objectSlot(QObject*) {}
3237 void customObjectSlot(CustomQObject2*) {}
3238 void sharedPointerSlot(QSharedPointer<CustomQObject2>) {}
3239 void weakPointerSlot(QWeakPointer<CustomQObject2>) {}
3240 void trackingPointerSlot(QPointer<CustomQObject2>) {}
3241 void listIntSlot(QList<int>) {}
3242 void vectorVariantSlot(QVector<QVariant>) {}
3243 void listCustomObjectSlot(QList<CustomQObject2*>) {}
3244 void vectorListIntSlot(QVector<QList<int> >) {}
3245 void vectorListCustomObjectSlot(QVector<QList<CustomQObject2*> >) {}
3246 void enumSlot(CustomQObject2::Number) {}
3247 void typedefSlot(CustomQObject2Star) {}
3248 void namespacedQObjectSlot(SomeNamespace2::NamespacedQObject2*) {}
3249 void namespacedNonQObjectSlot(SomeNamespace2::NamespacedNonQObject2) {}
3250
3251 void bu1(int, CustomObject3) {}
3252 void bu2(CustomObject4, int) {}
3253 void bu3(CustomObject5, CustomObject6) {}
3254 void bu4(CustomObject7, int, CustomObject8) {}
3255 void bu5(int, CustomObject9, CustomObject10) {}
3256 void bu6(int, CustomObject11, int) {}
3257
3258 // these can't be registered, but they should at least compile
3259 void ref1(int&) {}
3260 void ref2(QList<int>&) {}
3261 void ref3(CustomQObject2&) {}
3262 void ref4(QSharedPointer<CustomQObject2>&) {}
3263
3264signals:
3265 void someSignal(CustomObject12);
3266};
3267
3268void tst_Moc::autoPropertyMetaTypeRegistration()
3269{
3270 AutoRegistrationObject aro;
3271
3272 static const int numPropertiesUnderTest = 15;
3273 QVector<int> propertyMetaTypeIds;
3274 propertyMetaTypeIds.reserve(asize: numPropertiesUnderTest);
3275
3276 const QMetaObject *metaObject = aro.metaObject();
3277 QCOMPARE(metaObject->propertyCount(), numPropertiesUnderTest);
3278 for (int i = 0; i < metaObject->propertyCount(); ++i) {
3279 const QMetaProperty prop = metaObject->property(index: i);
3280 propertyMetaTypeIds.append(t: prop.userType());
3281 QVariant var = prop.read(obj: &aro);
3282 QVERIFY(var.isValid());
3283 }
3284
3285 // Verify that QMetaProperty::userType gave us what we expected.
3286 QVector<int> expectedMetaTypeIds = QVector<int>()
3287 << QMetaType::QString // QObject::userType
3288 << QMetaType::QObjectStar // AutoRegistrationObject::object
3289 << qMetaTypeId<CustomQObject*>() // etc.
3290 << qMetaTypeId<QSharedPointer<CustomQObject> >()
3291 << qMetaTypeId<QWeakPointer<CustomQObject> >()
3292 << qMetaTypeId<QPointer<CustomQObject> >()
3293 << qMetaTypeId<QList<int> >()
3294 << qMetaTypeId<QVector<QVariant> >()
3295 << qMetaTypeId<QList<CustomQObject*> >()
3296 << qMetaTypeId<QVector<QList<int> > >()
3297 << qMetaTypeId<QVector<QList<CustomQObject*> > >()
3298 << qMetaTypeId<CustomQObject::Number>()
3299 << qMetaTypeId<CustomQObjectStar>()
3300 << qMetaTypeId<SomeNamespace::NamespacedQObject*>()
3301 << qMetaTypeId<SomeNamespace::NamespacedNonQObject>()
3302 ;
3303
3304 QCOMPARE(propertyMetaTypeIds, expectedMetaTypeIds);
3305}
3306
3307template<typename T>
3308struct DefaultConstructor
3309{
3310 static inline T construct() { return T(); }
3311};
3312
3313template<typename T>
3314struct DefaultConstructor<T*>
3315{
3316 static inline T* construct() { return 0; }
3317};
3318
3319void tst_Moc::autoMethodArgumentMetaTypeRegistration()
3320{
3321 AutoRegistrationObject aro;
3322
3323 QVector<int> methodArgMetaTypeIds;
3324
3325 const QMetaObject *metaObject = aro.metaObject();
3326
3327 int i = metaObject->methodOffset(); // Start after QObject built-in slots;
3328
3329 while (i < metaObject->methodCount()) {
3330 // Skip over signals so we start at the first slot.
3331 const QMetaMethod method = metaObject->method(index: i);
3332 if (method.methodType() == QMetaMethod::Signal)
3333 ++i;
3334 else
3335 break;
3336
3337 }
3338
3339#define TYPE_LOOP(TYPE) \
3340 { \
3341 const QMetaMethod method = metaObject->method(i); \
3342 for (int j = 0; j < method.parameterCount(); ++j) \
3343 methodArgMetaTypeIds.append(method.parameterType(j)); \
3344 QVERIFY(method.invoke(&aro, Q_ARG(TYPE, DefaultConstructor<TYPE>::construct()))); \
3345 ++i; \
3346 }
3347
3348#define FOR_EACH_SLOT_ARG_TYPE(F) \
3349 F(QObject*) \
3350 F(CustomQObject2*) \
3351 F(QSharedPointer<CustomQObject2>) \
3352 F(QWeakPointer<CustomQObject2>) \
3353 F(QPointer<CustomQObject2>) \
3354 F(QList<int>) \
3355 F(QVector<QVariant>) \
3356 F(QList<CustomQObject2*>) \
3357 F(QVector<QList<int> >) \
3358 F(QVector<QList<CustomQObject2*> >) \
3359 F(CustomQObject2::Number) \
3360 F(CustomQObject2Star) \
3361 F(SomeNamespace2::NamespacedQObject2*) \
3362 F(SomeNamespace2::NamespacedNonQObject2)
3363
3364 // Note: mulit-arg slots are tested below.
3365
3366 FOR_EACH_SLOT_ARG_TYPE(TYPE_LOOP)
3367
3368#undef TYPE_LOOP
3369#undef FOR_EACH_SLOT_ARG_TYPE
3370
3371 QVector<int> expectedMetaTypeIds = QVector<int>()
3372 << QMetaType::QObjectStar
3373 << qMetaTypeId<CustomQObject2*>()
3374 << qMetaTypeId<QSharedPointer<CustomQObject2> >()
3375 << qMetaTypeId<QWeakPointer<CustomQObject2> >()
3376 << qMetaTypeId<QPointer<CustomQObject2> >()
3377 << qMetaTypeId<QList<int> >()
3378 << qMetaTypeId<QVector<QVariant> >()
3379 << qMetaTypeId<QList<CustomQObject2*> >()
3380 << qMetaTypeId<QVector<QList<int> > >()
3381 << qMetaTypeId<QVector<QList<CustomQObject2*> > >()
3382 << qMetaTypeId<CustomQObject2::Number>()
3383 << qMetaTypeId<CustomQObject2Star>()
3384 << qMetaTypeId<SomeNamespace2::NamespacedQObject2*>()
3385 << qMetaTypeId<SomeNamespace2::NamespacedNonQObject2>()
3386 ;
3387
3388 QCOMPARE(methodArgMetaTypeIds, expectedMetaTypeIds);
3389
3390
3391 QVector<int> methodMultiArgMetaTypeIds;
3392
3393 {
3394 const QMetaMethod method = metaObject->method(index: i);
3395 QCOMPARE(method.name(), QByteArray("bu1"));
3396 for (int j = 0; j < method.parameterCount(); ++j)
3397 methodMultiArgMetaTypeIds.append(t: method.parameterType(index: j));
3398 QVERIFY(method.invoke(&aro, Q_ARG(int, 42), Q_ARG(CustomObject3, CustomObject3())));
3399 ++i;
3400 }
3401 {
3402 const QMetaMethod method = metaObject->method(index: i);
3403 QCOMPARE(method.name(), QByteArray("bu2"));
3404 for (int j = 0; j < method.parameterCount(); ++j)
3405 methodMultiArgMetaTypeIds.append(t: method.parameterType(index: j));
3406 QVERIFY(method.invoke(&aro, Q_ARG(CustomObject4, CustomObject4()), Q_ARG(int, 42)));
3407 ++i;
3408 }
3409 {
3410 const QMetaMethod method = metaObject->method(index: i);
3411 QCOMPARE(method.name(), QByteArray("bu3"));
3412 for (int j = 0; j < method.parameterCount(); ++j)
3413 methodMultiArgMetaTypeIds.append(t: method.parameterType(index: j));
3414 QVERIFY(method.invoke(&aro, Q_ARG(CustomObject5, CustomObject5()), Q_ARG(CustomObject6, CustomObject6())));
3415 ++i;
3416 }
3417 {
3418 const QMetaMethod method = metaObject->method(index: i);
3419 QCOMPARE(method.name(), QByteArray("bu4"));
3420 for (int j = 0; j < method.parameterCount(); ++j)
3421 methodMultiArgMetaTypeIds.append(t: method.parameterType(index: j));
3422 QVERIFY(method.invoke(&aro, Q_ARG(CustomObject7, CustomObject7()), Q_ARG(int, 42), Q_ARG(CustomObject8, CustomObject8())));
3423 ++i;
3424 }
3425 {
3426 const QMetaMethod method = metaObject->method(index: i);
3427 QCOMPARE(method.name(), QByteArray("bu5"));
3428 for (int j = 0; j < method.parameterCount(); ++j)
3429 methodMultiArgMetaTypeIds.append(t: method.parameterType(index: j));
3430 QVERIFY(method.invoke(&aro, Q_ARG(int, 42), Q_ARG(CustomObject9, CustomObject9()), Q_ARG(CustomObject10, CustomObject10())));
3431 ++i;
3432 }
3433 {
3434 const QMetaMethod method = metaObject->method(index: i);
3435 QCOMPARE(method.name(), QByteArray("bu6"));
3436 for (int j = 0; j < method.parameterCount(); ++j)
3437 methodMultiArgMetaTypeIds.append(t: method.parameterType(index: j));
3438 QVERIFY(method.invoke(&aro, Q_ARG(int, 42), Q_ARG(CustomObject11, CustomObject11()), Q_ARG(int, 42)));
3439 ++i;
3440 }
3441
3442 QVector<int> expectedMultiMetaTypeIds = QVector<int>()
3443 << QMetaType::Int
3444 << qMetaTypeId<CustomObject3>()
3445 << qMetaTypeId<CustomObject4>()
3446 << QMetaType::Int
3447 << qMetaTypeId<CustomObject5>()
3448 << qMetaTypeId<CustomObject6>()
3449 << qMetaTypeId<CustomObject7>()
3450 << QMetaType::Int
3451 << qMetaTypeId<CustomObject8>()
3452 << QMetaType::Int
3453 << qMetaTypeId<CustomObject9>()
3454 << qMetaTypeId<CustomObject10>()
3455 << QMetaType::Int
3456 << qMetaTypeId<CustomObject11>()
3457 << QMetaType::Int
3458 ;
3459
3460 QCOMPARE(methodMultiArgMetaTypeIds, expectedMultiMetaTypeIds);
3461
3462
3463}
3464
3465void tst_Moc::autoSignalSpyMetaTypeRegistration()
3466{
3467 AutoRegistrationObject aro;
3468
3469 QVector<int> methodArgMetaTypeIds;
3470
3471 const QMetaObject *metaObject = aro.metaObject();
3472
3473 int i = metaObject->indexOfSignal(signal: QMetaObject::normalizedSignature(method: "someSignal(CustomObject12)"));
3474
3475 QVERIFY(i > 0);
3476
3477 QCOMPARE(QMetaType::type("CustomObject12"), (int)QMetaType::UnknownType);
3478
3479 QSignalSpy spy(&aro, SIGNAL(someSignal(CustomObject12)));
3480
3481 QVERIFY(QMetaType::type("CustomObject12") != QMetaType::UnknownType);
3482 QCOMPARE(QMetaType::type("CustomObject12"), qMetaTypeId<CustomObject12>());
3483}
3484
3485void tst_Moc::parseDefines()
3486{
3487 const QMetaObject *mo = &PD_NAMESPACE::PD_CLASSNAME::staticMetaObject;
3488 QCOMPARE(mo->className(), PD_SCOPED_STRING(PD_NAMESPACE, PD_CLASSNAME));
3489 QVERIFY(mo->indexOfSlot("voidFunction()") != -1);
3490
3491 int index = mo->indexOfSlot(slot: "stringMethod()");
3492 QVERIFY(index != -1);
3493 QCOMPARE(mo->method(index).returnType(), int(QMetaType::QString));
3494
3495 index = mo->indexOfSlot(slot: "combined1()");
3496 QVERIFY(index != -1);
3497
3498 index = mo->indexOfSlot(slot: "combined2()");
3499 QVERIFY(index != -1);
3500
3501 index = mo->indexOfSlot(slot: "combined3()");
3502 QVERIFY(index != -1);
3503
3504 index = mo->indexOfSlot(slot: "combined4(int,int)");
3505 QVERIFY(index != -1);
3506
3507 index = mo->indexOfSlot(slot: "combined5()");
3508 QVERIFY(index != -1);
3509
3510 index = mo->indexOfSlot(slot: "combined6()");
3511 QVERIFY(index != -1);
3512
3513 index = mo->indexOfSlot(slot: "vararg1()");
3514 QVERIFY(index != -1);
3515 index = mo->indexOfSlot(slot: "vararg2(int)");
3516 QVERIFY(index != -1);
3517 index = mo->indexOfSlot(slot: "vararg3(int,int)");
3518 QVERIFY(index != -1);
3519 index = mo->indexOfSlot(slot: "vararg4()");
3520 QVERIFY(index != -1);
3521 index = mo->indexOfSlot(slot: "vararg5(int)");
3522 QVERIFY(index != -1);
3523 index = mo->indexOfSlot(slot: "vararg6(int,int)");
3524 QVERIFY(index != -1);
3525
3526 index = mo->indexOfSlot(slot: "INNERFUNCTION(int)");
3527 QVERIFY(index != -1);
3528 index = mo->indexOfSlot(slot: "inner_expanded(int)");
3529 QVERIFY(index != -1);
3530 index = mo->indexOfSlot(slot: "expanded_method(int)");
3531 QVERIFY(index != -1);
3532
3533 index = mo->indexOfSlot(slot: "conditionSlot()");
3534 QVERIFY(index != -1);
3535
3536 int count = 0;
3537 for (int i = 0; i < mo->classInfoCount(); ++i) {
3538 QMetaClassInfo mci = mo->classInfo(index: i);
3539 if (!qstrcmp(str1: mci.name(), str2: "TestString")) {
3540 ++count;
3541 QVERIFY(!qstrcmp(mci.value(), "PD_CLASSNAME"));
3542 }
3543 if (!qstrcmp(str1: mci.name(), str2: "TestString2")) {
3544 ++count;
3545 QVERIFY(!qstrcmp(mci.value(), "ParseDefine"));
3546 }
3547 if (!qstrcmp(str1: mci.name(), str2: "TestString3")) {
3548 ++count;
3549 QVERIFY(!qstrcmp(mci.value(), "TestValue"));
3550 }
3551 }
3552 QCOMPARE(count, 3);
3553
3554 index = mo->indexOfSlot(slot: "PD_DEFINE_ITSELF_SUFFIX(int)");
3555 QVERIFY(index != -1);
3556
3557 index = mo->indexOfSignal(signal: "cmdlineSignal(QMap<int,int>)");
3558 QVERIFY(index != -1);
3559
3560 index = mo->indexOfSignal(signal: "signalQTBUG55853()");
3561 QVERIFY(index != -1);
3562}
3563
3564void tst_Moc::preprocessorOnly()
3565{
3566#ifdef MOC_CROSS_COMPILED
3567 QSKIP("Not tested when cross-compiled");
3568#endif
3569#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
3570 QProcess proc;
3571 proc.start(program: m_moc, arguments: QStringList() << "-E" << m_sourceDirectory + QStringLiteral("/pp-dollar-signs.h"));
3572 QVERIFY(proc.waitForFinished());
3573 QCOMPARE(proc.exitCode(), 0);
3574 QByteArray mocOut = proc.readAllStandardOutput();
3575 QVERIFY(!mocOut.isEmpty());
3576 QCOMPARE(proc.readAllStandardError(), QByteArray());
3577
3578 QVERIFY(mocOut.contains("$$ = parser->createFoo()"));
3579#else
3580 QSKIP("Only tested on linux/gcc");
3581#endif
3582}
3583
3584
3585void tst_Moc::unterminatedFunctionMacro()
3586{
3587#ifdef MOC_CROSS_COMPILED
3588 QSKIP("Not tested when cross-compiled");
3589#endif
3590#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && QT_CONFIG(process)
3591 QProcess proc;
3592 proc.start(program: m_moc, arguments: QStringList() << "-E" << m_sourceDirectory + QStringLiteral("/unterminated-function-macro.h"));
3593 QVERIFY(proc.waitForFinished());
3594 QCOMPARE(proc.exitCode(), 1);
3595 QCOMPARE(proc.readAllStandardOutput(), QByteArray());
3596 QByteArray errorOutput = proc.readAllStandardError();
3597 QVERIFY(!errorOutput.isEmpty());
3598 QVERIFY(errorOutput.contains("missing ')' in macro usage"));
3599#else
3600 QSKIP("Only tested on linux/gcc");
3601#endif
3602}
3603
3604namespace QTBUG32933_relatedObjectsDontIncludeItself {
3605 namespace NS {
3606 class Obj : QObject {
3607 Q_OBJECT
3608 Q_PROPERTY(MyEnum p1 MEMBER member)
3609 Q_PROPERTY(Obj::MyEnum p2 MEMBER member)
3610 Q_PROPERTY(NS::Obj::MyEnum p3 MEMBER member)
3611 Q_PROPERTY(QTBUG32933_relatedObjectsDontIncludeItself::NS::Obj::MyEnum p4 MEMBER member)
3612 Q_ENUMS(MyEnum);
3613 public:
3614 enum MyEnum { Something, SomethingElse };
3615 MyEnum member;
3616 };
3617 }
3618}
3619
3620void tst_Moc::QTBUG32933_relatedObjectsDontIncludeItself()
3621{
3622 const QMetaObject *mo = &QTBUG32933_relatedObjectsDontIncludeItself::NS::Obj::staticMetaObject;
3623 const auto *objects = mo->d.relatedMetaObjects;
3624 // the related objects should be empty because the enums is in the same object.
3625 QVERIFY(!objects);
3626}
3627
3628class UnrelatedClass : public QObject
3629{
3630 Q_OBJECT
3631 Q_ENUMS(UnrelatedEnum)
3632public:
3633 enum UnrelatedEnum {
3634 UnrelatedInvalidValue = -1,
3635 UnrelatedValue = 42
3636 };
3637};
3638
3639// The presence of this macro used to confuse moc and prevent
3640// UnrelatedClass from being listed in the related meta objects.
3641Q_DECLARE_METATYPE(UnrelatedClass::UnrelatedEnum)
3642
3643class TestClassReferencingUnrelatedEnum : public QObject
3644{
3645 Q_OBJECT
3646 Q_PROPERTY(UnrelatedClass::UnrelatedEnum enumProperty READ enumProperty WRITE setEnumProperty)
3647public:
3648 TestClassReferencingUnrelatedEnum()
3649 : m_enumProperty(UnrelatedClass::UnrelatedInvalidValue)
3650 {}
3651
3652 UnrelatedClass::UnrelatedEnum enumProperty() const {
3653 return m_enumProperty;
3654 }
3655
3656 void setEnumProperty(UnrelatedClass::UnrelatedEnum arg) {
3657 m_enumProperty = arg;
3658 }
3659
3660private:
3661 UnrelatedClass::UnrelatedEnum m_enumProperty;
3662};
3663
3664void tst_Moc::writeEnumFromUnrelatedClass()
3665{
3666 TestClassReferencingUnrelatedEnum obj;
3667 QString enumValueAsString("UnrelatedValue");
3668 obj.setProperty(name: "enumProperty", value: enumValueAsString);
3669 QCOMPARE(int(obj.enumProperty()), int(UnrelatedClass::UnrelatedValue));
3670}
3671
3672
3673
3674void tst_Moc::relatedMetaObjectsWithinNamespaces()
3675{
3676 const QMetaObject *relatedMo = &QTBUG_2151::A::staticMetaObject;
3677
3678 const QMetaObject *testMo = &QTBUG_2151::B::staticMetaObject;
3679 QVERIFY(testMo->d.relatedMetaObjects);
3680 QCOMPARE(testMo->d.relatedMetaObjects[0], relatedMo);
3681}
3682
3683void tst_Moc::relatedMetaObjectsInGadget()
3684{
3685 const QMetaObject *relatedMo = &QTBUG_35657::A::staticMetaObject;
3686
3687 const QMetaObject *testMo = &QTBUG_35657::B::staticMetaObject;
3688 QVERIFY(testMo->d.relatedMetaObjects);
3689 QCOMPARE(testMo->d.relatedMetaObjects[0], relatedMo);
3690}
3691
3692void tst_Moc::relatedMetaObjectsNameConflict_data()
3693{
3694 typedef QVector<const QMetaObject*> QMetaObjects;
3695 QTest::addColumn<const QMetaObject*>(name: "dependingObject");
3696 QTest::addColumn<QMetaObjects>(name: "relatedMetaObjects");
3697
3698 //NS1
3699 const QMetaObject *n1gadget = &NS1::Gadget::staticMetaObject;
3700 const QMetaObject *n1object = &NS1::Object::staticMetaObject;
3701 const QMetaObject *n1nestedGadget = &NS1::Nested::Gadget::staticMetaObject;
3702 const QMetaObject *n1nestedObject = &NS1::Nested::Object::staticMetaObject;
3703 //N2
3704 const QMetaObject *n2gadget = &NS2::Gadget::staticMetaObject;
3705 const QMetaObject *n2object = &NS2::Object::staticMetaObject;
3706 const QMetaObject *n2nestedGadget = &NS2::Nested::Gadget::staticMetaObject;
3707 const QMetaObject *n2nestedObject = &NS2::Nested::Object::staticMetaObject;
3708
3709 QTest::newRow(dataTag: "N1::dependingObject") << &NS1::DependingObject::staticMetaObject
3710 << (QMetaObjects() << n1gadget << n1object);
3711 QTest::newRow(dataTag: "N2::dependingObject") << &NS2::DependingObject::staticMetaObject
3712 << (QMetaObjects() << n2gadget << n2object);
3713 QTest::newRow(dataTag: "N1::dependingNestedObject") << &NS1::DependingNestedObject::staticMetaObject
3714 << (QMetaObjects() << n1nestedObject);
3715 QTest::newRow(dataTag: "N2::dependingNestedObject") << &NS2::DependingNestedObject::staticMetaObject
3716 << (QMetaObjects() << n2nestedObject);
3717 QTest::newRow(dataTag: "N1::dependingNestedGadget") << &NS1::DependingNestedGadget::staticMetaObject
3718 << (QMetaObjects() << n1nestedGadget);
3719 QTest::newRow(dataTag: "N2::dependingNestedGadget") << &NS2::DependingNestedGadget::staticMetaObject
3720 << (QMetaObjects() << n2nestedGadget);
3721}
3722
3723void tst_Moc::relatedMetaObjectsNameConflict()
3724{
3725 typedef QVector<const QMetaObject*> QMetaObjects;
3726 QFETCH(const QMetaObject*, dependingObject);
3727 QFETCH(QMetaObjects, relatedMetaObjects);
3728
3729 // load all specified metaobjects int a set
3730 QSet<const QMetaObject*> dependency;
3731 const auto *i = dependingObject->d.relatedMetaObjects;
3732 while (*i) {
3733 dependency.insert(value: *i);
3734 ++i;
3735 }
3736
3737 // check if all required metaobjects are specified
3738 foreach (const QMetaObject *mo, relatedMetaObjects)
3739 QVERIFY(dependency.contains(mo));
3740
3741 // check if no additional metaobjects ara specified
3742 QCOMPARE(dependency.size(), relatedMetaObjects.size());
3743}
3744
3745class StringLiteralsInMacroExtension: public QObject
3746{
3747 Q_OBJECT
3748#define Macro(F) F " " F
3749 Q_CLASSINFO(Macro("String"), Macro("Literal"))
3750#undef Macro
3751
3752#define Macro(F) F
3753 Q_CLASSINFO("String" Macro("!"), "Literal" Macro("!"))
3754 Q_CLASSINFO(Macro("!") "String", Macro("!") "Literal")
3755#undef Macro
3756
3757#define Macro "foo"
3758 Q_CLASSINFO("String" Macro, "Literal" Macro)
3759 Q_CLASSINFO(Macro "String", Macro "Literal")
3760#undef Macro
3761};
3762
3763void tst_Moc::strignLiteralsInMacroExtension()
3764{
3765 const QMetaObject *mobj = &StringLiteralsInMacroExtension::staticMetaObject;
3766 QCOMPARE(mobj->classInfoCount(), 5);
3767
3768 QCOMPARE(mobj->classInfo(0).name(), "String String");
3769 QCOMPARE(mobj->classInfo(0).value(), "Literal Literal");
3770
3771 QCOMPARE(mobj->classInfo(1).name(), "String!");
3772 QCOMPARE(mobj->classInfo(1).value(), "Literal!");
3773
3774 QCOMPARE(mobj->classInfo(2).name(), "!String");
3775 QCOMPARE(mobj->classInfo(2).value(), "!Literal");
3776
3777 QCOMPARE(mobj->classInfo(3).name(), "Stringfoo");
3778 QCOMPARE(mobj->classInfo(3).value(), "Literalfoo");
3779
3780 QCOMPARE(mobj->classInfo(4).name(), "fooString");
3781 QCOMPARE(mobj->classInfo(4).value(), "fooLiteral");
3782}
3783
3784class VeryLongStringData : public QObject
3785{
3786 Q_OBJECT
3787
3788 #define repeat2(V) V V
3789 #define repeat4(V) repeat2(V) repeat2(V)
3790 #define repeat8(V) repeat4(V) repeat4(V)
3791 #define repeat16(V) repeat8(V) repeat8(V)
3792 #define repeat32(V) repeat16(V) repeat16(V)
3793 #define repeat64(V) repeat32(V) repeat32(V)
3794 #define repeat128(V) repeat64(V) repeat64(V)
3795 #define repeat256(V) repeat128(V) repeat128(V)
3796 #define repeat512(V) repeat256(V) repeat256(V)
3797 #define repeat1024(V) repeat512(V) repeat512(V)
3798 #define repeat2048(V) repeat1024(V) repeat1024(V)
3799 #define repeat4096(V) repeat2048(V) repeat2048(V)
3800 #define repeat8192(V) repeat4096(V) repeat4096(V)
3801 #define repeat16384(V) repeat8192(V) repeat8192(V)
3802 #define repeat32768(V) repeat16384(V) repeat16384(V)
3803 #define repeat65534(V) repeat32768(V) repeat16384(V) repeat8192(V) repeat4096(V) repeat2048(V) repeat1024(V) repeat512(V) repeat256(V) repeat128(V) repeat64(V) repeat32(V) repeat16(V) repeat8(V) repeat4(V) repeat2(V)
3804
3805 Q_CLASSINFO(repeat65534("n"), repeat65534("i"))
3806 Q_CLASSINFO(repeat65534("e"), repeat65534("r"))
3807 Q_CLASSINFO(repeat32768("o"), repeat32768("b"))
3808 Q_CLASSINFO(":", ")")
3809
3810 #undef repeat2
3811 #undef repeat4
3812 #undef repeat8
3813 #undef repeat16
3814 #undef repeat32
3815 #undef repeat64
3816 #undef repeat128
3817 #undef repeat256
3818 #undef repeat512
3819 #undef repeat1024
3820 #undef repeat2048
3821 #undef repeat4096
3822 #undef repeat8192
3823 #undef repeat16384
3824 #undef repeat32768
3825 #undef repeat65534
3826};
3827
3828void tst_Moc::unnamedNamespaceObjectsAndGadgets()
3829{
3830 // these just test very basic functionality of gadgets and objects
3831 // defined in unnamed namespaces.
3832 {
3833 GadgetInUnnamedNS gadget(21, 42);
3834 QCOMPARE(gadget.x(), 21);
3835 QCOMPARE(gadget.y(), 42);
3836 gadget.staticMetaObject.property(index: 0).writeOnGadget(gadget: &gadget, value: 12);
3837 gadget.staticMetaObject.property(index: 1).writeOnGadget(gadget: &gadget, value: 24);
3838 QCOMPARE(gadget.x(), 12);
3839 QCOMPARE(gadget.y(), 24);
3840 }
3841
3842 {
3843 ObjectInUnnamedNS object;
3844 QObject *qObject = &object;
3845 QCOMPARE(static_cast<ObjectInUnnamedNS *>(qObject),
3846 qobject_cast<ObjectInUnnamedNS *>(qObject));
3847 }
3848}
3849
3850void tst_Moc::veryLongStringData()
3851{
3852 const QMetaObject *mobj = &VeryLongStringData::staticMetaObject;
3853 QCOMPARE(mobj->classInfoCount(), 4);
3854
3855 QCOMPARE(mobj->classInfo(0).name()[0], 'n');
3856 QCOMPARE(mobj->classInfo(0).value()[0], 'i');
3857 QCOMPARE(mobj->classInfo(1).name()[0], 'e');
3858 QCOMPARE(mobj->classInfo(1).value()[0], 'r');
3859 QCOMPARE(mobj->classInfo(2).name()[0], 'o');
3860 QCOMPARE(mobj->classInfo(2).value()[0], 'b');
3861 QCOMPARE(mobj->classInfo(3).name()[0], ':');
3862 QCOMPARE(mobj->classInfo(3).value()[0], ')');
3863
3864 QCOMPARE(strlen(mobj->classInfo(0).name()), static_cast<size_t>(65534));
3865 QCOMPARE(strlen(mobj->classInfo(0).value()), static_cast<size_t>(65534));
3866 QCOMPARE(strlen(mobj->classInfo(1).name()), static_cast<size_t>(65534));
3867 QCOMPARE(strlen(mobj->classInfo(1).value()), static_cast<size_t>(65534));
3868 QCOMPARE(strlen(mobj->classInfo(2).name()), static_cast<size_t>(32768));
3869 QCOMPARE(strlen(mobj->classInfo(2).value()), static_cast<size_t>(32768));
3870 QCOMPARE(strlen(mobj->classInfo(3).name()), static_cast<size_t>(1));
3871 QCOMPARE(strlen(mobj->classInfo(3).value()), static_cast<size_t>(1));
3872}
3873
3874void tst_Moc::gadgetHierarchy()
3875{
3876 QCOMPARE(NonGadgetParent::Derived::staticMetaObject.superClass(), static_cast<const QMetaObject*>(nullptr));
3877 QCOMPARE(GrandParentGadget::DerivedGadget::staticMetaObject.superClass(), &GrandParentGadget::BaseGadget::staticMetaObject);
3878 QCOMPARE(GrandParentGadget::CRTPDerivedGadget::staticMetaObject.superClass(), &GrandParentGadget::BaseGadget::staticMetaObject);
3879}
3880
3881void tst_Moc::optionsFileError_data()
3882{
3883 QTest::addColumn<QString>(name: "optionsArgument");
3884 QTest::newRow(dataTag: "no filename") << QStringLiteral("@");
3885 QTest::newRow(dataTag: "nonexistent file") << QStringLiteral("@letshuntasnark");
3886}
3887
3888void tst_Moc::optionsFileError()
3889{
3890#ifdef MOC_CROSS_COMPILED
3891 QSKIP("Not tested when cross-compiled");
3892#endif
3893#if QT_CONFIG(process)
3894 QFETCH(QString, optionsArgument);
3895 QProcess p;
3896 p.start(program: m_moc, arguments: QStringList(optionsArgument));
3897 QVERIFY(p.waitForFinished());
3898 QCOMPARE(p.exitCode(), 1);
3899 QVERIFY(p.readAllStandardOutput().isEmpty());
3900 const QByteArray err = p.readAllStandardError();
3901 QVERIFY(err.contains("moc: "));
3902 QVERIFY(!err.contains("QCommandLineParser"));
3903#endif
3904}
3905
3906static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name, const QVector<QPair<QByteArray, int >> &keys)
3907{
3908 QCOMPARE(name, QByteArray{enumerator.name()});
3909 QCOMPARE(keys.size(), enumerator.keyCount());
3910 for (int i = 0; i < enumerator.keyCount(); ++i) {
3911 QCOMPARE(keys[i].first, QByteArray{enumerator.key(i)});
3912 QCOMPARE(keys[i].second, enumerator.value(i));
3913 }
3914}
3915
3916class EnumFromNamespaceClass : public QObject
3917{
3918 Q_OBJECT
3919 Q_PROPERTY(FooNamespace::Enum1 prop READ prop CONSTANT)
3920public:
3921 FooNamespace::Enum1 prop() { return FooNamespace::Enum1::Key2; }
3922};
3923
3924void tst_Moc::testQNamespace()
3925{
3926 QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 4);
3927 checkEnum(enumerator: TestQNamespace::staticMetaObject.enumerator(index: 0), name: "TestEnum1",
3928 keys: {{"Key1", 11}, {"Key2", 12}});
3929 checkEnum(enumerator: TestQNamespace::staticMetaObject.enumerator(index: 1), name: "TestEnum2",
3930 keys: {{"Key1", 17}, {"Key2", 18}});
3931 checkEnum(enumerator: TestQNamespace::staticMetaObject.enumerator(index: 2), name: "TestFlag1",
3932 keys: {{"None", 0}, {"Flag1", 1}, {"Flag2", 2}, {"Any", 1 | 2}});
3933 checkEnum(enumerator: TestQNamespace::staticMetaObject.enumerator(index: 3), name: "TestFlag2",
3934 keys: {{"None", 0}, {"Flag1", 4}, {"Flag2", 8}, {"Any", 4 | 8}});
3935
3936 QCOMPARE(TestQNamespace::TestGadget::staticMetaObject.enumeratorCount(), 2);
3937 checkEnum(enumerator: TestQNamespace::TestGadget::staticMetaObject.enumerator(index: 0), name: "TestGEnum1",
3938 keys: {{"Key1", 13}, {"Key2", 14}});
3939 checkEnum(enumerator: TestQNamespace::TestGadget::staticMetaObject.enumerator(index: 1), name: "TestGEnum2",
3940 keys: {{"Key1", 23}, {"Key2", 24}});
3941
3942 QMetaEnum meta = QMetaEnum::fromType<TestQNamespace::TestEnum1>();
3943 QVERIFY(meta.isValid());
3944 QCOMPARE(meta.name(), "TestEnum1");
3945 QCOMPARE(meta.enclosingMetaObject(), &TestQNamespace::staticMetaObject);
3946 QCOMPARE(meta.keyCount(), 2);
3947
3948 QCOMPARE(TestExportNamespace::staticMetaObject.enumeratorCount(), 1);
3949 checkEnum(enumerator: TestExportNamespace::staticMetaObject.enumerator(index: 0), name: "MyEnum",
3950 keys: {{"Key1", 0}, {"Key2", 1}});
3951
3952 QCOMPARE(FooNamespace::staticMetaObject.enumeratorCount(), 1);
3953 QCOMPARE(FooNamespace::FooNestedNamespace::staticMetaObject.enumeratorCount(), 2);
3954 QCOMPARE(FooNamespace::FooNestedNamespace::FooMoreNestedNamespace::staticMetaObject.enumeratorCount(), 1);
3955
3956 EnumFromNamespaceClass obj;
3957 const QVariant prop = obj.property(name: "prop");
3958 QCOMPARE(prop.type(), QMetaType::Int);
3959 QCOMPARE(prop.toInt(), int(FooNamespace::Enum1::Key2));
3960}
3961
3962void tst_Moc::cxx17Namespaces()
3963{
3964 QCOMPARE(CXX17Namespace::A::B::C::D::staticMetaObject.className(),
3965 "CXX17Namespace::A::B::C::D");
3966 QCOMPARE(CXX17Namespace::A::B::C::D::staticMetaObject.enumeratorCount(), 1);
3967 QCOMPARE(CXX17Namespace::A::B::C::D::staticMetaObject.enumerator(0).name(), "NamEn");
3968 QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::NamEn>().name(), "NamEn");
3969 QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::NamEn>().keyCount(), 1);
3970 QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::NamEn>().value(0), 4);
3971
3972 QCOMPARE(CXX17Namespace::A::B::C::D::ClassInNamespace::staticMetaObject.className(),
3973 "CXX17Namespace::A::B::C::D::ClassInNamespace");
3974 QCOMPARE(CXX17Namespace::A::B::C::D::ClassInNamespace::staticMetaObject.enumeratorCount(), 1);
3975 QCOMPARE(CXX17Namespace::A::B::C::D::ClassInNamespace::staticMetaObject.enumerator(0).name(), "GadEn");
3976 QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().name(), "GadEn");
3977 QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().keyCount(), 1);
3978 QCOMPARE(QMetaEnum::fromType<CXX17Namespace::A::B::C::D::ClassInNamespace::GadEn>().value(0), 3);
3979}
3980
3981void tst_Moc::cxxAttributes()
3982{
3983 auto so = CppAttribute::staticMetaObject;
3984 QCOMPARE(so.className(), "CppAttribute");
3985 QCOMPARE(so.enumeratorCount(), 0);
3986 QVERIFY(so.indexOfSignal("deprecatedSignal") != 1);
3987 for (auto a: {"deprecatedSlot", "deprecatedSlot2", "deprecatedReason", "deprecatedReasonWithLBRACK",
3988 "deprecatedReasonWith2LBRACK", "deprecatedReasonWithRBRACK", "deprecatedReasonWith2RBRACK",
3989 "slotWithArguments"
3990#if !defined(_MSC_VER) || _MSC_VER >= 1912
3991 , "noreturnSlot", "noreturnSlot2", "returnInt", "noreturnDeprecatedSlot",
3992 "noreturnSlot3"
3993#endif
3994 }) {
3995 QVERIFY(so.indexOfSlot(a) != 1);
3996 }
3997
3998 QCOMPARE(TestQNamespaceDeprecated::staticMetaObject.enumeratorCount(), 2);
3999 checkEnum(enumerator: TestQNamespaceDeprecated::staticMetaObject.enumerator(index: 0), name: "TestEnum1",
4000 keys: {{"Key1", 11}, {"Key2", 12}, {"Key3", 13}, {"Key4", 14}, {"Key5", 15}, {"Key6", 16},
4001 {"Key7", 17}});
4002 checkEnum(enumerator: TestQNamespaceDeprecated::staticMetaObject.enumerator(index: 1), name: "TestFlag1",
4003 keys: {{"None", 0}, {"Flag1", 1}, {"Flag2", 2}, {"Flag3", 3}, {"Any", 1 | 2 | 3}});
4004
4005 QCOMPARE(TestQNamespaceDeprecated::TestGadget::staticMetaObject.enumeratorCount(), 1);
4006 checkEnum(enumerator: TestQNamespaceDeprecated::TestGadget::staticMetaObject.enumerator(index: 0), name: "TestGEnum1",
4007 keys: {{"Key1", 13}, {"Key2", 14}, {"Key3", 15}});
4008
4009 QMetaEnum meta = QMetaEnum::fromType<TestQNamespaceDeprecated::TestEnum1>();
4010 QVERIFY(meta.isValid());
4011 QCOMPARE(meta.name(), "TestEnum1");
4012 QCOMPARE(meta.enclosingMetaObject(), &TestQNamespaceDeprecated::staticMetaObject);
4013 QCOMPARE(meta.keyCount(), 7);
4014}
4015
4016void tst_Moc::mocJsonOutput()
4017{
4018 const auto readFile = [](const QString &fileName) {
4019 QFile f(fileName);
4020 f.open(flags: QIODevice::ReadOnly);
4021 return QJsonDocument::fromJson(json: f.readAll());
4022 };
4023
4024 const QString actualFile = QStringLiteral(":/allmocs.json");
4025 const QString expectedFile = QStringLiteral(":/allmocs_baseline.json");
4026
4027 QVERIFY2(QFile::exists(actualFile), qPrintable(actualFile));
4028 QVERIFY2(QFile::exists(expectedFile), qPrintable(expectedFile));
4029
4030 QJsonDocument actualOutput = readFile(QLatin1String(":/allmocs.json"));
4031 QJsonDocument expectedOutput = readFile(QLatin1String(":/allmocs_baseline.json"));
4032
4033 const auto showPotentialDiff = [](const QJsonDocument &actual, const QJsonDocument &expected) -> QByteArray {
4034#if defined(Q_OS_UNIX)
4035 QByteArray actualStr = actual.toJson();
4036 QByteArray expectedStr = expected.toJson();
4037
4038 QTemporaryFile actualFile;
4039 if (!actualFile.open())
4040 return "Error opening actual temp file";
4041 actualFile.write(data: actualStr);
4042 actualFile.flush();
4043
4044 QTemporaryFile expectedFile;
4045 if (!expectedFile.open())
4046 return "Error opening expected temp file";
4047 expectedFile.write(data: expectedStr);
4048 expectedFile.flush();
4049
4050 QProcess diffProc;
4051 diffProc.setProgram("diff");
4052 diffProc.setArguments(QStringList() << "-ub" << expectedFile.fileName() << actualFile.fileName());
4053 diffProc.start();
4054 if (!diffProc.waitForStarted())
4055 return "Error waiting for diff process to start.";
4056 if (!diffProc.waitForFinished())
4057 return "Error waiting for diff process to finish.";
4058 return diffProc.readAllStandardOutput();
4059#else
4060 return "Cannot launch diff. Please check allmocs.json and allmocs_baseline.json on disk.";
4061#endif
4062 };
4063
4064 QVERIFY2(actualOutput == expectedOutput, showPotentialDiff(actualOutput, expectedOutput).constData());
4065}
4066
4067class RequiredTest :public QObject
4068{
4069 Q_OBJECT
4070
4071 Q_PROPERTY(int required MEMBER m_required REQUIRED)
4072 Q_PROPERTY(int notRequired MEMBER m_notRequired)
4073
4074private:
4075 int m_required;
4076 int m_notRequired;
4077};
4078
4079void tst_Moc::requiredProperties()
4080{
4081 QMetaObject mo = RequiredTest::staticMetaObject;
4082 QMetaProperty required = mo.property(index: mo.indexOfProperty(name: "required"));
4083 QVERIFY(required.isValid());
4084 QVERIFY(required.isRequired());
4085 QMetaProperty notRequired = mo.property(index: mo.indexOfProperty(name: "notRequired"));
4086 QVERIFY(notRequired.isValid());
4087 QVERIFY(!notRequired.isRequired());
4088}
4089
4090QTEST_MAIN(tst_Moc)
4091
4092// the generated code must compile with QT_NO_KEYWORDS
4093#undef signals
4094#undef slots
4095#undef emit
4096
4097#include "tst_moc.moc"
4098
4099

source code of qtbase/tests/auto/tools/moc/tst_moc.cpp