1
/****************************************************************************
2
**
3
** Copyright (C) 2011 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 revisions();
497
signals:
498
    void sigWithUnsignedArg(unsigned foo);
499
    void sigWithSignedArg(signed foo);
500
    void sigWithConstSignedArg(const signed foo);
501
    void sigWithVolatileConstSignedArg(volatile const signed foo);
502
    void sigWithCustomType(const MyStruct);
503
    void constSignal1() const;
504
    void constSignal2(int arg) const;
505
506
private:
507
    bool user1() { return true; };
508
    bool user2() { return false; };
509
    bool user3() { return false; };
510
    bool userFunction(){ return false; };
511
    template <class T> void revisions_T();
512
513
private:
514
    QString qtIncludePath;
515
};
516
517
void tst_Moc::initTestCase()
518
{
519
#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS)
520
    QProcess proc;
521
    proc.start("qmake", QStringList() << "-query" << "QT_INSTALL_HEADERS");
522
    QVERIFY(proc.waitForFinished());
523
    QCOMPARE(proc.exitCode(), 0);
524
    QByteArray output = proc.readAllStandardOutput();
525
    QVERIFY(!output.isEmpty());
526
    QCOMPARE(proc.readAllStandardError(), QByteArray());
527
    qtIncludePath = QString::fromLocal8Bit(output).trimmed();
528
    QFileInfo fi(qtIncludePath);
529
    QVERIFY(fi.exists());
530
    QVERIFY(fi.isDir());
531
#endif
532
}
533
534
void tst_Moc::slotWithException() throw(MyStruct)
535
{
536
    // be happy
537
    QVERIFY(true);
538
}
539
540
void tst_Moc::dontStripNamespaces()
541
{
542
    Sender sender;
543
    Receiver receiver;
544
545
    connect(&sender, SIGNAL(send(const String::Type &)),
546
            &receiver, SLOT(receive(const String::Type &)));
547
    connect(&sender, SIGNAL(send(const Int::Type &)),
548
            &receiver, SLOT(receive(const Int::Type &)));
549
550
    sender.sendValue(String::Type("Hello"));
551
    QCOMPARE(receiver.stringCallCount, 1);
552
    QCOMPARE(receiver.intCallCount, 0);
553
    sender.sendValue(Int::Type(42));
554
    QCOMPARE(receiver.stringCallCount, 1);
555
    QCOMPARE(receiver.intCallCount, 1);
556
}
557
558
559
void tst_Moc::oldStyleCasts()
560
{
561
#ifdef MOC_CROSS_COMPILED
562
    QSKIP("Not tested when cross-compiled", SkipAll);
563
#endif
564
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
565
    QProcess proc;
566
    proc.start("moc", QStringList(srcify("/oldstyle-casts.h")));
567
    QVERIFY(proc.waitForFinished());
568
    QCOMPARE(proc.exitCode(), 0);
569
    QByteArray mocOut = proc.readAllStandardOutput();
570
    QVERIFY(!mocOut.isEmpty());
571
    QCOMPARE(proc.readAllStandardError(), QByteArray());
572
573
    QStringList args;
574
    args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
575
         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-";
576
    proc.start("gcc", args);
577
    QVERIFY(proc.waitForStarted());
578
    proc.write(mocOut);
579
    proc.closeWriteChannel();
580
581
    QVERIFY(proc.waitForFinished());
582
    QCOMPARE(proc.exitCode(), 0);
583
    QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
584
#else
585
    QSKIP("Only tested on linux/gcc", SkipAll);
586
#endif
587
}
588
589
void tst_Moc::warnOnExtraSignalSlotQualifiaction()
590
{
591
#ifdef MOC_CROSS_COMPILED
592
    QSKIP("Not tested when cross-compiled", SkipAll);
593
#endif
594
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
595
    QProcess proc;
596
    proc.start("moc", QStringList(srcify("extraqualification.h")));
597
    QVERIFY(proc.waitForFinished());
598
    QCOMPARE(proc.exitCode(), 0);
599
    QByteArray mocOut = proc.readAllStandardOutput();
600
    QVERIFY(!mocOut.isEmpty());
601
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
602
    QCOMPARE(mocWarning, QString(SRCDIR) +
603
                QString("/extraqualification.h:53: Warning: Function declaration Test::badFunctionDeclaration contains extra qualification. Ignoring as signal or slot.\n") +
604
                QString(SRCDIR) + QString("/extraqualification.h:56: Warning: parsemaybe: Function declaration Test::anotherOne contains extra qualification. Ignoring as signal or slot.\n"));
605
#else
606
    QSKIP("Only tested on linux/gcc", SkipAll);
607
#endif
608
}
609
610
void tst_Moc::uLongLong()
611
{
612
#ifndef NOLONGLONG
613
    TestClass tst;
614
    const QMetaObject *mobj = tst.metaObject();
615
    int idx = mobj->indexOfSlot("slotWithULong(ulong)");
616
    QVERIFY(idx != -1);
617
    idx = mobj->indexOfSlot("slotWithULongLong(unsigned long long)");
618
    QVERIFY(idx != -1);
619
    idx = mobj->indexOfSlot("slotWithULongLongP(unsigned long long*)");
620
    QVERIFY(idx != -1);
621
622
    idx = mobj->indexOfSlot("slotWithLong(long)");
623
    QVERIFY(idx != -1);
624
    idx = mobj->indexOfSlot("slotWithLongLong(long long)");
625
    QVERIFY(idx != -1);
626
#else
627
    QSKIP("long long doesn't work on MSVC6 & .NET 2002, also skipped on 2003 due to compiler version issue with moc", SkipAll);
628
#endif
629
}
630
631
void tst_Moc::inputFileNameWithDotsButNoExtension()
632
{
633
#ifdef MOC_CROSS_COMPILED
634
    QSKIP("Not tested when cross-compiled", SkipAll);
635
#endif
636
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
637
    QProcess proc;
638
    proc.setWorkingDirectory(QString(SRCDIR) + "/task71021");
639
    proc.start("moc", QStringList("../Header"));
640
    QVERIFY(proc.waitForFinished());
641
    QCOMPARE(proc.exitCode(), 0);
642
    QByteArray mocOut = proc.readAllStandardOutput();
643
    QVERIFY(!mocOut.isEmpty());
644
    QCOMPARE(proc.readAllStandardError(), QByteArray());
645
646
    QStringList args;
647
    args << "-c" << "-x" << "c++" << "-I" << ".."
648
         << "-I" << qtIncludePath << "-o" << "/dev/null" << "-";
649
    proc.start("gcc", args);
650
    QVERIFY(proc.waitForStarted());
651
    proc.write(mocOut);
652
    proc.closeWriteChannel();
653
654
    QVERIFY(proc.waitForFinished());
655
    QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
656
    QCOMPARE(proc.exitCode(), 0);
657
#else
658
    QSKIP("Only tested on linux/gcc", SkipAll);
659
#endif
660
}
661
662
void tst_Moc::userProperties()
663
{
664
    const QMetaObject *mobj = metaObject();
665
    QMetaProperty property = mobj->property(mobj->indexOfProperty("user1"));
666
    QVERIFY(property.isValid());
667
    QVERIFY(property.isUser());
668
669
    property = mobj->property(mobj->indexOfProperty("user2"));
670
    QVERIFY(property.isValid());
671
    QVERIFY(!property.isUser());
672
673
    property = mobj->property(mobj->indexOfProperty("user3"));
674
    QVERIFY(property.isValid());
675
    QVERIFY(!property.isUser(this));
676
}
677
678
void tst_Moc::supportConstSignals()
679
{
680
    QSignalSpy spy1(this, SIGNAL(constSignal1()));
681
    QVERIFY(spy1.isEmpty());
682
    emit constSignal1();
683
    QCOMPARE(spy1.count(), 1);
684
685
    QSignalSpy spy2(this, SIGNAL(constSignal2(int)));
686
    QVERIFY(spy2.isEmpty());
687
    emit constSignal2(42);
688
    QCOMPARE(spy2.count(), 1);
689
    QCOMPARE(spy2.at(0).at(0).toInt(), 42);
690
}
691
692
#include "task87883.h"
693
694
void tst_Moc::task87883()
695
{
696
    QVERIFY(Task87883::staticMetaObject.className());
697
}
698
699
#include "c-comments.h"
700
701
void tst_Moc::multilineComments()
702
{
703
    QVERIFY(IfdefedClass::staticMetaObject.className());
704
}
705
706
void tst_Moc::classinfoWithEscapes()
707
{
708
    const QMetaObject *mobj = &TestClassinfoWithEscapes::staticMetaObject;
709
    QCOMPARE(mobj->methodCount() - mobj->methodOffset(), 1);
710
711
    QMetaMethod mm = mobj->method(mobj->methodOffset());
712
    QCOMPARE(mm.signature(), "slotWithAReallyLongName(int)");
713
}
714
715
void tst_Moc::trNoopInClassInfo()
716
{
717
    TestClass t;
718
    const QMetaObject *mobj = t.metaObject();
719
    QVERIFY(mobj);
720
    QCOMPARE(mobj->classInfoCount(), 3);
721
    QCOMPARE(mobj->indexOfClassInfo("help"), 0);
722
    QCOMPARE(QString(mobj->classInfo(0).value()), QString("Opening this will let you configure something"));
723
}
724
725
void tst_Moc::ppExpressionEvaluation()
726
{
727
    TestClass tst;
728
    const QMetaObject *mobj = tst.metaObject();
729
    int idx = mobj->indexOfSlot("expressionEvaluationShortcut1()");
730
    QVERIFY(idx != -1);
731
732
    idx = mobj->indexOfSlot("expressionEvaluationShortcut2()");
733
    QVERIFY(idx != -1);
734
}
735
736
void tst_Moc::arrayArguments()
737
{
738
    TestClass tst;
739
    const QMetaObject *mobj = tst.metaObject();
740
    QVERIFY(mobj->indexOfSlot("slotWithArray(const double[3])") != -1);
741
    QVERIFY(mobj->indexOfSlot("slotWithNamedArray(const double[3])") != -1);
742
    QVERIFY(mobj->indexOfSlot("slotWithMultiArray(const double[3][4])") != -1);
743
    QVERIFY(mobj->indexOfSignal("signalWithArray(const double[3])") != -1);
744
    QVERIFY(mobj->indexOfSignal("signalWithNamedArray(const double[3])") != -1);
745
}
746
747
void tst_Moc::preprocessorConditionals()
748
{
749
    TestClass tst;
750
    const QMetaObject *mobj = tst.metaObject();
751
    QVERIFY(mobj->indexOfSlot("slotInElse()") != -1);
752
    QVERIFY(mobj->indexOfSlot("slotInIf()") != -1);
753
    QVERIFY(mobj->indexOfSlot("slotInLastElse()") != -1);
754
    QVERIFY(mobj->indexOfSlot("slotInElif()") != -1);
755
}
756
757
void tst_Moc::blackslashNewlines()
758
{
759
    BackslashNewlines tst;
760
    const QMetaObject *mobj = tst.metaObject();
761
    QVERIFY(mobj->indexOfSlot("works()") != -1);
762
    QVERIFY(mobj->indexOfSlot("buggy()") == -1);
763
}
764
765
void tst_Moc::slotWithSillyConst()
766
{
767
    TestClass tst;
768
    const QMetaObject *mobj = tst.metaObject();
769
    QVERIFY(mobj->indexOfSlot("slotWithSillyConst()") != -1);
770
    QVERIFY(mobj->indexOfMethod("slotWithSillyConst2()") != -1);
771
    QVERIFY(mobj->indexOfSlot("slotWithVoidStar(void*)") != -1);
772
}
773
774
void tst_Moc::testExtraData()
775
{
776
    const QMetaObject *mobj = &PropertyTestClass::staticMetaObject;
777
    QCOMPARE(mobj->enumeratorCount(), 1);
778
    QCOMPARE(QByteArray(mobj->enumerator(0).name()), QByteArray("TestEnum"));
779
780
    mobj = &PropertyUseClass::staticMetaObject;
781
    const int idx = mobj->indexOfProperty("foo");
782
    QVERIFY(idx != -1);
783
    const QMetaProperty prop = mobj->property(idx);
784
    QVERIFY(prop.isValid());
785
    QVERIFY(prop.isEnumType());
786
    const QMetaEnum en = prop.enumerator();
787
    QCOMPARE(QByteArray(en.name()), QByteArray("TestEnum"));
788
}
789
790
void tst_Moc::namespaceTypeProperty()
791
{
792
    qRegisterMetaType<myNS::Points>("myNS::Points");
793
    TestClass tst;
794
    QByteArray ba = QByteArray("points");
795
    QVariant v = tst.property(ba);
796
    QVERIFY(v.isValid());
797
    myNS::Points p = qVariantValue<myNS::Points>(v);
798
    QCOMPARE(p.p1, 0xBEEF);
799
    QCOMPARE(p.p2, 0xBABE);
800
    p.p1 = 0xCAFE;
801
    p.p2 = 0x1EE7;
802
    QVERIFY(tst.setProperty(ba, qVariantFromValue(p)));
803
    myNS::Points pp = qVariantValue<myNS::Points>(tst.property(ba));
804
    QCOMPARE(p.p1, pp.p1);
805
    QCOMPARE(p.p2, pp.p2);
806
}
807
808
void tst_Moc::slotsWithVoidTemplate()
809
{
810
    SlotsWithVoidTemplateTest test;
811
    QVERIFY(QObject::connect(&test, SIGNAL(myVoidSignal(void)),
812
                             &test, SLOT(dummySlot(void))));
813
    QVERIFY(QObject::connect(&test, SIGNAL(mySignal(const TestTemplate<void> &)),
814
                             &test, SLOT(anotherSlot(const TestTemplate<void> &))));
815
}
816
817
void tst_Moc::structQObject()
818
{
819
    StructQObject o;
820
    QCOMPARE(QByteArray(o.metaObject()->className()), QByteArray("StructQObject"));
821
}
822
823
#include "namespaced-flags.h"
824
825
Q_DECLARE_METATYPE(QList<Foo::Bar::Flags>);
826
827
void tst_Moc::namespacedFlags()
828
{
829
    Foo::Baz baz;
830
    Foo::Bar bar;
831
832
    bar.setFlags(Foo::Bar::Read | Foo::Bar::Write);
833
    QVERIFY(baz.flags() != bar.flags());
834
835
    const QVariant v = bar.property("flags");
836
    QVERIFY(v.isValid());
837
    QVERIFY(baz.setProperty("flags", v));
838
    QVERIFY(baz.flags() == bar.flags());
839
840
    QList<Foo::Bar::Flags> l;
841
    l << baz.flags();
842
    QVariant v2 = baz.setProperty("flagsList", QVariant::fromValue(l));
843
    QCOMPARE(l, baz.flagsList());
844
    QCOMPARE(l, qvariant_cast<QList<Foo::Bar::Flags> >(baz.property("flagsList")));
845
}
846
847
void tst_Moc::warnOnMultipleInheritance()
848
{
849
#ifdef MOC_CROSS_COMPILED
850
    QSKIP("Not tested when cross-compiled", SkipAll);
851
#endif
852
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
853
    QProcess proc;
854
    QStringList args;
855
    args << "-I" << qtIncludePath + "/QtGui"
856
         << srcify("warn-on-multiple-qobject-subclasses.h");
857
    proc.start("moc", args);
858
    QVERIFY(proc.waitForFinished());
859
    QCOMPARE(proc.exitCode(), 0);
860
    QByteArray mocOut = proc.readAllStandardOutput();
861
    QVERIFY(!mocOut.isEmpty());
862
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
863
    QCOMPARE(mocWarning, QString(SRCDIR) +
864
                QString("/warn-on-multiple-qobject-subclasses.h:53: Warning: Class Bar inherits from two QObject subclasses QWidget and Foo. This is not supported!\n"));
865
#else
866
    QSKIP("Only tested on linux/gcc", SkipAll);
867
#endif
868
}
869
870
void tst_Moc::forgottenQInterface()
871
{
872
#ifdef MOC_CROSS_COMPILED
873
    QSKIP("Not tested when cross-compiled", SkipAll);
874
#endif
875
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
876
    QProcess proc;
877
    QStringList args;
878
    args << "-I" << qtIncludePath + "/QtCore"
879
         << srcify("forgotten-qinterface.h");
880
    proc.start("moc", args);
881
    QVERIFY(proc.waitForFinished());
882
    QCOMPARE(proc.exitCode(), 0);
883
    QByteArray mocOut = proc.readAllStandardOutput();
884
    QVERIFY(!mocOut.isEmpty());
885
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
886
    QCOMPARE(mocWarning, QString(SRCDIR) +
887
                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"));
888
#else
889
    QSKIP("Only tested on linux/gcc", SkipAll);
890
#endif
891
}
892
893
void tst_Moc::os9Newline()
894
{
895
#if !defined(SKIP_NEWLINE_TEST)
896
    const QMetaObject &mo = Os9Newlines::staticMetaObject;
897
    QVERIFY(mo.indexOfSlot("testSlot()") != -1);
898
    QFile f(srcify("os9-newlines.h"));
899
    QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
900
    QByteArray data = f.readAll();
901
    f.close();
902
    QVERIFY(!data.contains('\n'));
903
    QVERIFY(data.contains('\r'));
904
#endif
905
}
906
907
void tst_Moc::winNewline()
908
{
909
#if !defined(SKIP_NEWLINE_TEST)
910
    const QMetaObject &mo = WinNewlines::staticMetaObject;
911
    QVERIFY(mo.indexOfSlot("testSlot()") != -1);
912
    QFile f(srcify("win-newlines.h"));
913
    QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text!
914
    QByteArray data = f.readAll();
915
    f.close();
916
    for (int i = 0; i < data.count(); ++i) {
917
        if (data.at(i) == QLatin1Char('\r')) {
918
            QVERIFY(i < data.count() - 1);
919
            ++i;
920
            QVERIFY(data.at(i) == '\n');
921
        } else {
922
            QVERIFY(data.at(i) != '\n');
923
        }
924
    }
925
#endif
926
}
927
928
void tst_Moc::escapesInStringLiterals()
929
{
930
    const QMetaObject &mo = StringLiterals::staticMetaObject;
931
    QCOMPARE(mo.classInfoCount(), 3);
932
933
    int idx = mo.indexOfClassInfo("Test");
934
    QVERIFY(idx != -1);
935
    QMetaClassInfo info = mo.classInfo(idx);
936
    QCOMPARE(QByteArray(info.value()),
937
             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x53"));
938
939
    QVERIFY(idx != -1);
940
    idx = mo.indexOfClassInfo("Test2");
941
    info = mo.classInfo(idx);
942
    QCOMPARE(QByteArray(info.value()),
943
             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\123"));
944
945
    QVERIFY(idx != -1);
946
    idx = mo.indexOfClassInfo("Test3");
947
    info = mo.classInfo(idx);
948
    QCOMPARE(QByteArray(info.value()),
949
             QByteArray("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\nb"));
950
}
951
952
void tst_Moc::frameworkSearchPath()
953
{
954
#ifdef MOC_CROSS_COMPILED
955
    QSKIP("Not tested when cross-compiled", SkipAll);
956
#endif
957
#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS)
958
    QStringList args;
959
    args << "-F" << srcify(".")
960
         << srcify("interface-from-framework.h")
961
         ;
962
963
    QProcess proc;
964
    proc.start("moc", args);
965
    bool finished = proc.waitForFinished();
966
    if (!finished)
967
        qWarning("waitForFinished failed. QProcess error: %d", (int)proc.error());
968
    QVERIFY(finished);
969
    if (proc.exitCode() != 0) {
970
        qDebug() << proc.readAllStandardError();
971
    }
972
    QCOMPARE(proc.exitCode(), 0);
973
    QCOMPARE(proc.readAllStandardError(), QByteArray());
974
#else
975
    QSKIP("Only tested/relevant on unixy platforms", SkipAll);
976
#endif
977
}
978
979
void tst_Moc::cstyleEnums()
980
{
981
    const QMetaObject &obj = CStyleEnums::staticMetaObject;
982
    QCOMPARE(obj.enumeratorCount(), 1);
983
    QMetaEnum metaEnum = obj.enumerator(0);
984
    QCOMPARE(metaEnum.name(), "Baz");
985
    QCOMPARE(metaEnum.keyCount(), 2);
986
    QCOMPARE(metaEnum.key(0), "Foo");
987
    QCOMPARE(metaEnum.key(1), "Bar");
988
}
989
990
void tst_Moc::templateGtGt()
991
{
992
#ifdef MOC_CROSS_COMPILED
993
    QSKIP("Not tested when cross-compiled", SkipAll);
994
#endif
995
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
996
    QProcess proc;
997
    proc.start("moc", QStringList(srcify("template-gtgt.h")));
998
    QVERIFY(proc.waitForFinished());
999
    QCOMPARE(proc.exitCode(), 0);
1000
    QByteArray mocOut = proc.readAllStandardOutput();
1001
    QVERIFY(!mocOut.isEmpty());
1002
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
1003
    QVERIFY(mocWarning.isEmpty());
1004
#else
1005
    QSKIP("Only tested on linux/gcc", SkipAll);
1006
#endif
1007
}
1008
1009
void tst_Moc::defineMacroViaCmdline()
1010
{
1011
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1012
    QProcess proc;
1013
1014
    QStringList args;
1015
    args << "-DFOO";
1016
    args << srcify("macro-on-cmdline.h");
1017
1018
    proc.start("moc", args);
1019
    QVERIFY(proc.waitForFinished());
1020
    QCOMPARE(proc.exitCode(), 0);
1021
    QCOMPARE(proc.readAllStandardError(), QByteArray());
1022
    QByteArray mocOut = proc.readAllStandardOutput();
1023
    QVERIFY(!mocOut.isEmpty());
1024
#else
1025
    QSKIP("Only tested on linux/gcc", SkipAll);
1026
#endif
1027
}
1028
1029
void tst_Moc::invokable()
1030
{
1031
    {
1032
        const QMetaObject &mobj = InvokableBeforeReturnType::staticMetaObject;
1033
        QCOMPARE(mobj.methodCount(), 5);
1034
        QVERIFY(mobj.method(4).signature() == QByteArray("foo()"));
1035
    }
1036
1037
    {
1038
        const QMetaObject &mobj = InvokableBeforeInline::staticMetaObject;
1039
        QCOMPARE(mobj.methodCount(), 6);
1040
        QVERIFY(mobj.method(4).signature() == QByteArray("foo()"));
1041
        QVERIFY(mobj.method(5).signature() == QByteArray("bar()"));
1042
    }
1043
}
1044
1045
void tst_Moc::singleFunctionKeywordSignalAndSlot()
1046
{
1047
    {
1048
        const QMetaObject &mobj = SingleFunctionKeywordBeforeReturnType::staticMetaObject;
1049
        QCOMPARE(mobj.methodCount(), 6);
1050
        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
1051
        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
1052
    }
1053
1054
    {
1055
        const QMetaObject &mobj = SingleFunctionKeywordBeforeInline::staticMetaObject;
1056
        QCOMPARE(mobj.methodCount(), 6);
1057
        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
1058
        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
1059
    }
1060
1061
    {
1062
        const QMetaObject &mobj = SingleFunctionKeywordAfterInline::staticMetaObject;
1063
        QCOMPARE(mobj.methodCount(), 6);
1064
        QVERIFY(mobj.method(4).signature() == QByteArray("mySignal()"));
1065
        QVERIFY(mobj.method(5).signature() == QByteArray("mySlot()"));
1066
    }
1067
}
1068
1069
#include "qprivateslots.h"
1070
1071
void tst_Moc::qprivateslots()
1072
{
1073
    TestQPrivateSlots tst;
1074
    const QMetaObject *mobj = tst.metaObject();
1075
    QVERIFY(mobj->indexOfSlot("_q_privateslot()") != -1);
1076
    QVERIFY(mobj->indexOfMethod("method1()") != -1); //tast204730
1077
}
1078
1079
class PrivatePropertyTest : public QObject
1080
{
1081
    Q_OBJECT
1082
    Q_PROPERTY(int foo READ foo WRITE setFoo)
1083
    Q_PRIVATE_PROPERTY(d, int bar READ bar WRITE setBar)
1084
    Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, int plop READ plop WRITE setPlop)
1085
    Q_PRIVATE_PROPERTY(PrivatePropertyTest::d_func(), int baz READ baz WRITE setBaz)
1086
    class MyDPointer {
1087
    public:
1088
        MyDPointer() : mBar(0), mPlop(0) {}
1089
        int bar() { return mBar ; }
1090
        void setBar(int value) { mBar = value; }
1091
        int plop() { return mPlop ; }
1092
        void setPlop(int value) { mPlop = value; }
1093
        int baz() { return mBaz ; }
1094
        void setBaz(int value) { mBaz = value; }
1095
    private:
1096
        int mBar;
1097
        int mPlop;
1098
        int mBaz;
1099
    };
1100
public:
1101
    PrivatePropertyTest() : mFoo(0), d (new MyDPointer) {}
1102
    int foo() { return mFoo ; }
1103
    void setFoo(int value) { mFoo = value; }
1104
    MyDPointer *d_func() {return d;}
1105
private:
1106
    int mFoo;
1107
    MyDPointer *d;
1108
};
1109
1110
1111
void tst_Moc::qprivateproperties()
1112
{
1113
    PrivatePropertyTest test;
1114
1115
    test.setProperty("foo", 1);
1116
    QCOMPARE(test.property("foo"), qVariantFromValue(1));
1117
1118
    test.setProperty("bar", 2);
1119
    QCOMPARE(test.property("bar"), qVariantFromValue(2));
1120
1121
    test.setProperty("plop", 3);
1122
    QCOMPARE(test.property("plop"), qVariantFromValue(3));
1123
1124
    test.setProperty("baz", 4);
1125
    QCOMPARE(test.property("baz"), qVariantFromValue(4));
1126
1127
}
1128
1129
#include "task189996.h"
1130
1131
void InlineSlotsWithThrowDeclaration::c() throw() {}
1132
1133
void tst_Moc::inlineSlotsWithThrowDeclaration()
1134
{
1135
    InlineSlotsWithThrowDeclaration tst;
1136
    const QMetaObject *mobj = tst.metaObject();
1137
    QVERIFY(mobj->indexOfSlot("a()") != -1);
1138
    QVERIFY(mobj->indexOfSlot("b()") != -1);
1139
    QVERIFY(mobj->indexOfSlot("c()") != -1);
1140
    QVERIFY(mobj->indexOfSlot("d()") != -1);
1141
    QVERIFY(mobj->indexOfSlot("e()") != -1);
1142
}
1143
1144
void tst_Moc::warnOnPropertyWithoutREAD()
1145
{
1146
#ifdef MOC_CROSS_COMPILED
1147
    QSKIP("Not tested when cross-compiled", SkipAll);
1148
#endif
1149
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1150
    QProcess proc;
1151
    proc.start("moc", QStringList(srcify("warn-on-property-without-read.h")));
1152
    QVERIFY(proc.waitForFinished());
1153
    QCOMPARE(proc.exitCode(), 0);
1154
    QByteArray mocOut = proc.readAllStandardOutput();
1155
    QVERIFY(!mocOut.isEmpty());
1156
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
1157
    QCOMPARE(mocWarning, QString(SRCDIR) +
1158
                QString("/warn-on-property-without-read.h:46: Warning: Property declaration foo has no READ accessor function. The property will be invalid.\n"));
1159
#else
1160
    QSKIP("Only tested on linux/gcc", SkipAll);
1161
#endif
1162
}
1163
1164
void tst_Moc::constructors()
1165
{
1166
    const QMetaObject *mo = &CtorTestClass::staticMetaObject;
1167
    QCOMPARE(mo->constructorCount(), 3);
1168
    {
1169
        QMetaMethod mm = mo->constructor(0);
1170
        QCOMPARE(mm.access(), QMetaMethod::Public);
1171
        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1172
        QCOMPARE(mm.signature(), "CtorTestClass(QObject*)");
1173
        QCOMPARE(mm.typeName(), "");
1174
        QList<QByteArray> paramNames = mm.parameterNames();
1175
        QCOMPARE(paramNames.size(), 1);
1176
        QCOMPARE(paramNames.at(0), QByteArray("parent"));
1177
        QList<QByteArray> paramTypes = mm.parameterTypes();
1178
        QCOMPARE(paramTypes.size(), 1);
1179
        QCOMPARE(paramTypes.at(0), QByteArray("QObject*"));
1180
    }
1181
    {
1182
        QMetaMethod mm = mo->constructor(1);
1183
        QCOMPARE(mm.access(), QMetaMethod::Public);
1184
        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1185
        QCOMPARE(mm.signature(), "CtorTestClass()");
1186
        QCOMPARE(mm.typeName(), "");
1187
        QCOMPARE(mm.parameterNames().size(), 0);
1188
        QCOMPARE(mm.parameterTypes().size(), 0);
1189
    }
1190
    {
1191
        QMetaMethod mm = mo->constructor(2);
1192
        QCOMPARE(mm.access(), QMetaMethod::Public);
1193
        QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
1194
        QCOMPARE(mm.signature(), "CtorTestClass(QString)");
1195
        QCOMPARE(mm.typeName(), "");
1196
        QList<QByteArray> paramNames = mm.parameterNames();
1197
        QCOMPARE(paramNames.size(), 1);
1198
        QCOMPARE(paramNames.at(0), QByteArray("str"));
1199
        QList<QByteArray> paramTypes = mm.parameterTypes();
1200
        QCOMPARE(paramTypes.size(), 1);
1201
        QCOMPARE(paramTypes.at(0), QByteArray("QString"));
1202
    }
1203
1204
    QCOMPARE(mo->indexOfConstructor("CtorTestClass(QObject*)"), 0);
1205
    QCOMPARE(mo->indexOfConstructor("CtorTestClass()"), 1);
1206
    QCOMPARE(mo->indexOfConstructor("CtorTestClass(QString)"), 2);
1207
    QCOMPARE(mo->indexOfConstructor("CtorTestClass2(QObject*)"), -1);
1208
    QCOMPARE(mo->indexOfConstructor("CtorTestClass(float,float)"), -1);
1209
1210
    QObject *o1 = mo->newInstance();
1211
    QVERIFY(o1 != 0);
1212
    QCOMPARE(o1->parent(), (QObject*)0);
1213
    QVERIFY(qobject_cast<CtorTestClass*>(o1) != 0);
1214
1215
    QObject *o2 = mo->newInstance(Q_ARG(QObject*, o1));
1216
    QVERIFY(o2 != 0);
1217
    QCOMPARE(o2->parent(), o1);
1218
1219
    QString str = QString::fromLatin1("hello");
1220
    QObject *o3 = mo->newInstance(Q_ARG(QString, str));
1221
    QVERIFY(o3 != 0);
1222
    QCOMPARE(qobject_cast<CtorTestClass*>(o3)->m_str, str);
1223
1224
    {
1225
        //explicit constructor
1226
        QObject *o = QObject::staticMetaObject.newInstance();
1227
        QVERIFY(o);
1228
        delete o;
1229
    }
1230
}
1231
1232
#include "task234909.h"
1233
1234
#include "task240368.h"
1235
1236
void tst_Moc::typenameWithUnsigned()
1237
{
1238
    TypenameWithUnsigned tst;
1239
    const QMetaObject *mobj = tst.metaObject();
1240
    QVERIFY(mobj->indexOfSlot("a(uint)") != -1);
1241
    QVERIFY(mobj->indexOfSlot("b(uint)") != -1);
1242
    QVERIFY(mobj->indexOfSlot("c(uint*)") != -1);
1243
    QVERIFY(mobj->indexOfSlot("d(uint*)") != -1);
1244
    QVERIFY(mobj->indexOfSlot("e(uint&)") != -1);
1245
    QVERIFY(mobj->indexOfSlot("f(uint&)") != -1);
1246
    QVERIFY(mobj->indexOfSlot("g(unsigned1)") != -1);
1247
    QVERIFY(mobj->indexOfSlot("h(unsigned1)") != -1);
1248
    QVERIFY(mobj->indexOfSlot("i(uint,unsigned1)") != -1);
1249
    QVERIFY(mobj->indexOfSlot("j(unsigned1,uint)") != -1);
1250
    QVERIFY(mobj->indexOfSlot("k(unsignedQImage)") != -1);
1251
    QVERIFY(mobj->indexOfSlot("l(unsignedQImage)") != -1);
1252
}
1253
1254
1255
void tst_Moc::warnOnVirtualSignal()
1256
{
1257
#ifdef MOC_CROSS_COMPILED
1258
    QSKIP("Not tested when cross-compiled", SkipAll);
1259
#endif
1260
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1261
    QProcess proc;
1262
    proc.start("moc", QStringList(srcify("pure-virtual-signals.h")));
1263
    QVERIFY(proc.waitForFinished());
1264
    QCOMPARE(proc.exitCode(), 0);
1265
    QByteArray mocOut = proc.readAllStandardOutput();
1266
    QVERIFY(!mocOut.isEmpty());
1267
    QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError());
1268
    QCOMPARE(mocWarning, QString(SRCDIR) + QString("/pure-virtual-signals.h:48: Warning: Signals cannot be declared virtual\n") +
1269
                         QString(SRCDIR) + QString("/pure-virtual-signals.h:50: Warning: Signals cannot be declared virtual\n"));
1270
#else
1271
    QSKIP("Only tested on linux/gcc", SkipAll);
1272
#endif
1273
}
1274
1275
1276
class QTBUG5590_DummyObject: public QObject
1277
{
1278
    Q_OBJECT
1279
    Q_PROPERTY(bool dummy)
1280
};
1281
1282
class QTBUG5590_PropertyObject: public QTBUG5590_DummyObject
1283
{
1284
    Q_OBJECT
1285
    Q_PROPERTY(int value READ value WRITE setValue)
1286
    Q_PROPERTY(int value2 READ value2 WRITE setValue2)
1287
1288
    public:
1289
        QTBUG5590_PropertyObject() :  m_value(85), m_value2(40) { }
1290
        int value() const { return m_value; }
1291
        void setValue(int value) { m_value = value; }
1292
        int value2() const { return m_value2; }
1293
        void setValue2(int value) { m_value2 = value; }
1294
    private:
1295
        int m_value, m_value2;
1296
};
1297
1298
void tst_Moc::QTBUG5590_dummyProperty()
1299
{
1300
    QTBUG5590_PropertyObject o;
1301
    QCOMPARE(o.property("value").toInt(), 85);
1302
    QCOMPARE(o.property("value2").toInt(), 40);
1303
    o.setProperty("value", 32);
1304
    QCOMPARE(o.value(), 32);
1305
    o.setProperty("value2", 82);
1306
    QCOMPARE(o.value2(), 82);
1307
}
1308
1309
class QTBUG7421_ReturnConstTemplate: public QObject
1310
{ Q_OBJECT
1311
public slots:
1312
        const QList<int> returnConstTemplate1() { return QList<int>(); }
1313
        QList<int> const returnConstTemplate2() { return QList<int>(); }
1314
        const int returnConstInt() { return 0; }
1315
        const QString returnConstString(const QString s) { return s; }
1316
        QString const returnConstString2( QString const s) { return s; }
1317
};
1318
1319
class QTBUG9354_constInName: public QObject
1320
{ Q_OBJECT
1321
public slots:
1322
    void slotChooseScientificConst0(struct science_constant const &) {};
1323
    void foo(struct science_const const &) {};
1324
    void foo(struct constconst const &) {};
1325
    void foo(struct constconst *) {};
1326
    void foo(struct const_ *) {};
1327
};
1328
1329
1330
template<typename T1, typename T2>
1331
class TestTemplate2
1332
{
1333
};
1334
1335
class QTBUG11647_constInTemplateParameter : public QObject
1336
{ Q_OBJECT
1337
public slots:
1338
    void testSlot(TestTemplate2<const int, const short*>) {}
1339
    void testSlot2(TestTemplate2<int, short const * const >) {}
1340
    void testSlot3(TestTemplate2<TestTemplate2 < const int, const short* > const *,
1341
                                TestTemplate2< TestTemplate2 < void, int > , unsigned char *> > ) {}
1342
1343
signals:
1344
    void testSignal(TestTemplate2<const int, const short*>);
1345
};
1346
1347
class QTBUG12260_defaultTemplate_Object : public QObject
1348
{ Q_OBJECT
1349
public slots:
1350
#if !(defined(Q_CC_GNU) && __GNUC__ == 4 && __GNUC_MINOR__ <= 3) || defined(Q_MOC_RUN)
1351
    void doSomething(QHash<QString, QVariant> values = QHash<QString, QVariant>() ) { Q_UNUSED(values); }
1352
#else
1353
    // we want to test the previous function, but gcc < 4.4 seemed to have a bug similar to the one moc has.
1354
    typedef QHash<QString, QVariant> WorkaroundGCCBug;
1355
    void doSomething(QHash<QString, QVariant> values = WorkaroundGCCBug() ) { Q_UNUSED(values); }
1356
#endif
1357
1358
    void doAnotherThing(bool a = (1 < 3), bool b = (1 > 4)) { Q_UNUSED(a); Q_UNUSED(b); }
1359
};
1360
1361
1362
void tst_Moc::QTBUG12260_defaultTemplate()
1363
{
1364
    QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomething(QHash<QString,QVariant>)") != -1);
1365
    QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doAnotherThing(bool,bool)") != -1);
1366
}
1367
1368
void tst_Moc::notifyError()
1369
{
1370
#ifdef MOC_CROSS_COMPILED
1371
    QSKIP("Not tested when cross-compiled", SkipAll);
1372
#endif
1373
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
1374
    QProcess proc;
1375
    proc.start("moc", QStringList(srcify("error-on-wrong-notify.h")));
1376
    QVERIFY(proc.waitForFinished());
1377
    QCOMPARE(proc.exitCode(), 1);
1378
    QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
1379
    QByteArray mocOut = proc.readAllStandardOutput();
1380
    QVERIFY(mocOut.isEmpty());
1381
    QString mocError = QString::fromLocal8Bit(proc.readAllStandardError());
1382
    QCOMPARE(mocError, QString(SRCDIR) +
1383
        QString("/error-on-wrong-notify.h:52: Error: NOTIFY signal 'fooChanged' of property 'foo' does not exist in class ClassWithWrongNOTIFY.\n"));
1384
#else
1385
    QSKIP("Only tested on linux/gcc", SkipAll);
1386
#endif
1387
}
1388
1389
// If changed, update VersionTestNotify below
1390
class VersionTest : public QObject
1391
{
1392
    Q_OBJECT
1393
    Q_PROPERTY(int prop1 READ foo)
1394
    Q_PROPERTY(int prop2 READ foo REVISION 2)
1395
    Q_ENUMS(TestEnum);
1396
1397
public:
1398
    int foo() const { return 0; }
1399
1400
    Q_INVOKABLE void method1() {}
1401
    Q_INVOKABLE Q_REVISION(4) void method2() {}
1402
1403
    enum TestEnum { One, Two };
1404
1405
public slots:
1406
    void slot1() {}
1407
    Q_REVISION(3) void slot2() {}
1408
1409
signals:
1410
    void signal1();
1411
    Q_REVISION(5) void signal2();
1412
1413
public slots Q_REVISION(6):
1414
    void slot3() {}
1415
    void slot4() {}
1416
1417
signals Q_REVISION(7):
1418
    void signal3();
1419
    void signal4();
1420
};
1421
1422
// If changed, update VersionTest above
1423
class VersionTestNotify : public QObject
1424
{
1425
    Q_OBJECT
1426
    Q_PROPERTY(int prop1 READ foo NOTIFY fooChanged)
1427
    Q_PROPERTY(int prop2 READ foo REVISION 2)
1428
    Q_ENUMS(TestEnum);
1429
1430
public:
1431
    int foo() const { return 0; }
1432
1433
    Q_INVOKABLE void method1() {}
1434
    Q_INVOKABLE Q_REVISION(4) void method2() {}
1435
1436
    enum TestEnum { One, Two };
1437
1438
public slots:
1439
    void slot1() {}
1440
    Q_REVISION(3) void slot2() {}
1441
1442
signals:
1443
    void fooChanged();
1444
    void signal1();
1445
    Q_REVISION(5) void signal2();
1446
1447
public slots Q_REVISION(6):
1448
    void slot3() {}
1449
    void slot4() {}
1450
1451
signals Q_REVISION(7):
1452
    void signal3();
1453
    void signal4();
1454
};
1455
1456
template <class T>
1457
void tst_Moc::revisions_T()
1458
{
1459
    int idx = T::staticMetaObject.indexOfProperty("prop1");
1460
    QVERIFY(T::staticMetaObject.property(idx).revision() == 0);
1461
    idx = T::staticMetaObject.indexOfProperty("prop2");
1462
    QVERIFY(T::staticMetaObject.property(idx).revision() == 2);
1463
1464
    idx = T::staticMetaObject.indexOfMethod("method1()");
1465
    QVERIFY(T::staticMetaObject.method(idx).revision() == 0);
1466
    idx = T::staticMetaObject.indexOfMethod("method2()");
1467
    QVERIFY(T::staticMetaObject.method(idx).revision() == 4);
1468
1469
    idx = T::staticMetaObject.indexOfSlot("slot1()");
1470
    QVERIFY(T::staticMetaObject.method(idx).revision() == 0);
1471
    idx = T::staticMetaObject.indexOfSlot("slot2()");
1472
    QVERIFY(T::staticMetaObject.method(idx).revision() == 3);
1473
1474
    idx = T::staticMetaObject.indexOfSlot("slot3()");
1475
    QVERIFY(T::staticMetaObject.method(idx).revision() == 6);
1476
    idx = T::staticMetaObject.indexOfSlot("slot4()");
1477
    QVERIFY(T::staticMetaObject.method(idx).revision() == 6);
1478
1479
    idx = T::staticMetaObject.indexOfSignal("signal1()");
1480
    QVERIFY(T::staticMetaObject.method(idx).revision() == 0);
1481
    idx = T::staticMetaObject.indexOfSignal("signal2()");
1482
    QVERIFY(T::staticMetaObject.method(idx).revision() == 5);
1483
1484
    idx = T::staticMetaObject.indexOfSignal("signal3()");
1485
    QVERIFY(T::staticMetaObject.method(idx).revision() == 7);
1486
    idx = T::staticMetaObject.indexOfSignal("signal4()");
1487
    QVERIFY(T::staticMetaObject.method(idx).revision() == 7);
1488
1489
    idx = T::staticMetaObject.indexOfEnumerator("TestEnum");
1490
    QCOMPARE(T::staticMetaObject.enumerator(idx).keyCount(), 2);
1491
    QCOMPARE(T::staticMetaObject.enumerator(idx).key(0), "One");
1492
}
1493
1494
// test using both class that has properties with and without NOTIFY signals
1495
void tst_Moc::revisions()
1496
{
1497
    revisions_T<VersionTest>();
1498
    revisions_T<VersionTestNotify>();
1499
}
1500
1501
QTEST_APPLESS_MAIN(tst_Moc)
1502
#include "tst_moc.moc"