/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** 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 either Technology Preview License Agreement or the ** Beta Release License Agreement. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #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", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \" name=\"com.trolltech.QtDBus.QtTypeName.In0\" />\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \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"); TestClass tst; QByteArray ba = QByteArray("points"); QVariant v = tst.property(ba); QVERIFY(v.isValid()); myNS::Points p = qVariantValue(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(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 &)), &test, SLOT(anotherSlot(const TestTemplate &)))); } 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 paramNames = mm.parameterNames(); QCOMPARE(paramNames.size(), 1); QCOMPARE(paramNames.at(0), QByteArray("parent")); QList 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 paramNames = mm.parameterNames(); QCOMPARE(paramNames.size(), 1); QCOMPARE(paramNames.at(0), QByteArray("str")); QList 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(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(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"