1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the test suite of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
43
44
#include <QtTest/QtTest>
45
#include <stdio.h>
46
#include <qobject.h>
47
48
#include "using-namespaces.h"
49
#include "assign-namespace.h"
50
#include "no-keywords.h"
51
#include "single_function_keyword.h"
52
#include "backslash-newlines.h"
53
#include "slots-with-void-template.h"
54
#include "pure-virtual-signals.h"
55
#include "qinvokable.h"
56
// msvc and friends crap out on it
57
#if !defined(Q_CC_GNU) || defined(Q_OS_IRIX) || defined(Q_OS_WIN)
58
#define SKIP_NEWLINE_TEST
59
#endif
60
#if !defined(SKIP_NEWLINE_TEST)
61
#include "os9-newlines.h"
62
// msvc and friends crap out on this file too,
63
// it seems to contain Mac 9 EOLs, and not windows EOLs.
64
#include "win-newlines.h"
65
#endif
66
#include "escapes-in-string-literals.h"
67
#include "cstyle-enums.h"
68
69
70
#if defined(PARSE_BOOST)
71
#include "parse-boost.h"
72
#endif
73
74
// No such thing as "long long" in Microsoft's compiler 13.0 and before
75
#if defined Q_CC_MSVC && _MSC_VER <= 1310
76
#  define NOLONGLONG
77
#endif
78
79
QT_USE_NAMESPACE
80
81
struct MyStruct {};
82
struct MyStruct2 {};
83
84
struct SuperClass {};
85
86
// Try to avoid inserting for instance a comment with a quote between the following line and the Q_OBJECT
87
// That will make the test give a false positive.
88
const char* test_multiple_number_of_escapes =   "\\\"";
89
namespace MyNamespace
90
{
91
    class TestSuperClass : public QObject
92
    {
93
        Q_OBJECT
94
        public:
95
            inline TestSuperClass() {}
96
    };
97
}
98
99
namespace String
100
{
101
    typedef QString Type;
102
}
103
104
namespace Int
105
{
106
    typedef int Type;
107
}
108
109
typedef struct {
110
    int doNotConfuseMoc;
111
} OldStyleCStruct;
112
113
class Sender : public QObject
114
{
115
    Q_OBJECT
116
117
public:
118
    void sendValue(const String::Type& value)
119
    {
120
        emit send(value);
121
    }
122
    void sendValue(const Int::Type& value)
123
    {
124
        emit send(value);
125
    }
126
127
signals:
128
    void send(const String::Type&);
129
    void send(const Int::Type&);
130
};
131
132
class Receiver : public QObject
133
{
134
    Q_OBJECT
135
public:
136
    Receiver() : stringCallCount(0), intCallCount(0) {}
137
138
    int stringCallCount;
139
    int intCallCount;
140
141
public slots:
142
    void receive(const String::Type&) { stringCallCount++; }
143
    void receive(const Int::Type&)    { intCallCount++; }
144
};
145
146
#define MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES
147
148
#define DONT_CONFUSE_MOC(klass) klass
149
#define DONT_CONFUSE_MOC_EVEN_MORE(klass, dummy, dummy2) klass
150
151
Q_DECLARE_METATYPE(MyStruct)
152
Q_DECLARE_METATYPE(MyStruct*)
153
154
namespace myNS {
155
    struct Points
156
    {
157
        Points() : p1(0xBEEF), p2(0xBABE) { }
158
        int p1, p2;
159
    };
160
}
161
162
Q_DECLARE_METATYPE(myNS::Points)
163
164
class TestClassinfoWithEscapes: public QObject
165
{
166
    Q_OBJECT
167
    Q_CLASSINFO("escaped", "\"bar\"")
168
    Q_CLASSINFO("\"escaped\"", "foo")
169
public slots:
170
    void slotWithAReallyLongName(int)
171
    { }
172
};
173
174
struct ForwardDeclaredStruct;
175
176
struct StructQObject : public QObject
177
{
178
    Q_OBJECT
179
public:
180
    void foo(struct ForwardDeclaredStruct *);
181
};
182
183
void StructQObject::foo(struct ForwardDeclaredStruct *)
184
{
185
    struct Inner {
186
        bool field;
187
    };
188
189
    struct Inner unusedVariable;
190
}
191
192
class TestClass : public MyNamespace::TestSuperClass, public DONT_CONFUSE_MOC(MyStruct),
193
                  public DONT_CONFUSE_MOC_EVEN_MORE(MyStruct2, dummy, ignored)
194
{
195
    Q_OBJECT
196
    Q_CLASSINFO("help", QT_TR_NOOP("Opening this will let you configure something"))
197
    Q_PROPERTY(short int shortIntProperty READ shortIntProperty)
198
    Q_PROPERTY(unsigned short int unsignedShortIntProperty READ unsignedShortIntProperty)
199
    Q_PROPERTY(signed short int signedShortIntProperty READ signedShortIntProperty)
200
    Q_PROPERTY(long int longIntProperty READ longIntProperty)
201
    Q_PROPERTY(unsigned long int unsignedLongIntProperty READ unsignedLongIntProperty)
202
    Q_PROPERTY(signed long int signedLongIntProperty READ signedLongIntProperty)
203
    Q_PROPERTY(long double longDoubleProperty READ longDoubleProperty)
204
    Q_PROPERTY(myNS::Points points READ points WRITE setPoints)
205
206
    Q_CLASSINFO("Multi"
207
                "line",
208
                ""
209
                "This is a "
210
                "multiline Q_CLASSINFO"
211
                "")
212
213
    // a really really long string that we have to cut into pieces in the generated stringdata
214
    // table, otherwise msvc craps out
215
    Q_CLASSINFO("D-Bus Introspection", ""
216
"  <interface name=\"org.kde.KCookieServer\" >\n"
217
"    <method name=\"findCookies\" >\n"
218
"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
219
"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
220
"      <arg direction=\"out\" type=\"s\" name=\"cookies\" />\n"
221
"    </method>\n"
222
"    <method name=\"findDomains\" >\n"
223
"      <arg direction=\"out\" type=\"as\" name=\"domains\" />\n"
224
"    </method>\n"
225
"    <method name=\"findCookies\" >\n"
226
"      <arg direction=\"in\" type=\"ai\" name=\"fields\" />\n"
227
"      <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
228
"      <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
229
"      <arg direction=\"in\" type=\"s\" name=\"path\" />\n"
230
"      <arg direction=\"in\" type=\"s\" name=\"name\" />\n"
231
"      <arg direction=\"out\" type=\"as\" name=\"cookies\" />\n"
232
"      <annotation value=\"QList&lt;int>\" name=\"com.trolltech.QtDBus.QtTypeName.In0\" />\n"
233
"    </method>\n"
234
"    <method name=\"findDOMCookies\" >\n"
235
"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
236
"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
237
"      <arg direction=\"out\" type=\"s\" name=\"cookies\" />\n"
238
"    </method>\n"
239
"    <method name=\"addCookies\" >\n"
240
"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
241
"      <arg direction=\"in\" type=\"ay\" name=\"cookieHeader\" />\n"
242
"      <arg direction=\"in\" type=\"x\" name=\"windowId\"  />\n"
243
"    </method>\n"
244
"    <method name=\"deleteCookie\" >\n"
245
"      <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
246
"      <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
247
"      <arg direction=\"in\" type=\"s\" name=\"path\" />\n"
248
"      <arg direction=\"in\" type=\"s\" name=\"name\" />\n"
249
"    </method>\n"
250
"    <method name=\"deleteCookiesFromDomain\" >\n"
251
"      <arg direction=\"in\" type=\"s\" name=\"domain\" />\n"
252
"    </method>\n"
253
"    <method name=\"deleteSessionCookies\" >\n"
254
"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
255
"    </method>\n"
256
"    <method name=\"deleteSessionCookiesFor\" >\n"
257
"      <arg direction=\"in\" type=\"s\" name=\"fqdn\" />\n"
258
"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
259
"    </method>\n"
260
"    <method name=\"deleteAllCookies\" />\n"
261
"    <method name=\"addDOMCookies\" >\n"
262
"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
263
"      <arg direction=\"in\" type=\"ay\" name=\"cookieHeader\" />\n"
264
"      <arg direction=\"in\" type=\"x\" name=\"windowId\" />\n"
265
"    </method>\n"
266
"    <method name=\"setDomainAdvice\" >\n"
267
"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
268
"      <arg direction=\"in\" type=\"s\" name=\"advice\" />\n"
269
"    </method>\n"
270
"    <method name=\"getDomainAdvice\" >\n"
271
"      <arg direction=\"in\" type=\"s\" name=\"url\" />\n"
272
"      <arg direction=\"out\" type=\"s\" name=\"advice\" />\n"
273
"    </method>\n"
274
"    <method name=\"reloadPolicy\" />\n"
275
"    <method name=\"shutdown\" />\n"
276
"  </interface>\n"
277
        "")
278
279
public:
280
    inline TestClass() {}
281
282
private slots:
283
    inline void dummy1() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES {}
284
    inline void dummy2() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES const {}
285
    inline void dummy3() const MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES {}
286
287
#ifndef NOLONGLONG
288
    void slotWithULongLong(unsigned long long) {}
289
    void slotWithULongLongP(unsigned long long*) {}
290
    void slotWithULong(unsigned long) {}
291
    void slotWithLongLong(long long) {}
292
    void slotWithLong(long) {}
293
#endif
294
295
    void slotWithColonColonType(::Int::Type) {}
296
297
    TestClass &slotWithReferenceReturnType() { return *this; }
298
299
#if (0 && 1) || 1
300
    void expressionEvaluationShortcut1() {}
301
#endif
302
#if (1 || 0) && 0
303
#else
304
    void expressionEvaluationShortcut2() {}
305
#endif
306
307
public slots:
308
    void slotWithArray(const double[3]) {}
309
    void slotWithNamedArray(const double namedArray[3]) {}
310
    void slotWithMultiArray(const double[3][4]) {}
311
312
    short int shortIntProperty() { return 0; }
313
    unsigned short int unsignedShortIntProperty() { return 0; }
314
    signed short int signedShortIntProperty() { return 0; }
315
    long int longIntProperty() { return 0; }
316
    unsigned long int unsignedLongIntProperty() { return 0; }
317
    signed long int signedLongIntProperty() { return 0; }
318
    long double longDoubleProperty() { return 0.0; }
319
320
    myNS::Points points() { return m_points; }
321
    void setPoints(myNS::Points points) { m_points = points; }
322
323
signals:
324
    void signalWithArray(const double[3]);
325
    void signalWithNamedArray(const double namedArray[3]);
326
327
private slots:
328
    // for tst_Moc::preprocessorConditionals
329
#if 0
330
    void invalidSlot() {}
331
#else
332
    void slotInElse() {}
333
#endif
334
335
#if 1
336
    void slotInIf() {}
337
#else
338
    void invalidSlot() {}
339
#endif
340
341
#if 0
342
    void invalidSlot() {}
343
#elif 0
344
#else
345
    void slotInLastElse() {}
346
#endif
347
348
#if 0
349
    void invalidSlot() {}
350
#elif 1
351
    void slotInElif() {}
352
#else
353
    void invalidSlot() {}
354
#endif
355
356
357
    friend class Receiver; // task #85783
358
signals:
359
    friend class Sender; // task #85783
360
361
public slots:
362
    void const slotWithSillyConst() {}
363
364
public:
365
    Q_INVOKABLE void const slotWithSillyConst2() {}
366
367
    // that one however should be fine
368
public slots:
369
    void slotWithVoidStar(void *) {}
370
371
private:
372
     myNS::Points m_points;
373
374
private slots:
375
     inline virtual void blub1() {}
376
     virtual inline void blub2() {}
377
};
378
379
class PropertyTestClass : public QObject
380
{
381
    Q_OBJECT
382
public:
383
384
    enum TestEnum { One, Two, Three };
385
386
    Q_ENUMS(TestEnum)
387
};
388
389
class PropertyUseClass : public QObject
390
{
391
    Q_OBJECT
392
    Q_PROPERTY(PropertyTestClass::TestEnum foo READ foo)
393
public:
394
395
    inline PropertyTestClass::TestEnum foo() const { return PropertyTestClass::One; }
396
};
397
398
#if defined(Q_MOC_RUN)
399
// Task #119503
400
#define _TASK_119503
401
#if !_TASK_119503
402
#endif
403
#endif
404
405
static QString srcify(const char *path)
406
{
407
#ifndef Q_OS_IRIX
408
    return QString(SRCDIR) + QLatin1Char('/') + QLatin1String(path);
409
#else
410
    return QString(QLatin1String(path));
411
#endif
412
}
413
414
class CtorTestClass : public QObject
415
{
416
    Q_OBJECT
417
public:
418
    Q_INVOKABLE CtorTestClass(QObject *parent = 0);
419
420
    CtorTestClass(int foo);
421
422
    inline Q_INVOKABLE CtorTestClass(const QString &str)
423
        { m_str = str; }
424
425
    QString m_str;
426
427
protected:
428
    CtorTestClass(int foo, int bar, int baz);
429
private:
430
    CtorTestClass(float, float) {}
431
};
432
433
CtorTestClass::CtorTestClass(QObject *parent)
434
    : QObject(parent) {}
435
436
CtorTestClass::CtorTestClass(int, int, int) {}
437
438
439
class tst_Moc : public QObject
440
{
441
    Q_OBJECT
442
443
    Q_PROPERTY(bool user1 READ user1 USER true )
444
    Q_PROPERTY(bool user2 READ user2 USER false)
445
    Q_PROPERTY(bool user3 READ user3 USER userFunction())
446
447
public:
448
    inline tst_Moc() {}
449
450
private slots:
451
    void initTestCase();
452
453
    void slotWithException() throw(MyStruct);
454
    void dontStripNamespaces();
455
    void oldStyleCasts();
456
    void warnOnExtraSignalSlotQualifiaction();
457
    void uLongLong();
458
    void inputFileNameWithDotsButNoExtension();
459
    void userProperties();
460
    void supportConstSignals();
461
    void task87883();
462
    void multilineComments();
463
    void classinfoWithEscapes();
464
    void trNoopInClassInfo();
465
    void ppExpressionEvaluation();
466
    void arrayArguments();
467
    void preprocessorConditionals();
468
    void blackslashNewlines();
469
    void slotWithSillyConst();
470
    void testExtraData();
471
    void namespaceTypeProperty();
472
    void slotsWithVoidTemplate();
473
    void structQObject();
474
    void namespacedFlags();
475
    void warnOnMultipleInheritance();
476
    void forgottenQInterface();
477
    void os9Newline();
478
    void winNewline();
479
    void escapesInStringLiterals();
480
    void frameworkSearchPath();
481
    void cstyleEnums();
482
    void defineMacroViaCmdline();
483
    void invokable();
484
    void singleFunctionKeywordSignalAndSlot();
485
    void templateGtGt();
486
    void qprivateslots();
487
    void qprivateproperties();
488
    void inlineSlotsWithThrowDeclaration();
489
    void warnOnPropertyWithoutREAD();
490
    void constructors();
491
    void typenameWithUnsigned();
492
    void warnOnVirtualSignal();
493
    void QTBUG5590_dummyProperty();
494
    void QTBUG12260_defaultTemplate();
495
    void notifyError();
496
    void QTBUG17635_invokableAndProperty();
497
    void revisions();
498
    void warnings_data();
499
    void warnings();
500
    void privateClass();
501
502
signals:
503
    void sigWithUnsignedArg(unsigned foo);
504
    void sigWithSignedArg(signed foo);
505
    void sigWithConstSignedArg(const signed foo);
506
    void sigWithVolatileConstSignedArg(volatile const signed foo);
507
    void sigWithCustomType(const MyStruct);
508
    void constSignal1() const;
509
    void constSignal2(int arg) const;
510
511
private:
512
    bool user1() { return true; };
513
    bool user2() { return false; };
514
    bool user3() { return false; };
515
    bool userFunction(){ return false; };
516
    template <class T> void revisions_T();
517
518
private:
519
    QString qtIncludePath;
520
    class PrivateClass;
521
};
522
523
void tst_Moc::initTestCase()
524
{
525
#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS)
526
    QProcess proc;
527
    proc.start("qmake", QStringList() << "-query" << "QT_INSTALL_HEADERS");
528
    QVERIFY(proc.waitForFinished());
529
    QCOMPARE(proc.exitCode(), 0);
530
    QByteArray output = proc.readAllStandardOutput();
531
    QVERIFY(!output.isEmpty());
532
    QCOMPARE(proc.readAllStandardError(), QByteArray());
533
    qtIncludePath = QString::fromLocal8Bit(output).trimmed();
534
    QFileInfo fi(qtIncludePath);
535
    QVERIFY(fi.exists());
536
    QVERIFY(fi.isDir());
537
#endif
538
}
539
540
void tst_Moc::slotWithException() throw(MyStruct)
541
{
542
    // be happy
543
    QVERIFY(true);
544
}
545
546
void tst_Moc::dontStripNamespaces()
547
{
548
    Sender sender;
549
    Receiver receiver;
550
551
    connect(&sender, SIGNAL(send(const String::Type &)),
552
            &receiver, SLOT(receive(const String::Type &)));
553
    connect(&sender, SIGNAL(send(const Int::Type &)),
554
            &receiver, SLOT(receive(const Int::Type &)));
555
556
    sender.sendValue(String::Type("Hello"));
557
    QCOMPARE(receiver.stringCallCount, 1);
558
    QCOMPARE(receiver.intCallCount, 0);
559
    sender.sendValue(Int::Type(42));
560
    QCOMPARE(receiver.stringCallCount, 1);
561
    QCOMPARE(receiver.intCallCount, 1);
562
}
563
564
565
void tst_Moc::oldStyleCasts()
566
{
567
#ifdef MOC_CROSS_COMPILED
568
    QSKIP("Not tested when cross-compiled", SkipAll);
569
#endif
570
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
571
    QProcess proc;
572
    proc.start("moc", QStringList(srcify("/oldstyle-casts.h")));
573
    QVERIFY(proc.waitForFinished());
574
    QCOMPARE(proc.exitCode(), 0);
575
    QByteArray mocOut = proc.readAllStandardOutput();
576
    QVERIFY(!mocOut.isEmpty());
577
    QCOMPARE(proc.readAllStandardError(), QByteArray());
578
579
    QStringList args;
580
    args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
581
         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-";
582
    proc.start("gcc", args);
583
    QVERIFY(proc.waitForStarted());
584
    proc.write(mocOut);
585
    proc.closeWriteChannel();
586
587
    QVERIFY(proc.waitForFinished());
588
    QCOMPARE(proc.exitCode(), 0);
589
    QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
590
#else
591
    QSKIP("Only tested on linux/gcc", SkipAll);
592
#endif
593
}
594
595
void tst_Moc::warnOnExtraSignalSlotQualifiaction()
596
{
597
#ifdef MOC_CROSS_COMPILED
598
    QSKIP("Not tested when cross-compiled", SkipAll);
599
#endif
600
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
601
    QProcess proc;
602
    proc.start("moc", QStringList(srcify("extraqualification.h")));
603
    QVERIFY(proc.waitForFinished());
604
    QCOMPARE(proc.exitCode(), 0);
605
    QByteArray mocOut = proc.readAllStandardOutput();
606
    QVERIFY(!mocOut.isEmpty());
607
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
608
    QCOMPARE(mocWarning, QString(SRCDIR) +
609
                QString("/extraqualification.h:53: Warning: Function declaration Test::badFunctionDeclaration contains extra qualification. Ignoring as signal or slot.\n") +
610
                QString(SRCDIR) + QString("/extraqualification.h:56: Warning: parsemaybe: Function declaration Test::anotherOne contains extra qualification. Ignoring as signal or slot.\n"));
611
#else
612
    QSKIP("Only tested on linux/gcc", SkipAll);
613
#endif
614
}
615
616
void tst_Moc::uLongLong()
617
{
618
#ifndef NOLONGLONG
619
    TestClass tst;
620
    const QMetaObject *mobj = tst.metaObject();
621
    int idx = mobj->indexOfSlot("slotWithULong(ulong)");
622
    QVERIFY(idx != -1);
623
    idx = mobj->indexOfSlot("slotWithULongLong(unsigned long long)");
624
    QVERIFY(idx != -1);
625
    idx = mobj->indexOfSlot("slotWithULongLongP(unsigned long long*)");
626
    QVERIFY(idx != -1);
627
628
    idx = mobj->indexOfSlot("slotWithLong(long)");
629
    QVERIFY(idx != -1);
630
    idx = mobj->indexOfSlot("slotWithLongLong(long long)");
631
    QVERIFY(idx != -1);
632
#else
633
    QSKIP("long long doesn't work on MSVC6 & .NET 2002, also skipped on 2003 due to compiler version issue with moc", SkipAll);
634
#endif
635
}
636
637
void tst_Moc::inputFileNameWithDotsButNoExtension()
638
{
639
#ifdef MOC_CROSS_COMPILED
640
    QSKIP("Not tested when cross-compiled", SkipAll);
641
#endif
642
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
643
    QProcess proc;
644
    proc.setWorkingDirectory(QString(SRCDIR) + "/task71021");
645
    proc.start("moc", QStringList("../Header"));
646
    QVERIFY(proc.waitForFinished());
647
    QCOMPARE(proc.exitCode(), 0);
648
    QByteArray mocOut = proc.readAllStandardOutput();
649
    QVERIFY(!mocOut.isEmpty());
650
    QCOMPARE(proc.readAllStandardError(), QByteArray());
651
652
    QStringList args;
653
    args << "-c" << "-x" << "c++" << "-I" << ".."
654
         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-";
655
    proc.start("gcc", args);
656
    QVERIFY(proc.waitForStarted());
657
    proc.write(mocOut);
658
    proc.closeWriteChannel();
659
660
    QVERIFY(proc.waitForFinished());
661
    QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
662
    QCOMPARE(proc.exitCode(), 0);
663
#else
664
    QSKIP("Only tested on linux/gcc", SkipAll);
665
#endif
666
}
667
668
void tst_Moc::userProperties()
669
{
670
    const QMetaObject *mobj = metaObject();
671
    QMetaProperty property = mobj->property(mobj->indexOfProperty("user1"));
672
    QVERIFY(property.isValid());
673
    QVERIFY(property.isUser());
674
675
    property = mobj->property(mobj->indexOfProperty("user2"));
676
    QVERIFY(property.isValid());
677
    QVERIFY(!property.isUser());
678
679
    property = mobj->property(mobj->indexOfProperty("user3"));
680
    QVERIFY(property.isValid());
681
    QVERIFY(!property.isUser(this));
682
}
683
684
void tst_Moc::supportConstSignals()
685
{
686
    QSignalSpy spy1(this, SIGNAL(constSignal1()));
687
    QVERIFY(spy1.isEmpty());
688
    emit constSignal1();
689
    QCOMPARE(spy1.count(), 1);
690
691
    QSignalSpy spy2(this, SIGNAL(constSignal2(int)));
692
    QVERIFY(spy2.isEmpty());
693
    emit constSignal2(42);
694
    QCOMPARE(spy2.count(), 1);
695
    QCOMPARE(spy2.at(0).at(0).toInt(), 42);
696
}
697
698
#include "task87883.h"
699
700
void tst_Moc::task87883()
701
{
702
    QVERIFY(Task87883::staticMetaObject.className());
703
}
704
705
#include "c-comments.h"
706
707
void tst_Moc::multilineComments()
708
{
709
    QVERIFY(IfdefedClass::staticMetaObject.className());
710
}
711
712
void tst_Moc::classinfoWithEscapes()
713
{
714
    const QMetaObject *mobj = &TestClassinfoWithEscapes::staticMetaObject;
715
    QCOMPARE(mobj->methodCount() - mobj->methodOffset(), 1);
716
717
    QMetaMethod mm = mobj->method(mobj->methodOffset());
718
    QCOMPARE(mm.signature(), "slotWithAReallyLongName(int)");
719
}
720
721
void tst_Moc::trNoopInClassInfo()
722
{
723
    TestClass t;
724
    const QMetaObject *mobj = t.metaObject();
725
    QVERIFY(mobj);
726
    QCOMPARE(mobj->classInfoCount(), 3);
727
    QCOMPARE(mobj->indexOfClassInfo("help"), 0);
728
    QCOMPARE(QString(mobj->classInfo(0).value()), QString("Opening this will let you configure something"));
729
}
730
731
void tst_Moc::ppExpressionEvaluation()
732
{
733
    TestClass tst;
734
    const QMetaObject *mobj = tst.metaObject();
735
    int idx = mobj->indexOfSlot("expressionEvaluationShortcut1()");
736
    QVERIFY(idx != -1);
737
738
    idx = mobj->indexOfSlot("expressionEvaluationShortcut2()");
739
    QVERIFY(idx != -1);
740
}
741
742
void tst_Moc::arrayArguments()
743
{
744
    TestClass tst;
745
    const QMetaObject *mobj = tst.metaObject();
746
    QVERIFY(mobj->indexOfSlot("slotWithArray(const double[3])") != -1);
747
    QVERIFY(mobj->indexOfSlot("slotWithNamedArray(const double[3])") != -1);
748
    QVERIFY(mobj->indexOfSlot("slotWithMultiArray(const double[3][4])") != -1);
749
    QVERIFY(mobj->indexOfSignal("signalWithArray(const double[3])") != -1);
750
    QVERIFY(mobj->indexOfSignal("signalWithNamedArray(const double[3])") != -1);
751
}
752
753
void tst_Moc::preprocessorConditionals()
754
{
755
    TestClass tst;
756
    const QMetaObject *mobj = tst.metaObject();
757
    QVERIFY(mobj->indexOfSlot("slotInElse()") != -1);
758
    QVERIFY(mobj->indexOfSlot("slotInIf()") != -1);
759
    QVERIFY(mobj->indexOfSlot("slotInLastElse()") != -1);
760
    QVERIFY(mobj->indexOfSlot("slotInElif()") != -1);
761
}
762
763
void tst_Moc::blackslashNewlines()
764
{
765
    BackslashNewlines tst;
766
    const QMetaObject *mobj = tst.metaObject();
767
    QVERIFY(mobj->indexOfSlot("works()") != -1);
768
    QVERIFY(mobj->indexOfSlot("buggy()") == -1);
769
}
770
771
void tst_Moc::slotWithSillyConst()
772
{
773
    TestClass tst;
774
    const QMetaObject *mobj = tst.metaObject();
775
    QVERIFY(mobj->indexOfSlot("slotWithSillyConst()") != -1);
776
    QVERIFY(mobj->indexOfMethod("slotWithSillyConst2()") != -1);
777
    QVERIFY(mobj->indexOfSlot("slotWithVoidStar(void*)") != -1);
778
}
779
780
void tst_Moc::testExtraData()
781
{
782
    const QMetaObject *mobj = &PropertyTestClass::staticMetaObject;
783
    QCOMPARE(mobj->enumeratorCount(), 1);
784
    QCOMPARE(QByteArray(mobj->enumerator(0).name()), QByteArray("TestEnum"));
785
786
    mobj = &PropertyUseClass::staticMetaObject;
787
    const int idx = mobj->indexOfProperty("foo");
788
    QVERIFY(idx != -1);
789
    const QMetaProperty prop = mobj->property(idx);
790
    QVERIFY(prop.isValid());
791
    QVERIFY(prop.isEnumType());
792
    const QMetaEnum en = prop.enumerator();
793
    QCOMPARE(QByteArray(en.name()), QByteArray("TestEnum"));
794
}
795
796
void tst_Moc::namespaceTypeProperty()
797
{
798
    qRegisterMetaType<myNS::Points>("myNS::Points");
799
    TestClass tst;
800
    QByteArray ba = QByteArray("points");
801
    QVariant v = tst.property(ba);
802
    QVERIFY(v.isValid());
803
    myNS::Points p = qVariantValue<myNS::Points>(v);
804
    QCOMPARE(p.p1, 0xBEEF);
805
    QCOMPARE(p.p2, 0xBABE);
806
    p.p1 = 0xCAFE;
807
    p.p2 = 0x1EE7;
808
    QVERIFY(tst.setProperty(ba, qVariantFromValue(p)));
809
    myNS::Points pp = qVariantValue<myNS::Points>(tst.property(ba));
810
    QCOMPARE(p.p1, pp.p1);
811
    QCOMPARE(p.p2, pp.p2);
812
}
813
814
void tst_Moc::slotsWithVoidTemplate()
815
{
816
    SlotsWithVoidTemplateTest test;
817
    QVERIFY(QObject::connect(&test, SIGNAL(myVoidSignal(void)),
818
                             &test, SLOT(dummySlot(void))));
819
    QVERIFY(QObject::connect(&test, SIGNAL(mySignal(const TestTemplate<void> &)),
820
                             &test, SLOT(anotherSlot(const TestTemplate<void> &))));
821
}
822
823
void tst_Moc::structQObject()
824
{
825
    StructQObject o;
826
    QCOMPARE(QByteArray(o.metaObject()->className()), QByteArray("StructQObject"));
827
}
828
829
#include "namespaced-flags.h"
830
831
Q_DECLARE_METATYPE(QList<Foo::Bar::Flags>);
832
833
void tst_Moc::namespacedFlags()
834
{
835
    Foo::Baz baz;
836
    Foo::Bar bar;
837
838
    bar.setFlags(Foo::Bar::Read | Foo::Bar::Write);
839
    QVERIFY(baz.flags() != bar.flags());
840
841
    const QVariant v = bar.property("flags");
842
    QVERIFY(v.isValid());
843
    QVERIFY(baz.setProperty("flags", v));
844
    QVERIFY(baz.flags() == bar.flags());
845
846
    QList<Foo::Bar::Flags> l;
847
    l << baz.flags();
848
    QVariant v2 = baz.setProperty("flagsList", QVariant::fromValue(l));
849
    QCOMPARE(l, baz.flagsList());
850
    QCOMPARE(l, qvariant_cast<QList<Foo::Bar::Flags> >(baz.property("flagsList")));
851
}
852
853
void tst_Moc::warnOnMultipleInheritance()
854
{
855
#ifdef MOC_CROSS_COMPILED
856
    QSKIP("Not tested when cross-compiled", SkipAll);
857
#endif
858
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
859
    QProcess proc;
860
    QStringList args;
861
    args << "-I" << qtIncludePath + "/QtGui"
862
         << srcify("warn-on-multiple-qobject-subclasses.h");
863
    proc.start("moc", args);
864
    QVERIFY(proc.waitForFinished());
865
    QCOMPARE(proc.exitCode(), 0);
866
    QByteArray mocOut = proc.readAllStandardOutput();
867
    QVERIFY(!mocOut.isEmpty());
868
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
869
    QCOMPARE(mocWarning, QString(SRCDIR) +
870
                QString("/warn-on-multiple-qobject-subclasses.h:53: Warning: Class Bar inherits from two QObject subclasses QWidget and Foo. This is not supported!\n"));
871
#else
872
    QSKIP("Only tested on linux/gcc", SkipAll);
873
#endif
874
}
875
876
void tst_Moc::forgottenQInterface()
877
{
878
#ifdef MOC_CROSS_COMPILED
879
    QSKIP("Not tested when cross-compiled", SkipAll);
880
#endif
881
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
882
    QProcess proc;
883
    QStringList args;
884
    args << "-I" << qtIncludePath + "/QtCore"
885
         << srcify("forgotten-qinterface.h");
886
    proc.start("moc", args);
887
    QVERIFY(proc.waitForFinished());
888
    QCOMPARE(proc.exitCode(), 0);
889
    QByteArray mocOut = proc.readAllStandardOutput();
890
    QVERIFY(!mocOut.isEmpty());
891
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
892
    QCOMPARE(mocWarning, QString(SRCDIR) +
893
                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"));
894
#else
895
    QSKIP("Only tested on linux/gcc", SkipAll);
896
#endif
897
}
898
899
void tst_Moc::os9Newline()
900
{
901
#if !defined(SKIP_NEWLINE_TEST)
902
    const QMetaObject &mo = Os9Newlines::staticMetaObject;
903
    QVERIFY(mo.indexOfSlot("testSlot()") != -1);
904
    QFile f(srcify("os9-newlines.h"));
905
    QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
906
    QByteArray data = f.readAll();
907
    f.close();
908
    QVERIFY(!data.contains('\n'));
909
    QVERIFY(data.contains('\r'));
910
#endif
911
}
912
913
void tst_Moc::winNewline()
914
{
915
#if !defined(SKIP_NEWLINE_TEST)
916
    const QMetaObject &mo = WinNewlines::staticMetaObject;
917
    QVERIFY(mo.indexOfSlot("testSlot()") != -1);
918
    QFile f(srcify("win-newlines.h"));
919
    QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
920
    QByteArray data = f.readAll();
921
    f.close();
922
    for (int i = 0; i < data.count(); ++i) {
923
        if (data.at(i) == QLatin1Char('\r')) {
924
            QVERIFY(i < data.count() - 1);
925
            ++i;
926
            QVERIFY(data.at(i) == '\n');
927
        } else {
928
            QVERIFY(data.at(i) != '\n');
929
        }
930
    }
931
#endif
932
}
933
934
void tst_Moc::escapesInStringLiterals()
935
{
936
    const QMetaObject &mo = StringLiterals::staticMetaObject;
937
    QCOMPARE(mo.classInfoCount(), 3);
938
939
    int idx = mo.indexOfClassInfo("Test");
940
    QVERIFY(idx != -1);
941
    QMetaClassInfo info = mo.classInfo(idx);
942
    QCOMPARE(QByteArray(info.value()),
943
             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x53"));
944
945
    QVERIFY(idx != -1);
946
    idx = mo.indexOfClassInfo("Test2");
947
    info = mo.classInfo(idx);
948
    QCOMPARE(QByteArray(info.value()),
949
             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\123"));
950
951
    QVERIFY(idx != -1);
952
    idx = mo.indexOfClassInfo("Test3");
953
    info = mo.classInfo(idx);
954
    QCOMPARE(QByteArray(info.value()),
955
             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\nb"));
956
}
957
958
void tst_Moc::frameworkSearchPath()
959
{
960
#ifdef MOC_CROSS_COMPILED
961
    QSKIP("Not tested when cross-compiled", SkipAll);
962
#endif
963
#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS)
964
    QStringList args;
965
    args << "-F" << srcify(".")
966
         << srcify("interface-from-framework.h")
967
         ;
968
969
    QProcess proc;
970
    proc.start("moc", args);
971
    bool finished = proc.waitForFinished();
972
    if (!finished)
973
        qWarning("waitForFinished failed. QProcess error: %d", (int)proc.error());
974
    QVERIFY(finished);
975
    if (proc.exitCode() != 0) {
976
        qDebug() << proc.readAllStandardError();
977
    }
978
    QCOMPARE(proc.exitCode(), 0);
979
    QCOMPARE(proc.readAllStandardError(), QByteArray());
980
#else
981
    QSKIP("Only tested/relevant on unixy platforms", SkipAll);
982
#endif
983
}
984
985
void tst_Moc::cstyleEnums()
986
{
987
    const QMetaObject &obj = CStyleEnums::staticMetaObject;
988
    QCOMPARE(obj.enumeratorCount(), 1);
989
    QMetaEnum metaEnum = obj.enumerator(0);
990
    QCOMPARE(metaEnum.name(), "Baz");
991
    QCOMPARE(metaEnum.keyCount(), 2);
992
    QCOMPARE(metaEnum.key(0), "Foo");
993
    QCOMPARE(metaEnum.key(1), "Bar");
994
}
995
996
void tst_Moc::templateGtGt()
997
{
998
#ifdef MOC_CROSS_COMPILED
999
    QSKIP("Not tested when cross-compiled", SkipAll);
1000
#endif
1001
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1002
    QProcess proc;
1003
    proc.start("moc", QStringList(srcify("template-gtgt.h")));
1004
    QVERIFY(proc.waitForFinished());
1005
    QCOMPARE(proc.exitCode(), 0);
1006
    QByteArray mocOut = proc.readAllStandardOutput();
1007
    QVERIFY(!mocOut.isEmpty());
1008
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
1009
    QVERIFY(mocWarning.isEmpty());
1010
#else
1011
    QSKIP("Only tested on linux/gcc", SkipAll);
1012
#endif
1013
}
1014
1015
void tst_Moc::defineMacroViaCmdline()
1016
{
1017
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1018
    QProcess proc;
1019
1020
    QStringList args;
1021
    args << "-DFOO";
1022
    args << srcify("macro-on-cmdline.h");
1023
1024
    proc.start("moc", args);
1025
    QVERIFY(proc.waitForFinished());
1026
    QCOMPARE(proc.exitCode(), 0);
1027
    QCOMPARE(proc.readAllStandardError(), QByteArray());
1028
    QByteArray mocOut = proc.readAllStandardOutput();
1029
    QVERIFY(!mocOut.isEmpty());
1030
#else
1031
    QSKIP("Only tested on linux/gcc", SkipAll);
1032
#endif
1033
}
1034
1035
void tst_Moc::invokable()
1036
{
1037
    {
1038
        const QMetaObject &mobj = InvokableBeforeReturnType::staticMetaObject;
1039
        QCOMPARE(mobj.methodCount(), 5);
1040
        QVERIFY(mobj.method(4).signature() == QByteArray("foo()"));
1041
    }
1042
1043
    {
1044
        const QMetaObject &mobj = InvokableBeforeInline::staticMetaObject;
1045
        QCOMPARE(mobj.methodCount(), 6);
1046
        QVERIFY(mobj.method(4).signature() == QByteArray("foo()"));
1047
        QVERIFY(mobj.method(5).signature() == QByteArray("bar()"));
1048
    }
1049
}
1050
1051
void tst_Moc::singleFunctionKeywordSignalAndSlot()
1052
{
1053
    {
1054
        const QMetaObject &mobj = SingleFunctionKeywordBeforeReturnType::staticMetaObject;
1055
        QCOMPARE(mobj.methodCount(), 6);
1056
        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
1057
        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
1058
    }
1059
1060
    {
1061
        const QMetaObject &mobj = SingleFunctionKeywordBeforeInline::staticMetaObject;
1062
        QCOMPARE(mobj.methodCount(), 6);
1063
        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
1064
        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
1065
    }
1066
1067
    {
1068
        const QMetaObject &mobj = SingleFunctionKeywordAfterInline::staticMetaObject;
1069
        QCOMPARE(mobj.methodCount(), 6);
1070
        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
1071
        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
1072
    }
1073
}
1074
1075
#include "qprivateslots.h"
1076
1077
void tst_Moc::qprivateslots()
1078
{
1079
    TestQPrivateSlots tst;
1080
    const QMetaObject *mobj = tst.metaObject();
1081
    QVERIFY(mobj->indexOfSlot("_q_privateslot()") != -1);
1082
    QVERIFY(mobj->indexOfMethod("method1()") != -1); //tast204730
1083
}
1084
1085
class PrivatePropertyTest : public QObject
1086
{
1087
    Q_OBJECT
1088
    Q_PROPERTY(int foo READ foo WRITE setFoo)
1089
    Q_PRIVATE_PROPERTY(d, int bar READ bar WRITE setBar)
1090
    Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, int plop READ plop WRITE setPlop)
1091
    Q_PRIVATE_PROPERTY(PrivatePropertyTest::d_func(), int baz READ baz WRITE setBaz)
1092
    class MyDPointer {
1093
    public:
1094
        MyDPointer() : mBar(0), mPlop(0) {}
1095
        int bar() { return mBar ; }
1096
        void setBar(int value) { mBar = value; }
1097
        int plop() { return mPlop ; }
1098
        void setPlop(int value) { mPlop = value; }
1099
        int baz() { return mBaz ; }
1100
        void setBaz(int value) { mBaz = value; }
1101
    private:
1102
        int mBar;
1103
        int mPlop;
1104
        int mBaz;
1105
    };
1106
public:
1107
    PrivatePropertyTest() : mFoo(0), d (new MyDPointer) {}
1108
    int foo() { return mFoo ; }
1109
    void setFoo(int value) { mFoo = value; }
1110
    MyDPointer *d_func() {return d;}
1111
private:
1112
    int mFoo;
1113
    MyDPointer *d;
1114
};
1115
1116
1117
void tst_Moc::qprivateproperties()
1118
{
1119
    PrivatePropertyTest test;
1120
1121
    test.setProperty("foo", 1);
1122
    QCOMPARE(test.property("foo"), qVariantFromValue(1));
1123
1124
    test.setProperty("bar", 2);
1125
    QCOMPARE(test.property("bar"), qVariantFromValue(2));
1126
1127
    test.setProperty("plop", 3);
1128
    QCOMPARE(test.property("plop"), qVariantFromValue(3));
1129
1130
    test.setProperty("baz", 4);
1131
    QCOMPARE(test.property("baz"), qVariantFromValue(4));
1132
1133
}
1134
1135
#include "task189996.h"
1136
1137
void InlineSlotsWithThrowDeclaration::c() throw() {}
1138
1139
void tst_Moc::inlineSlotsWithThrowDeclaration()
1140
{
1141
    InlineSlotsWithThrowDeclaration tst;
1142
    const QMetaObject *mobj = tst.metaObject();
1143
    QVERIFY(mobj->indexOfSlot("a()") != -1);
1144
    QVERIFY(mobj->indexOfSlot("b()") != -1);
1145
    QVERIFY(mobj->indexOfSlot("c()") != -1);
1146
    QVERIFY(mobj->indexOfSlot("d()") != -1);
1147
    QVERIFY(mobj->indexOfSlot("e()") != -1);
1148
}
1149
1150
void tst_Moc::warnOnPropertyWithoutREAD()
1151
{
1152
#ifdef MOC_CROSS_COMPILED
1153
    QSKIP("Not tested when cross-compiled", SkipAll);
1154
#endif
1155
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1156
    QProcess proc;
1157
    proc.start("moc", QStringList(srcify("warn-on-property-without-read.h")));
1158
    QVERIFY(proc.waitForFinished());
1159
    QCOMPARE(proc.exitCode(), 0);
1160
    QByteArray mocOut = proc.readAllStandardOutput();
1161
    QVERIFY(!mocOut.isEmpty());
1162
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
1163
    QCOMPARE(mocWarning, QString(SRCDIR) +
1164
                QString("/warn-on-property-without-read.h:46: Warning: Property declaration foo has no READ accessor function. The property will be invalid.\n"));
1165
#else
1166
    QSKIP("Only tested on linux/gcc", SkipAll);
1167
#endif
1168
}
1169
1170
void tst_Moc::constructors()
1171
{
1172
    const QMetaObject *mo = &CtorTestClass::staticMetaObject;
1173
    QCOMPARE(mo->constructorCount(), 3);
1174
    {
1175
        QMetaMethod mm = mo->constructor(0);
1176
        QCOMPARE(mm.access(), QMetaMethod::Public);
1177
        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1178
        QCOMPARE(mm.signature(), "CtorTestClass(QObject*)");
1179
        QCOMPARE(mm.typeName(), "");
1180
        QList<QByteArray> paramNames = mm.parameterNames();
1181
        QCOMPARE(paramNames.size(), 1);
1182
        QCOMPARE(paramNames.at(0), QByteArray("parent"));
1183
        QList<QByteArray> paramTypes = mm.parameterTypes();
1184
        QCOMPARE(paramTypes.size(), 1);
1185
        QCOMPARE(paramTypes.at(0), QByteArray("QObject*"));
1186
    }
1187
    {
1188
        QMetaMethod mm = mo->constructor(1);
1189
        QCOMPARE(mm.access(), QMetaMethod::Public);
1190
        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1191
        QCOMPARE(mm.signature(), "CtorTestClass()");
1192
        QCOMPARE(mm.typeName(), "");
1193
        QCOMPARE(mm.parameterNames().size(), 0);
1194
        QCOMPARE(mm.parameterTypes().size(), 0);
1195
    }
1196
    {
1197
        QMetaMethod mm = mo->constructor(2);
1198
        QCOMPARE(mm.access(), QMetaMethod::Public);
1199
        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1200
        QCOMPARE(mm.signature(), "CtorTestClass(QString)");
1201
        QCOMPARE(mm.typeName(), "");
1202
        QList<QByteArray> paramNames = mm.parameterNames();
1203
        QCOMPARE(paramNames.size(), 1);
1204
        QCOMPARE(paramNames.at(0), QByteArray("str"));
1205
        QList<QByteArray> paramTypes = mm.parameterTypes();
1206
        QCOMPARE(paramTypes.size(), 1);
1207
        QCOMPARE(paramTypes.at(0), QByteArray("QString"));
1208
    }
1209
1210
    QCOMPARE(mo->indexOfConstructor("CtorTestClass(QObject*)"), 0);
1211
    QCOMPARE(mo->indexOfConstructor("CtorTestClass()"), 1);
1212
    QCOMPARE(mo->indexOfConstructor("CtorTestClass(QString)"), 2);
1213
    QCOMPARE(mo->indexOfConstructor("CtorTestClass2(QObject*)"), -1);
1214
    QCOMPARE(mo->indexOfConstructor("CtorTestClass(float,float)"), -1);
1215
1216
    QObject *o1 = mo->newInstance();
1217
    QVERIFY(o1 != 0);
1218
    QCOMPARE(o1->parent(), (QObject*)0);
1219
    QVERIFY(qobject_cast<CtorTestClass*>(o1) != 0);
1220
1221
    QObject *o2 = mo->newInstance(Q_ARG(QObject*, o1));
1222
    QVERIFY(o2 != 0);
1223
    QCOMPARE(o2->parent(), o1);
1224
1225
    QString str = QString::fromLatin1("hello");
1226
    QObject *o3 = mo->newInstance(Q_ARG(QString, str));
1227
    QVERIFY(o3 != 0);
1228
    QCOMPARE(qobject_cast<CtorTestClass*>(o3)->m_str, str);
1229
1230
    {
1231
        //explicit constructor
1232
        QObject *o = QObject::staticMetaObject.newInstance();
1233
        QVERIFY(o);
1234
        delete o;
1235
    }
1236
}
1237
1238
#include "task234909.h"
1239
1240
#include "task240368.h"
1241
1242
void tst_Moc::typenameWithUnsigned()
1243
{
1244
    TypenameWithUnsigned tst;
1245
    const QMetaObject *mobj = tst.metaObject();
1246
    QVERIFY(mobj->indexOfSlot("a(uint)") != -1);
1247
    QVERIFY(mobj->indexOfSlot("b(uint)") != -1);
1248
    QVERIFY(mobj->indexOfSlot("c(uint*)") != -1);
1249
    QVERIFY(mobj->indexOfSlot("d(uint*)") != -1);
1250
    QVERIFY(mobj->indexOfSlot("e(uint&)") != -1);
1251
    QVERIFY(mobj->indexOfSlot("f(uint&)") != -1);
1252
    QVERIFY(mobj->indexOfSlot("g(unsigned1)") != -1);
1253
    QVERIFY(mobj->indexOfSlot("h(unsigned1)") != -1);
1254
    QVERIFY(mobj->indexOfSlot("i(uint,unsigned1)") != -1);
1255
    QVERIFY(mobj->indexOfSlot("j(unsigned1,uint)") != -1);
1256
    QVERIFY(mobj->indexOfSlot("k(unsignedQImage)") != -1);
1257
    QVERIFY(mobj->indexOfSlot("l(unsignedQImage)") != -1);
1258
}
1259
1260
1261
void tst_Moc::warnOnVirtualSignal()
1262
{
1263
#ifdef MOC_CROSS_COMPILED
1264
    QSKIP("Not tested when cross-compiled", SkipAll);
1265
#endif
1266
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1267
    QProcess proc;
1268
    proc.start("moc", QStringList(srcify("pure-virtual-signals.h")));
1269
    QVERIFY(proc.waitForFinished());
1270
    QCOMPARE(proc.exitCode(), 0);
1271
    QByteArray mocOut = proc.readAllStandardOutput();
1272
    QVERIFY(!mocOut.isEmpty());
1273
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
1274
    QCOMPARE(mocWarning, QString(SRCDIR) + QString("/pure-virtual-signals.h:48: Warning: Signals cannot be declared virtual\n") +
1275
                         QString(SRCDIR) + QString("/pure-virtual-signals.h:50: Warning: Signals cannot be declared virtual\n"));
1276
#else
1277
    QSKIP("Only tested on linux/gcc", SkipAll);
1278
#endif
1279
}
1280
1281
1282
class QTBUG5590_DummyObject: public QObject
1283
{
1284
    Q_OBJECT
1285
    Q_PROPERTY(bool dummy)
1286
};
1287
1288
class QTBUG5590_PropertyObject: public QTBUG5590_DummyObject
1289
{
1290
    Q_OBJECT
1291
    Q_PROPERTY(int value READ value WRITE setValue)
1292
    Q_PROPERTY(int value2 READ value2 WRITE setValue2)
1293
1294
    public:
1295
        QTBUG5590_PropertyObject() :  m_value(85), m_value2(40) { }
1296
        int value() const { return m_value; }
1297
        void setValue(int value) { m_value = value; }
1298
        int value2() const { return m_value2; }
1299
        void setValue2(int value) { m_value2 = value; }
1300
    private:
1301
        int m_value, m_value2;
1302
};
1303
1304
void tst_Moc::QTBUG5590_dummyProperty()
1305
{
1306
    QTBUG5590_PropertyObject o;
1307
    QCOMPARE(o.property("value").toInt(), 85);
1308
    QCOMPARE(o.property("value2").toInt(), 40);
1309
    o.setProperty("value", 32);
1310
    QCOMPARE(o.value(), 32);
1311
    o.setProperty("value2", 82);
1312
    QCOMPARE(o.value2(), 82);
1313
}
1314
1315
class QTBUG7421_ReturnConstTemplate: public QObject
1316
{ Q_OBJECT
1317
public slots:
1318
        const QList<int> returnConstTemplate1() { return QList<int>(); }
1319
        QList<int> const returnConstTemplate2() { return QList<int>(); }
1320
        const int returnConstInt() { return 0; }
1321
        const QString returnConstString(const QString s) { return s; }
1322
        QString const returnConstString2( QString const s) { return s; }
1323
};
1324
1325
class QTBUG9354_constInName: public QObject
1326
{ Q_OBJECT
1327
public slots:
1328
    void slotChooseScientificConst0(struct science_constant const &) {};
1329
    void foo(struct science_const const &) {};
1330
    void foo(struct constconst const &) {};
1331
    void foo(struct constconst *) {};
1332
    void foo(struct const_ *) {};
1333
};
1334
1335
1336
template<typename T1, typename T2>
1337
class TestTemplate2
1338
{
1339
};
1340
1341
class QTBUG11647_constInTemplateParameter : public QObject
1342
{ Q_OBJECT
1343
public slots:
1344
    void testSlot(TestTemplate2<const int, const short*>) {}
1345
    void testSlot2(TestTemplate2<int, short const * const >) {}
1346
    void testSlot3(TestTemplate2<TestTemplate2 < const int, const short* > const *,
1347
                                TestTemplate2< TestTemplate2 < void, int > , unsigned char *> > ) {}
1348
1349
signals:
1350
    void testSignal(TestTemplate2<const int, const short*>);
1351
};
1352
1353
class QTBUG12260_defaultTemplate_Object : public QObject
1354
{ Q_OBJECT
1355
public slots:
1356
#if !(defined(Q_CC_GNU) && __GNUC__ == 4 && __GNUC_MINOR__ <= 3) || defined(Q_MOC_RUN)
1357
    void doSomething(QHash<QString, QVariant> values = QHash<QString, QVariant>() ) { Q_UNUSED(values); }
1358
#else
1359
    // we want to test the previous function, but gcc < 4.4 seemed to have a bug similar to the one moc has.
1360
    typedef QHash<QString, QVariant> WorkaroundGCCBug;
1361
    void doSomething(QHash<QString, QVariant> values = WorkaroundGCCBug() ) { Q_UNUSED(values); }
1362
#endif
1363
1364
    void doAnotherThing(bool a = (1 < 3), bool b = (1 > 4)) { Q_UNUSED(a); Q_UNUSED(b); }
1365
};
1366
1367
1368
void tst_Moc::QTBUG12260_defaultTemplate()
1369
{
1370
    QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomething(QHash<QString,QVariant>)") != -1);
1371
    QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doAnotherThing(bool,bool)") != -1);
1372
}
1373
1374
void tst_Moc::notifyError()
1375
{
1376
#ifdef MOC_CROSS_COMPILED
1377
    QSKIP("Not tested when cross-compiled", SkipAll);
1378
#endif
1379
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1380
    QProcess proc;
1381
    proc.start("moc", QStringList(srcify("error-on-wrong-notify.h")));
1382
    QVERIFY(proc.waitForFinished());
1383
    QCOMPARE(proc.exitCode(), 1);
1384
    QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
1385
    QByteArray mocOut = proc.readAllStandardOutput();
1386
    QVERIFY(mocOut.isEmpty());
1387
    QString mocError = QString::fromLocal8Bit(proc.readAllStandardError());
1388
    QCOMPARE(mocError, QString(SRCDIR) +
1389
        QString("/error-on-wrong-notify.h:52: Error: NOTIFY signal 'fooChanged' of property 'foo' does not exist in class ClassWithWrongNOTIFY.\n"));
1390
#else
1391
    QSKIP("Only tested on linux/gcc", SkipAll);
1392
#endif
1393
}
1394
1395
class QTBUG_17635_InvokableAndProperty : public QObject
1396
{
1397
    Q_OBJECT
1398
public:
1399
    Q_PROPERTY(int numberOfEggs READ numberOfEggs)
1400
    Q_PROPERTY(int numberOfChickens READ numberOfChickens)
1401
    Q_INVOKABLE QString getEgg(int index) { return QString::fromLatin1("Egg"); }
1402
    Q_INVOKABLE QString getChicken(int index) { return QString::fromLatin1("Chicken"); }
1403
    int numberOfEggs() { return 2; }
1404
    int numberOfChickens() { return 4; }
1405
};
1406
1407
void tst_Moc::QTBUG17635_invokableAndProperty()
1408
{
1409
    //Moc used to fail parsing Q_INVOKABLE if they were dirrectly following a Q_PROPERTY;
1410
    QTBUG_17635_InvokableAndProperty mc;
1411
    QString val;
1412
    QMetaObject::invokeMethod(&mc, "getEgg", Q_RETURN_ARG(QString, val), Q_ARG(int, 10));
1413
    QCOMPARE(val, QString::fromLatin1("Egg"));
1414
    QMetaObject::invokeMethod(&mc, "getChicken", Q_RETURN_ARG(QString, val), Q_ARG(int, 10));
1415
    QCOMPARE(val, QString::fromLatin1("Chicken"));
1416
    QVERIFY(mc.metaObject()->indexOfProperty("numberOfEggs") != -1);
1417
    QVERIFY(mc.metaObject()->indexOfProperty("numberOfChickens") != -1);
1418
}
1419
1420
// If changed, update VersionTestNotify below
1421
class VersionTest : public QObject
1422
{
1423
    Q_OBJECT
1424
    Q_PROPERTY(int prop1 READ foo)
1425
    Q_PROPERTY(int prop2 READ foo REVISION 2)
1426
    Q_ENUMS(TestEnum);
1427
1428
public:
1429
    int foo() const { return 0; }
1430
1431
    Q_INVOKABLE void method1() {}
1432
    Q_INVOKABLE Q_REVISION(4) void method2() {}
1433
1434
    enum TestEnum { One, Two };
1435
1436
public slots:
1437
    void slot1() {}
1438
    Q_REVISION(3) void slot2() {}
1439
1440
signals:
1441
    void signal1();
1442
    Q_REVISION(5) void signal2();
1443
1444
public slots Q_REVISION(6):
1445
    void slot3() {}
1446
    void slot4() {}
1447
1448
signals Q_REVISION(7):
1449
    void signal3();
1450
    void signal4();
1451
};
1452
1453
// If changed, update VersionTest above
1454
class VersionTestNotify : public QObject
1455
{
1456
    Q_OBJECT
1457
    Q_PROPERTY(int prop1 READ foo NOTIFY fooChanged)
1458
    Q_PROPERTY(int prop2 READ foo REVISION 2)
1459
    Q_ENUMS(TestEnum);
1460
1461
public:
1462
    int foo() const { return 0; }
1463
1464
    Q_INVOKABLE void method1() {}
1465
    Q_INVOKABLE Q_REVISION(4) void method2() {}
1466
1467
    enum TestEnum { One, Two };
1468
1469
public slots:
1470
    void slot1() {}
1471
    Q_REVISION(3) void slot2() {}
1472
1473
signals:
1474
    void fooChanged();
1475
    void signal1();
1476
    Q_REVISION(5) void signal2();
1477
1478
public slots Q_REVISION(6):
1479
    void slot3() {}
1480
    void slot4() {}
1481
1482
signals Q_REVISION(7):
1483
    void signal3();
1484
    void signal4();
1485
};
1486
1487
template <class T>
1488
void tst_Moc::revisions_T()
1489
{
1490
    int idx = T::staticMetaObject.indexOfProperty("prop1");
1491
    QVERIFY(T::staticMetaObject.property(idx).revision() == 0);
1492
    idx = T::staticMetaObject.indexOfProperty("prop2");
1493
    QVERIFY(T::staticMetaObject.property(idx).revision() == 2);
1494
1495
    idx = T::staticMetaObject.indexOfMethod("method1()");
1496
    QVERIFY(T::staticMetaObject.method(idx).revision() == 0);
1497
    idx = T::staticMetaObject.indexOfMethod("method2()");
1498
    QVERIFY(T::staticMetaObject.method(idx).revision() == 4);
1499
1500
    idx = T::staticMetaObject.indexOfSlot("slot1()");
1501
    QVERIFY(T::staticMetaObject.method(idx).revision() == 0);
1502
    idx = T::staticMetaObject.indexOfSlot("slot2()");
1503
    QVERIFY(T::staticMetaObject.method(idx).revision() == 3);
1504
1505
    idx = T::staticMetaObject.indexOfSlot("slot3()");
1506
    QVERIFY(T::staticMetaObject.method(idx).revision() == 6);
1507
    idx = T::staticMetaObject.indexOfSlot("slot4()");
1508
    QVERIFY(T::staticMetaObject.method(idx).revision() == 6);
1509
1510
    idx = T::staticMetaObject.indexOfSignal("signal1()");
1511
    QVERIFY(T::staticMetaObject.method(idx).revision() == 0);
1512
    idx = T::staticMetaObject.indexOfSignal("signal2()");
1513
    QVERIFY(T::staticMetaObject.method(idx).revision() == 5);
1514
1515
    idx = T::staticMetaObject.indexOfSignal("signal3()");
1516
    QVERIFY(T::staticMetaObject.method(idx).revision() == 7);
1517
    idx = T::staticMetaObject.indexOfSignal("signal4()");
1518
    QVERIFY(T::staticMetaObject.method(idx).revision() == 7);
1519
1520
    idx = T::staticMetaObject.indexOfEnumerator("TestEnum");
1521
    QCOMPARE(T::staticMetaObject.enumerator(idx).keyCount(), 2);
1522
    QCOMPARE(T::staticMetaObject.enumerator(idx).key(0), "One");
1523
}
1524
1525
// test using both class that has properties with and without NOTIFY signals
1526
void tst_Moc::revisions()
1527
{
1528
    revisions_T<VersionTest>();
1529
    revisions_T<VersionTestNotify>();
1530
}
1531
1532
void tst_Moc::warnings_data()
1533
{
1534
    QTest::addColumn<QByteArray>("input");
1535
    QTest::addColumn<QStringList>("args");
1536
    QTest::addColumn<int>("exitCode");
1537
    QTest::addColumn<QString>("expectedStdOut");
1538
    QTest::addColumn<QString>("expectedStdErr");
1539
1540
    // empty input should result in "no relevant classes" note
1541
    QTest::newRow("No relevant classes")
1542
        << QByteArray(" ")
1543
        << QStringList()
1544
        << 0
1545
        << QString()
1546
        << QString("standard input:0: Note: No relevant classes found. No output generated.");
1547
1548
    // passing "-nn" should suppress "no relevant classes" note
1549
    QTest::newRow("-nn")
1550
        << QByteArray(" ")
1551
        << (QStringList() << "-nn")
1552
        << 0
1553
        << QString()
1554
        << QString();
1555
1556
    // passing "-nw" should also suppress "no relevant classes" note
1557
    QTest::newRow("-nw")
1558
        << QByteArray(" ")
1559
        << (QStringList() << "-nw")
1560
        << 0
1561
        << QString()
1562
        << QString();
1563
1564
    // This should output a warning
1565
    QTest::newRow("Invalid property warning")
1566
        << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };")
1567
        << QStringList()
1568
        << 0
1569
        << QString("IGNORE_ALL_STDOUT")
1570
        << QString("standard input:1: Warning: Property declaration x has no READ accessor function. The property will be invalid.");
1571
1572
    // Passing "-nn" should NOT suppress the warning
1573
    QTest::newRow("Invalid property warning")
1574
        << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };")
1575
        << (QStringList() << "-nn")
1576
        << 0
1577
        << QString("IGNORE_ALL_STDOUT")
1578
        << QString("standard input:1: Warning: Property declaration x has no READ accessor function. The property will be invalid.");
1579
1580
    // Passing "-nw" should suppress the warning
1581
    QTest::newRow("Invalid property warning")
1582
        << QByteArray("class X : public QObject { Q_OBJECT Q_PROPERTY(int x) };")
1583
        << (QStringList() << "-nw")
1584
        << 0
1585
        << QString("IGNORE_ALL_STDOUT")
1586
        << QString();
1587
1588
    // This should output an error
1589
    QTest::newRow("Does not inherit QObject")
1590
        << QByteArray("class X { Q_OBJECT };")
1591
        << QStringList()
1592
        << 1
1593
        << QString()
1594
        << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject");
1595
1596
    // "-nn" should not suppress the error
1597
    QTest::newRow("Does not inherit QObject with -nn")
1598
        << QByteArray("class X { Q_OBJECT };")
1599
        << (QStringList() << "-nn")
1600
        << 1
1601
        << QString()
1602
        << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject");
1603
1604
    // "-nw" should not suppress the error
1605
    QTest::newRow("Does not inherit QObject with -nn")
1606
        << QByteArray("class X { Q_OBJECT };")
1607
        << (QStringList() << "-nw")
1608
        << 1
1609
        << QString()
1610
        << QString("standard input:1: Error: Class contains Q_OBJECT macro but does not inherit from QObject");
1611
}
1612
1613
void tst_Moc::warnings()
1614
{
1615
#ifdef MOC_CROSS_COMPILED
1616
    QSKIP("Not tested when cross-compiled", SkipAll);
1617
#endif
1618
1619
    QFETCH(QByteArray, input);
1620
    QFETCH(QStringList, args);
1621
    QFETCH(int, exitCode);
1622
    QFETCH(QString, expectedStdOut);
1623
    QFETCH(QString, expectedStdErr);
1624
1625
#ifdef Q_CC_MSVC
1626
    // for some reasons, moc compiled with MSVC uses a different output format
1627
    QRegExp lineNumberRe(":(\\d+):");
1628
    lineNumberRe.setMinimal(true);
1629
    expectedStdErr.replace(lineNumberRe, "(\\1):");
1630
#endif
1631
1632
    QProcess proc;
1633
    proc.start("moc", args);
1634
    QVERIFY(proc.waitForStarted());
1635
1636
    QCOMPARE(proc.write(input), qint64(input.size()));
1637
1638
    proc.closeWriteChannel();
1639
1640
    QVERIFY(proc.waitForFinished());
1641
1642
    QCOMPARE(proc.exitCode(), exitCode);
1643
    QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
1644
1645
    // magic value "IGNORE_ALL_STDOUT" ignores stdout
1646
    if (expectedStdOut != "IGNORE_ALL_STDOUT")
1647
        QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardOutput()).trimmed(), expectedStdOut);
1648
    QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()).trimmed(), expectedStdErr);
1649
1650
    }
1651
1652
class tst_Moc::PrivateClass : public QObject {
1653
    Q_PROPERTY(int someProperty READ someSlot WRITE someSlot2)
1654
Q_OBJECT
1655
Q_SIGNALS:
1656
    void someSignal();
1657
public Q_SLOTS:
1658
    int someSlot() { return 1; }
1659
    void someSlot2(int) {}
1660
public:
1661
    Q_INVOKABLE PrivateClass()  {}
1662
};
1663
1664
void tst_Moc::privateClass()
1665
{
1666
    QVERIFY(PrivateClass::staticMetaObject.indexOfConstructor("PrivateClass()") == 0);
1667
    QVERIFY(PrivateClass::staticMetaObject.indexOfSignal("someSignal()") > 0);
1668
}
1669
1670
1671
QTEST_APPLESS_MAIN(tst_Moc)
1672
#include "tst_moc.moc"