tests/auto/moc/tst_moc.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/auto/moc/tst_moc.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#include <QtTest/QtTest>
+#include <stdio.h>
+#include <qobject.h>
+
+#include "using-namespaces.h"
+#include "assign-namespace.h"
+#include "no-keywords.h"
+#include "single_function_keyword.h"
+#include "backslash-newlines.h"
+#include "slots-with-void-template.h"
+#include "pure-virtual-signals.h"
+#include "qinvokable.h"
+// msvc and friends crap out on it
+#if !defined(Q_CC_GNU) || defined(Q_OS_IRIX) || defined(Q_OS_WIN)
+#define SKIP_NEWLINE_TEST
+#endif
+#if !defined(SKIP_NEWLINE_TEST)
+#include "os9-newlines.h"
+// msvc and friends crap out on this file too,
+// it seems to contain Mac 9 EOLs, and not windows EOLs.
+#include "win-newlines.h"
+#endif
+#include "escapes-in-string-literals.h"
+#include "cstyle-enums.h"
+
+
+#if defined(PARSE_BOOST)
+#include "parse-boost.h"
+#endif
+
+// No such thing as "long long" in Microsoft's compiler 13.0 and before
+#if defined Q_CC_MSVC && _MSC_VER <= 1310
+#  define NOLONGLONG
+#endif
+
+QT_USE_NAMESPACE
+
+struct MyStruct {};
+struct MyStruct2 {};
+
+struct SuperClass {};
+
+// Try to avoid inserting for instance a comment with a quote between the following line and the Q_OBJECT
+// That will make the test give a false positive.
+const char* test_multiple_number_of_escapes =   "\\\"";
+namespace MyNamespace
+{
+    class TestSuperClass : public QObject
+    {
+        Q_OBJECT
+        public:
+            inline TestSuperClass() {}
+    };
+}
+
+namespace String
+{
+    typedef QString Type;
+}
+
+namespace Int
+{
+    typedef int Type;
+}
+
+typedef struct {
+    int doNotConfuseMoc;
+} OldStyleCStruct;
+
+class Sender : public QObject
+{
+    Q_OBJECT
+
+public:
+    void sendValue(const String::Type& value)
+    {
+        emit send(value);
+    }
+    void sendValue(const Int::Type& value)
+    {
+        emit send(value);
+    }
+
+signals:
+    void send(const String::Type&);
+    void send(const Int::Type&);
+};
+
+class Receiver : public QObject
+{
+    Q_OBJECT
+public:
+    Receiver() : stringCallCount(0), intCallCount(0) {}
+
+    int stringCallCount;
+    int intCallCount;
+
+public slots:
+    void receive(const String::Type&) { stringCallCount++; }
+    void receive(const Int::Type&)    { intCallCount++; }
+};
+
+#define MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES
+
+#define DONT_CONFUSE_MOC(klass) klass
+#define DONT_CONFUSE_MOC_EVEN_MORE(klass, dummy, dummy2) klass
+
+Q_DECLARE_METATYPE(MyStruct)
+Q_DECLARE_METATYPE(MyStruct*)
+
+namespace myNS {
+    struct Points
+    {
+        Points() : p1(0xBEEF), p2(0xBABE) { }
+        int p1, p2;
+    };
+}
+
+Q_DECLARE_METATYPE(myNS::Points)
+
+class TestClassinfoWithEscapes: public QObject
+{
+    Q_OBJECT
+    Q_CLASSINFO("escaped", "\"bar\"")
+    Q_CLASSINFO("\"escaped\"", "foo")
+public slots:
+    void slotWithAReallyLongName(int)
+    { }
+};
+
+struct ForwardDeclaredStruct;
+
+struct StructQObject : public QObject
+{
+    Q_OBJECT
+public:
+    void foo(struct ForwardDeclaredStruct *);
+};
+
+void StructQObject::foo(struct ForwardDeclaredStruct *)
+{
+    struct Inner {
+        bool field;
+    };
+
+    struct Inner unusedVariable;
+}
+
+class TestClass : public MyNamespace::TestSuperClass, public DONT_CONFUSE_MOC(MyStruct),
+                  public DONT_CONFUSE_MOC_EVEN_MORE(MyStruct2, dummy, ignored)
+{
+    Q_OBJECT
+    Q_CLASSINFO("help", QT_TR_NOOP("Opening this will let you configure something"))
+    Q_PROPERTY(short int shortIntProperty READ shortIntProperty)
+    Q_PROPERTY(unsigned short int unsignedShortIntProperty READ unsignedShortIntProperty)
+    Q_PROPERTY(signed short int signedShortIntProperty READ signedShortIntProperty)
+    Q_PROPERTY(long int longIntProperty READ longIntProperty)
+    Q_PROPERTY(unsigned long int unsignedLongIntProperty READ unsignedLongIntProperty)
+    Q_PROPERTY(signed long int signedLongIntProperty READ signedLongIntProperty)
+    Q_PROPERTY(long double longDoubleProperty READ longDoubleProperty)
+    Q_PROPERTY(myNS::Points points READ points WRITE setPoints)
+
+    Q_CLASSINFO("Multi"
+                "line",
+                ""
+                "This is a "
+                "multiline Q_CLASSINFO"
+                "")
+
+    // a really really long string that we have to cut into pieces in the generated stringdata
+    // table, otherwise msvc craps out
+    Q_CLASSINFO("D-Bus Introspection", ""
+"  <interface name=\"org.kde.KCookieServer\" >\n"
+"    <method name=\"findCookies\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
+"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
+"      <arg direction=\"out\" type=\"s\" name=\"cookies\" />\n"
+"    </method>\n"
+"    <method name=\"findDomains\" >\n"
+"      <arg direction=\"out\" type=\"as\" name=\"domains\" />\n"
+"    </method>\n"
+"    <method name=\"findCookies\" >\n"
+"      <arg direction=\"in\" type=\"ai\" name=\"fields\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"path\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"name\" />\n"
+"      <arg direction=\"out\" type=\"as\" name=\"cookies\" />\n"
+"      <annotation value=\"QList&lt;int>\" name=\"com.trolltech.QtDBus.QtTypeName.In0\" />\n"
+"    </method>\n"
+"    <method name=\"findDOMCookies\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
+"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
+"      <arg direction=\"out\" type=\"s\" name=\"cookies\" />\n"
+"    </method>\n"
+"    <method name=\"addCookies\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
+"      <arg direction=\"in\" type=\"ay\" name=\"cookieHeader\" />\n"
+"      <arg direction=\"in\" type=\"x\" name=\"windowId\"  />\n"
+"    </method>\n"
+"    <method name=\"deleteCookie\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"path\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"name\" />\n"
+"    </method>\n"
+"    <method name=\"deleteCookiesFromDomain\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
+"    </method>\n"
+"    <method name=\"deleteSessionCookies\" >\n"
+"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
+"    </method>\n"
+"    <method name=\"deleteSessionCookiesFor\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
+"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
+"    </method>\n"
+"    <method name=\"deleteAllCookies\" />\n"
+"    <method name=\"addDOMCookies\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
+"      <arg direction=\"in\" type=\"ay\" name=\"cookieHeader\" />\n"
+"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
+"    </method>\n"
+"    <method name=\"setDomainAdvice\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
+"      <arg direction=\"in\" type=\"s\" name=\"advice\" />\n"
+"    </method>\n"
+"    <method name=\"getDomainAdvice\" >\n"
+"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
+"      <arg direction=\"out\" type=\"s\" name=\"advice\" />\n"
+"    </method>\n"
+"    <method name=\"reloadPolicy\" />\n"
+"    <method name=\"shutdown\" />\n"
+"  </interface>\n"
+        "")
+
+public:
+    inline TestClass() {}
+
+private slots:
+    inline void dummy1() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES {}
+    inline void dummy2() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES const {}
+    inline void dummy3() const MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES {}
+
+#ifndef NOLONGLONG
+    void slotWithULongLong(unsigned long long) {}
+    void slotWithULongLongP(unsigned long long*) {}
+    void slotWithULong(unsigned long) {}
+    void slotWithLongLong(long long) {}
+    void slotWithLong(long) {}
+#endif
+
+    void slotWithColonColonType(::Int::Type) {}
+
+    TestClass &slotWithReferenceReturnType() { return *this; }
+
+#if (0 && 1) || 1
+    void expressionEvaluationShortcut1() {}
+#endif
+#if (1 || 0) && 0
+#else
+    void expressionEvaluationShortcut2() {}
+#endif
+
+public slots:
+    void slotWithArray(const double[3]) {}
+    void slotWithNamedArray(const double namedArray[3]) {}
+    void slotWithMultiArray(const double[3][4]) {}
+
+    short int shortIntProperty() { return 0; }
+    unsigned short int unsignedShortIntProperty() { return 0; }
+    signed short int signedShortIntProperty() { return 0; }
+    long int longIntProperty() { return 0; }
+    unsigned long int unsignedLongIntProperty() { return 0; }
+    signed long int signedLongIntProperty() { return 0; }
+    long double longDoubleProperty() { return 0.0; }
+
+    myNS::Points points() { return m_points; }
+    void setPoints(myNS::Points points) { m_points = points; }
+
+signals:
+    void signalWithArray(const double[3]);
+    void signalWithNamedArray(const double namedArray[3]);
+
+private slots:
+    // for tst_Moc::preprocessorConditionals
+#if 0
+    void invalidSlot() {}
+#else
+    void slotInElse() {}
+#endif
+
+#if 1
+    void slotInIf() {}
+#else
+    void invalidSlot() {}
+#endif
+
+#if 0
+    void invalidSlot() {}
+#elif 0
+#else
+    void slotInLastElse() {}
+#endif
+
+#if 0
+    void invalidSlot() {}
+#elif 1
+    void slotInElif() {}
+#else
+    void invalidSlot() {}
+#endif
+
+
+    friend class Receiver; // task #85783
+signals:
+    friend class Sender; // task #85783
+
+public slots:
+    void const slotWithSillyConst() {}
+
+public:
+    Q_INVOKABLE void const slotWithSillyConst2() {}
+
+    // that one however should be fine
+public slots:
+    void slotWithVoidStar(void *) {}
+
+private:
+     myNS::Points m_points;
+
+private slots:
+     inline virtual void blub1() {}
+     virtual inline void blub2() {}
+};
+
+class PropertyTestClass : public QObject
+{
+    Q_OBJECT
+public:
+
+    enum TestEnum { One, Two, Three };
+
+    Q_ENUMS(TestEnum)
+};
+
+class PropertyUseClass : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(PropertyTestClass::TestEnum foo READ foo)
+public:
+
+    inline PropertyTestClass::TestEnum foo() const { return PropertyTestClass::One; }
+};
+
+#if defined(Q_MOC_RUN)
+// Task #119503
+#define _TASK_119503
+#if !_TASK_119503
+#endif
+#endif
+
+static QString srcify(const char *path)
+{
+#ifndef Q_OS_IRIX
+    return QString(SRCDIR) + QLatin1Char('/') + QLatin1String(path);
+#else
+    return QString(QLatin1String(path));
+#endif
+}
+
+class CtorTestClass : public QObject
+{
+    Q_OBJECT
+public:
+    Q_INVOKABLE CtorTestClass(QObject *parent = 0);
+
+    CtorTestClass(int foo);
+
+    inline Q_INVOKABLE CtorTestClass(const QString &str)
+        { m_str = str; }
+
+    QString m_str;
+
+protected:
+    CtorTestClass(int foo, int bar, int baz);
+private:
+    CtorTestClass(float, float) {}
+};
+
+CtorTestClass::CtorTestClass(QObject *parent)
+    : QObject(parent) {}
+
+CtorTestClass::CtorTestClass(int, int, int) {}
+
+
+class tst_Moc : public QObject
+{
+    Q_OBJECT
+
+    Q_PROPERTY(bool user1 READ user1 USER true )
+    Q_PROPERTY(bool user2 READ user2 USER false)
+    Q_PROPERTY(bool user3 READ user3 USER userFunction())
+
+public:
+    inline tst_Moc() {}
+
+private slots:
+    void initTestCase();
+
+    void slotWithException() throw(MyStruct);
+    void dontStripNamespaces();
+    void oldStyleCasts();
+    void warnOnExtraSignalSlotQualifiaction();
+    void uLongLong();
+    void inputFileNameWithDotsButNoExtension();
+    void userProperties();
+    void supportConstSignals();
+    void task87883();
+    void multilineComments();
+    void classinfoWithEscapes();
+    void trNoopInClassInfo();
+    void ppExpressionEvaluation();
+    void arrayArguments();
+    void preprocessorConditionals();
+    void blackslashNewlines();
+    void slotWithSillyConst();
+    void testExtraData();
+    void namespaceTypeProperty();
+    void slotsWithVoidTemplate();
+    void structQObject();
+    void namespacedFlags();
+    void warnOnMultipleInheritance();
+    void forgottenQInterface();
+    void os9Newline();
+    void winNewline();
+    void escapesInStringLiterals();
+    void frameworkSearchPath();
+    void cstyleEnums();
+    void defineMacroViaCmdline();
+    void invokable();
+    void singleFunctionKeywordSignalAndSlot();
+    void templateGtGt();
+    void qprivateslots();
+    void inlineSlotsWithThrowDeclaration();
+    void warnOnPropertyWithoutREAD();
+    void constructors();
+    void typenameWithUnsigned();
+    void warnOnVirtualSignal();
+
+signals:
+    void sigWithUnsignedArg(unsigned foo);
+    void sigWithSignedArg(signed foo);
+    void sigWithConstSignedArg(const signed foo);
+    void sigWithVolatileConstSignedArg(volatile const signed foo);
+    void sigWithCustomType(const MyStruct);
+    void constSignal1() const;
+    void constSignal2(int arg) const;
+
+private:
+    bool user1() { return true; };
+    bool user2() { return false; };
+    bool user3() { return false; };
+    bool userFunction(){ return false; };
+
+private:
+    QString qtIncludePath;
+};
+
+void tst_Moc::initTestCase()
+{
+#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    proc.start("qmake", QStringList() << "-query" << "QT_INSTALL_HEADERS");
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray output = proc.readAllStandardOutput();
+    QVERIFY(!output.isEmpty());
+    QCOMPARE(proc.readAllStandardError(), QByteArray());
+    qtIncludePath = QString::fromLocal8Bit(output).trimmed();
+    QFileInfo fi(qtIncludePath);
+    QVERIFY(fi.exists());
+    QVERIFY(fi.isDir());
+#endif
+}
+
+void tst_Moc::slotWithException() throw(MyStruct)
+{
+    // be happy
+    QVERIFY(true);
+}
+
+void tst_Moc::dontStripNamespaces()
+{
+    Sender sender;
+    Receiver receiver;
+
+    connect(&sender, SIGNAL(send(const String::Type &)),
+            &receiver, SLOT(receive(const String::Type &)));
+    connect(&sender, SIGNAL(send(const Int::Type &)),
+            &receiver, SLOT(receive(const Int::Type &)));
+
+    sender.sendValue(String::Type("Hello"));
+    QCOMPARE(receiver.stringCallCount, 1);
+    QCOMPARE(receiver.intCallCount, 0);
+    sender.sendValue(Int::Type(42));
+    QCOMPARE(receiver.stringCallCount, 1);
+    QCOMPARE(receiver.intCallCount, 1);
+}
+
+
+void tst_Moc::oldStyleCasts()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    proc.start("moc", QStringList(srcify("/oldstyle-casts.h")));
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QCOMPARE(proc.readAllStandardError(), QByteArray());
+
+    QStringList args;
+    args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
+         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-";
+    proc.start("gcc", args);
+    QVERIFY(proc.waitForStarted());
+    proc.write(mocOut);
+    proc.closeWriteChannel();
+
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::warnOnExtraSignalSlotQualifiaction()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    proc.start("moc", QStringList(srcify("extraqualification.h")));
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
+    QCOMPARE(mocWarning, QString(SRCDIR) +
+                QString("/extraqualification.h:53: Warning: Function declaration Test::badFunctionDeclaration contains extra qualification. Ignoring as signal or slot.\n") +
+                QString(SRCDIR) + QString("/extraqualification.h:56: Warning: parsemaybe: Function declaration Test::anotherOne contains extra qualification. Ignoring as signal or slot.\n"));
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::uLongLong()
+{
+#ifndef NOLONGLONG
+    TestClass tst;
+    const QMetaObject *mobj = tst.metaObject();
+    int idx = mobj->indexOfSlot("slotWithULong(ulong)");
+    QVERIFY(idx != -1);
+    idx = mobj->indexOfSlot("slotWithULongLong(unsigned long long)");
+    QVERIFY(idx != -1);
+    idx = mobj->indexOfSlot("slotWithULongLongP(unsigned long long*)");
+    QVERIFY(idx != -1);
+
+    idx = mobj->indexOfSlot("slotWithLong(long)");
+    QVERIFY(idx != -1);
+    idx = mobj->indexOfSlot("slotWithLongLong(long long)");
+    QVERIFY(idx != -1);
+#else
+    QSKIP("long long doesn't work on MSVC6 & .NET 2002, also skipped on 2003 due to compiler version issue with moc", SkipAll);
+#endif
+}
+
+void tst_Moc::inputFileNameWithDotsButNoExtension()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    proc.setWorkingDirectory(QString(SRCDIR) + "/task71021");
+    proc.start("moc", QStringList("../Header"));
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QCOMPARE(proc.readAllStandardError(), QByteArray());
+
+    QStringList args;
+    args << "-c" << "-x" << "c++" << "-I" << ".."
+         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-";
+    proc.start("gcc", args);
+    QVERIFY(proc.waitForStarted());
+    proc.write(mocOut);
+    proc.closeWriteChannel();
+
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
+    QCOMPARE(proc.exitCode(), 0);
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::userProperties()
+{
+    const QMetaObject *mobj = metaObject();
+    QMetaProperty property = mobj->property(mobj->indexOfProperty("user1"));
+    QVERIFY(property.isValid());
+    QVERIFY(property.isUser());
+
+    property = mobj->property(mobj->indexOfProperty("user2"));
+    QVERIFY(property.isValid());
+    QVERIFY(!property.isUser());
+
+    property = mobj->property(mobj->indexOfProperty("user3"));
+    QVERIFY(property.isValid());
+    QVERIFY(!property.isUser(this));
+}
+
+void tst_Moc::supportConstSignals()
+{
+    QSignalSpy spy1(this, SIGNAL(constSignal1()));
+    QVERIFY(spy1.isEmpty());
+    emit constSignal1();
+    QCOMPARE(spy1.count(), 1);
+
+    QSignalSpy spy2(this, SIGNAL(constSignal2(int)));
+    QVERIFY(spy2.isEmpty());
+    emit constSignal2(42);
+    QCOMPARE(spy2.count(), 1);
+    QCOMPARE(spy2.at(0).at(0).toInt(), 42);
+}
+
+#include "task87883.h"
+
+void tst_Moc::task87883()
+{
+    QVERIFY(Task87883::staticMetaObject.className());
+}
+
+#include "c-comments.h"
+
+void tst_Moc::multilineComments()
+{
+    QVERIFY(IfdefedClass::staticMetaObject.className());
+}
+
+void tst_Moc::classinfoWithEscapes()
+{
+    const QMetaObject *mobj = &TestClassinfoWithEscapes::staticMetaObject;
+    QCOMPARE(mobj->methodCount() - mobj->methodOffset(), 1);
+
+    QMetaMethod mm = mobj->method(mobj->methodOffset());
+    QCOMPARE(mm.signature(), "slotWithAReallyLongName(int)");
+}
+
+void tst_Moc::trNoopInClassInfo()
+{
+    TestClass t;
+    const QMetaObject *mobj = t.metaObject();
+    QVERIFY(mobj);
+    QCOMPARE(mobj->classInfoCount(), 3);
+    QCOMPARE(mobj->indexOfClassInfo("help"), 0);
+    QCOMPARE(QString(mobj->classInfo(0).value()), QString("Opening this will let you configure something"));
+}
+
+void tst_Moc::ppExpressionEvaluation()
+{
+    TestClass tst;
+    const QMetaObject *mobj = tst.metaObject();
+    int idx = mobj->indexOfSlot("expressionEvaluationShortcut1()");
+    QVERIFY(idx != -1);
+
+    idx = mobj->indexOfSlot("expressionEvaluationShortcut2()");
+    QVERIFY(idx != -1);
+}
+
+void tst_Moc::arrayArguments()
+{
+    TestClass tst;
+    const QMetaObject *mobj = tst.metaObject();
+    QVERIFY(mobj->indexOfSlot("slotWithArray(const double[3])") != -1);
+    QVERIFY(mobj->indexOfSlot("slotWithNamedArray(const double[3])") != -1);
+    QVERIFY(mobj->indexOfSlot("slotWithMultiArray(const double[3][4])") != -1);
+    QVERIFY(mobj->indexOfSignal("signalWithArray(const double[3])") != -1);
+    QVERIFY(mobj->indexOfSignal("signalWithNamedArray(const double[3])") != -1);
+}
+
+void tst_Moc::preprocessorConditionals()
+{
+    TestClass tst;
+    const QMetaObject *mobj = tst.metaObject();
+    QVERIFY(mobj->indexOfSlot("slotInElse()") != -1);
+    QVERIFY(mobj->indexOfSlot("slotInIf()") != -1);
+    QVERIFY(mobj->indexOfSlot("slotInLastElse()") != -1);
+    QVERIFY(mobj->indexOfSlot("slotInElif()") != -1);
+}
+
+void tst_Moc::blackslashNewlines()
+{
+    BackslashNewlines tst;
+    const QMetaObject *mobj = tst.metaObject();
+    QVERIFY(mobj->indexOfSlot("works()") != -1);
+    QVERIFY(mobj->indexOfSlot("buggy()") == -1);
+}
+
+void tst_Moc::slotWithSillyConst()
+{
+    TestClass tst;
+    const QMetaObject *mobj = tst.metaObject();
+    QVERIFY(mobj->indexOfSlot("slotWithSillyConst()") != -1);
+    QVERIFY(mobj->indexOfMethod("slotWithSillyConst2()") != -1);
+    QVERIFY(mobj->indexOfSlot("slotWithVoidStar(void*)") != -1);
+}
+
+void tst_Moc::testExtraData()
+{
+    const QMetaObject *mobj = &PropertyTestClass::staticMetaObject;
+    QCOMPARE(mobj->enumeratorCount(), 1);
+    QCOMPARE(QByteArray(mobj->enumerator(0).name()), QByteArray("TestEnum"));
+
+    mobj = &PropertyUseClass::staticMetaObject;
+    const int idx = mobj->indexOfProperty("foo");
+    QVERIFY(idx != -1);
+    const QMetaProperty prop = mobj->property(idx);
+    QVERIFY(prop.isValid());
+    QVERIFY(prop.isEnumType());
+    const QMetaEnum en = prop.enumerator();
+    QCOMPARE(QByteArray(en.name()), QByteArray("TestEnum"));
+}
+
+void tst_Moc::namespaceTypeProperty()
+{
+    qRegisterMetaType<myNS::Points>("myNS::Points");
+    TestClass tst;
+    QByteArray ba = QByteArray("points");
+    QVariant v = tst.property(ba);
+    QVERIFY(v.isValid());
+    myNS::Points p = qVariantValue<myNS::Points>(v);
+    QCOMPARE(p.p1, 0xBEEF);
+    QCOMPARE(p.p2, 0xBABE);
+    p.p1 = 0xCAFE;
+    p.p2 = 0x1EE7;
+    QVERIFY(tst.setProperty(ba, qVariantFromValue(p)));
+    myNS::Points pp = qVariantValue<myNS::Points>(tst.property(ba));
+    QCOMPARE(p.p1, pp.p1);
+    QCOMPARE(p.p2, pp.p2);
+}
+
+void tst_Moc::slotsWithVoidTemplate()
+{
+    SlotsWithVoidTemplateTest test;
+    QVERIFY(QObject::connect(&test, SIGNAL(myVoidSignal(void)),
+                             &test, SLOT(dummySlot(void))));
+    QVERIFY(QObject::connect(&test, SIGNAL(mySignal(const TestTemplate<void> &)),
+                             &test, SLOT(anotherSlot(const TestTemplate<void> &))));
+}
+
+void tst_Moc::structQObject()
+{
+    StructQObject o;
+    QCOMPARE(QByteArray(o.metaObject()->className()), QByteArray("StructQObject"));
+}
+
+#include "namespaced-flags.h"
+
+void tst_Moc::namespacedFlags()
+{
+    Foo::Baz baz;
+    Foo::Bar bar;
+
+    bar.setFlags(Foo::Bar::Read | Foo::Bar::Write);
+    QVERIFY(baz.flags() != bar.flags());
+
+    const QVariant v = bar.property("flags");
+    QVERIFY(v.isValid());
+    QVERIFY(baz.setProperty("flags", v));
+    QVERIFY(baz.flags() == bar.flags());
+}
+
+void tst_Moc::warnOnMultipleInheritance()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    QStringList args;
+    args << "-I" << qtIncludePath + "/QtGui"
+         << srcify("warn-on-multiple-qobject-subclasses.h");
+    proc.start("moc", args);
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
+    QCOMPARE(mocWarning, QString(SRCDIR) +
+                QString("/warn-on-multiple-qobject-subclasses.h:53: Warning: Class Bar inherits from two QObject subclasses QWidget and Foo. This is not supported!\n"));
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::forgottenQInterface()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    QStringList args;
+    args << "-I" << qtIncludePath + "/QtCore"
+         << srcify("forgotten-qinterface.h");
+    proc.start("moc", args);
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
+    QCOMPARE(mocWarning, QString(SRCDIR) +
+                QString("/forgotten-qinterface.h:55: Warning: Class Test implements the interface MyInterface but does not list it in Q_INTERFACES. qobject_cast to MyInterface will not work!\n"));
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::os9Newline()
+{
+#if !defined(SKIP_NEWLINE_TEST)
+    const QMetaObject &mo = Os9Newlines::staticMetaObject;
+    QVERIFY(mo.indexOfSlot("testSlot()") != -1);
+    QFile f(srcify("os9-newlines.h"));
+    QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
+    QByteArray data = f.readAll();
+    f.close();
+    QVERIFY(!data.contains('\n'));
+    QVERIFY(data.contains('\r'));
+#endif
+}
+
+void tst_Moc::winNewline()
+{
+#if !defined(SKIP_NEWLINE_TEST)
+    const QMetaObject &mo = WinNewlines::staticMetaObject;
+    QVERIFY(mo.indexOfSlot("testSlot()") != -1);
+    QFile f(srcify("win-newlines.h"));
+    QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
+    QByteArray data = f.readAll();
+    f.close();
+    for (int i = 0; i < data.count(); ++i) {
+        if (data.at(i) == QLatin1Char('\r')) {
+            QVERIFY(i < data.count() - 1);
+            ++i;
+            QVERIFY(data.at(i) == '\n');
+        } else {
+            QVERIFY(data.at(i) != '\n');
+        }
+    }
+#endif
+}
+
+void tst_Moc::escapesInStringLiterals()
+{
+    const QMetaObject &mo = StringLiterals::staticMetaObject;
+    QCOMPARE(mo.classInfoCount(), 3);
+
+    int idx = mo.indexOfClassInfo("Test");
+    QVERIFY(idx != -1);
+    QMetaClassInfo info = mo.classInfo(idx);
+    QCOMPARE(QByteArray(info.value()),
+             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x53"));
+
+    QVERIFY(idx != -1);
+    idx = mo.indexOfClassInfo("Test2");
+    info = mo.classInfo(idx);
+    QCOMPARE(QByteArray(info.value()),
+             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\123"));
+
+    QVERIFY(idx != -1);
+    idx = mo.indexOfClassInfo("Test3");
+    info = mo.classInfo(idx);
+    QCOMPARE(QByteArray(info.value()),
+             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\nb"));
+}
+
+void tst_Moc::frameworkSearchPath()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS)
+    QStringList args;
+    args << "-F" << srcify(".")
+         << srcify("interface-from-framework.h")
+         ;
+
+    QProcess proc;
+    proc.start("moc", args);
+    bool finished = proc.waitForFinished();
+    if (!finished)
+        qWarning("waitForFinished failed. QProcess error: %d", (int)proc.error());
+    QVERIFY(finished);
+    if (proc.exitCode() != 0) {
+        qDebug() << proc.readAllStandardError();
+    }
+    QCOMPARE(proc.exitCode(), 0);
+    QCOMPARE(proc.readAllStandardError(), QByteArray());
+#else
+    QSKIP("Only tested/relevant on unixy platforms", SkipAll);
+#endif
+}
+
+void tst_Moc::cstyleEnums()
+{
+    const QMetaObject &obj = CStyleEnums::staticMetaObject;
+    QCOMPARE(obj.enumeratorCount(), 1);
+    QMetaEnum metaEnum = obj.enumerator(0);
+    QCOMPARE(metaEnum.name(), "Baz");
+    QCOMPARE(metaEnum.keyCount(), 2);
+    QCOMPARE(metaEnum.key(0), "Foo");
+    QCOMPARE(metaEnum.key(1), "Bar");
+}
+
+void tst_Moc::templateGtGt()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    proc.start("moc", QStringList(srcify("template-gtgt.h")));
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
+    QVERIFY(mocWarning.isEmpty());
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::defineMacroViaCmdline()
+{
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+
+    QStringList args;
+    args << "-DFOO";
+    args << srcify("macro-on-cmdline.h");
+
+    proc.start("moc", args);
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QCOMPARE(proc.readAllStandardError(), QByteArray());
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::invokable()
+{
+    {
+        const QMetaObject &mobj = InvokableBeforeReturnType::staticMetaObject;
+        QCOMPARE(mobj.methodCount(), 5);
+        QVERIFY(mobj.method(4).signature() == QByteArray("foo()"));
+    }
+
+    {
+        const QMetaObject &mobj = InvokableBeforeInline::staticMetaObject;
+        QCOMPARE(mobj.methodCount(), 6);
+        QVERIFY(mobj.method(4).signature() == QByteArray("foo()"));
+        QVERIFY(mobj.method(5).signature() == QByteArray("bar()"));
+    }
+}
+
+void tst_Moc::singleFunctionKeywordSignalAndSlot()
+{
+    {
+        const QMetaObject &mobj = SingleFunctionKeywordBeforeReturnType::staticMetaObject;
+        QCOMPARE(mobj.methodCount(), 6);
+        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
+        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
+    }
+
+    {
+        const QMetaObject &mobj = SingleFunctionKeywordBeforeInline::staticMetaObject;
+        QCOMPARE(mobj.methodCount(), 6);
+        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
+        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
+    }
+
+    {
+        const QMetaObject &mobj = SingleFunctionKeywordAfterInline::staticMetaObject;
+        QCOMPARE(mobj.methodCount(), 6);
+        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
+        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
+    }
+}
+
+#include "qprivateslots.h"
+
+void tst_Moc::qprivateslots()
+{
+    TestQPrivateSlots tst;
+    const QMetaObject *mobj = tst.metaObject();
+    QVERIFY(mobj->indexOfSlot("_q_privateslot()") != -1);
+    QVERIFY(mobj->indexOfMethod("method1()") != -1); //tast204730
+}
+
+#include "task189996.h"
+
+void InlineSlotsWithThrowDeclaration::c() throw() {}
+
+void tst_Moc::inlineSlotsWithThrowDeclaration()
+{
+    InlineSlotsWithThrowDeclaration tst;
+    const QMetaObject *mobj = tst.metaObject();
+    QVERIFY(mobj->indexOfSlot("a()") != -1);
+    QVERIFY(mobj->indexOfSlot("b()") != -1);
+    QVERIFY(mobj->indexOfSlot("c()") != -1);
+    QVERIFY(mobj->indexOfSlot("d()") != -1);
+    QVERIFY(mobj->indexOfSlot("e()") != -1);
+}
+
+void tst_Moc::warnOnPropertyWithoutREAD()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    proc.start("moc", QStringList(srcify("warn-on-property-without-read.h")));
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
+    QCOMPARE(mocWarning, QString(SRCDIR) +
+                QString("/warn-on-property-without-read.h:46: Warning: Property declaration foo has no READ accessor function. The property will be invalid.\n"));
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+void tst_Moc::constructors()
+{
+    const QMetaObject *mo = &CtorTestClass::staticMetaObject;
+    QCOMPARE(mo->constructorCount(), 3);
+    {
+        QMetaMethod mm = mo->constructor(0);
+        QCOMPARE(mm.access(), QMetaMethod::Public);
+        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
+        QCOMPARE(mm.signature(), "CtorTestClass(QObject*)");
+        QCOMPARE(mm.typeName(), "");
+        QList<QByteArray> paramNames = mm.parameterNames();
+        QCOMPARE(paramNames.size(), 1);
+        QCOMPARE(paramNames.at(0), QByteArray("parent"));
+        QList<QByteArray> paramTypes = mm.parameterTypes();
+        QCOMPARE(paramTypes.size(), 1);
+        QCOMPARE(paramTypes.at(0), QByteArray("QObject*"));
+    }
+    {
+        QMetaMethod mm = mo->constructor(1);
+        QCOMPARE(mm.access(), QMetaMethod::Public);
+        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
+        QCOMPARE(mm.signature(), "CtorTestClass()");
+        QCOMPARE(mm.typeName(), "");
+        QCOMPARE(mm.parameterNames().size(), 0);
+        QCOMPARE(mm.parameterTypes().size(), 0);
+    }
+    {
+        QMetaMethod mm = mo->constructor(2);
+        QCOMPARE(mm.access(), QMetaMethod::Public);
+        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
+        QCOMPARE(mm.signature(), "CtorTestClass(QString)");
+        QCOMPARE(mm.typeName(), "");
+        QList<QByteArray> paramNames = mm.parameterNames();
+        QCOMPARE(paramNames.size(), 1);
+        QCOMPARE(paramNames.at(0), QByteArray("str"));
+        QList<QByteArray> paramTypes = mm.parameterTypes();
+        QCOMPARE(paramTypes.size(), 1);
+        QCOMPARE(paramTypes.at(0), QByteArray("QString"));
+    }
+
+    QCOMPARE(mo->indexOfConstructor("CtorTestClass(QObject*)"), 0);
+    QCOMPARE(mo->indexOfConstructor("CtorTestClass()"), 1);
+    QCOMPARE(mo->indexOfConstructor("CtorTestClass(QString)"), 2);
+    QCOMPARE(mo->indexOfConstructor("CtorTestClass2(QObject*)"), -1);
+    QCOMPARE(mo->indexOfConstructor("CtorTestClass(float,float)"), -1);
+
+    QObject *o1 = mo->newInstance();
+    QVERIFY(o1 != 0);
+    QCOMPARE(o1->parent(), (QObject*)0);
+    QVERIFY(qobject_cast<CtorTestClass*>(o1) != 0);
+
+    QObject *o2 = mo->newInstance(Q_ARG(QObject*, o1));
+    QVERIFY(o2 != 0);
+    QCOMPARE(o2->parent(), o1);
+
+    QString str = QString::fromLatin1("hello");
+    QObject *o3 = mo->newInstance(Q_ARG(QString, str));
+    QVERIFY(o3 != 0);
+    QCOMPARE(qobject_cast<CtorTestClass*>(o3)->m_str, str);
+
+    {
+        //explicit constructor
+        QObject *o = QObject::staticMetaObject.newInstance();
+        QVERIFY(o);
+        delete o;
+    }
+}
+
+#include "task234909.h"
+
+#include "task240368.h"
+
+void tst_Moc::typenameWithUnsigned()
+{
+    TypenameWithUnsigned tst;
+    const QMetaObject *mobj = tst.metaObject();
+    QVERIFY(mobj->indexOfSlot("a(uint)") != -1);
+    QVERIFY(mobj->indexOfSlot("b(uint)") != -1);
+    QVERIFY(mobj->indexOfSlot("c(uint*)") != -1);
+    QVERIFY(mobj->indexOfSlot("d(uint*)") != -1);
+    QVERIFY(mobj->indexOfSlot("e(uint&)") != -1);
+    QVERIFY(mobj->indexOfSlot("f(uint&)") != -1);
+    QVERIFY(mobj->indexOfSlot("g(unsigned1)") != -1);
+    QVERIFY(mobj->indexOfSlot("h(unsigned1)") != -1);
+    QVERIFY(mobj->indexOfSlot("i(uint,unsigned1)") != -1);
+    QVERIFY(mobj->indexOfSlot("j(unsigned1,uint)") != -1);
+    QVERIFY(mobj->indexOfSlot("k(unsignedQImage)") != -1);
+    QVERIFY(mobj->indexOfSlot("l(unsignedQImage)") != -1);
+}
+
+
+void tst_Moc::warnOnVirtualSignal()
+{
+#ifdef MOC_CROSS_COMPILED
+    QSKIP("Not tested when cross-compiled", SkipAll);
+#endif
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
+    QProcess proc;
+    proc.start("moc", QStringList(srcify("pure-virtual-signals.h")));
+    QVERIFY(proc.waitForFinished());
+    QCOMPARE(proc.exitCode(), 0);
+    QByteArray mocOut = proc.readAllStandardOutput();
+    QVERIFY(!mocOut.isEmpty());
+    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
+    QCOMPARE(mocWarning, QString(SRCDIR) + QString("/pure-virtual-signals.h:48: Warning: Signals cannot be declared virtual\n") +
+                         QString(SRCDIR) + QString("/pure-virtual-signals.h:50: Warning: Signals cannot be declared virtual\n"));
+#else
+    QSKIP("Only tested on linux/gcc", SkipAll);
+#endif
+}
+
+QTEST_APPLESS_MAIN(tst_Moc)
+#include "tst_moc.moc"
+
+
+