summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro1
-rw-r--r--tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp2
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp4
-rw-r--r--tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp2
-rw-r--r--tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp65
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp16
-rw-r--r--tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp8
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp9
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp24
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp174
-rw-r--r--tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp12
-rw-r--r--tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp33
-rw-r--r--tests/auto/dbus/qdbustype/tst_qdbustype.cpp13
-rw-r--r--tests/auto/gui/image/qimage/images/jpeg_exif_QTBUG-45865.jpgbin0 -> 27540 bytes
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp53
-rw-r--r--tests/auto/gui/kernel/qtouchevent/BLACKLIST6
-rw-r--r--tests/auto/gui/kernel/qtouchevent/qtouchevent.pro2
-rw-r--r--tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp316
-rw-r--r--tests/auto/gui/kernel/qwindow/BLACKLIST6
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp174
-rw-r--r--tests/auto/network/kernel/qhostinfo/BLACKLIST3
-rw-r--r--tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp21
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp10
-rw-r--r--tests/auto/other/baselineexample/baselineexample.pro19
-rw-r--r--tests/auto/other/baselineexample/tst_baselineexample.cpp138
-rw-r--r--tests/auto/other/other.pro3
-rw-r--r--tests/auto/testlib/selftests/blacklisted/BLACKLIST12
-rw-r--r--tests/auto/testlib/selftests/blacklisted/blacklisted.pro7
-rw-r--r--tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp94
-rw-r--r--tests/auto/testlib/selftests/expected_blacklisted.txt26
-rw-r--r--tests/auto/testlib/selftests/selftests.pri1
-rw-r--r--tests/auto/testlib/selftests/selftests.qrc1
-rw-r--r--tests/auto/testlib/selftests/tst_selftests.cpp8
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp25
-rw-r--r--tests/auto/tools/qmake/testdata/comments/comments.pro31
-rw-r--r--tests/auto/tools/qmake/testdata/func_export/func_export.pro19
-rw-r--r--tests/auto/tools/qmake/testdata/func_variables/func_variables.pro49
-rw-r--r--tests/auto/tools/qmake/testdata/functions/1.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/2.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/functions.pro184
-rw-r--r--tests/auto/tools/qmake/testdata/functions/one/1.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/one/2.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/textfile1
-rw-r--r--tests/auto/tools/qmake/testdata/functions/three/wildcard21.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/three/wildcard22.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/two/1.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/two/2.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/wildcard21.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/functions/wildcard22.cpp32
-rw-r--r--tests/auto/tools/qmake/testdata/include_function/existing_file.pri3
-rw-r--r--tests/auto/tools/qmake/testdata/include_function/include_existing_file.pro7
-rw-r--r--tests/auto/tools/qmake/testdata/include_function/include_missing_file.pro3
-rw-r--r--tests/auto/tools/qmake/testdata/include_function/include_missing_file2.pro3
-rw-r--r--tests/auto/tools/qmake/testdata/include_function/main.cpp37
-rw-r--r--tests/auto/tools/qmake/testdata/json/json.pro26
-rw-r--r--tests/auto/tools/qmake/testdata/json/test.json9
-rw-r--r--tests/auto/tools/qmake/testdata/operators/operators.pro23
-rw-r--r--tests/auto/tools/qmake/testdata/variables/variables.pro12
-rw-r--r--tests/auto/tools/qmake/tst_qmake.cpp93
-rw-r--r--tests/auto/tools/qmakelib/evaltest.cpp2513
-rw-r--r--tests/auto/tools/qmakelib/parsertest.cpp1987
-rw-r--r--tests/auto/tools/qmakelib/qmakelib.pro12
-rw-r--r--tests/auto/tools/qmakelib/testdata/cat/file1.txt2
-rw-r--r--tests/auto/tools/qmakelib/testdata/cat/file2.txt5
-rw-r--r--tests/auto/tools/qmakelib/testdata/files/dir/file1.txt0
-rw-r--r--tests/auto/tools/qmakelib/testdata/files/dir/file2.txt0
-rw-r--r--tests/auto/tools/qmakelib/testdata/files/file1.txt0
-rw-r--r--tests/auto/tools/qmakelib/testdata/files/file2.txt0
-rw-r--r--tests/auto/tools/qmakelib/testdata/files/other.txt0
-rw-r--r--tests/auto/tools/qmakelib/testdata/fromfile/badfile.prx1
-rw-r--r--tests/auto/tools/qmakelib/testdata/fromfile/infile.prx (renamed from tests/auto/tools/qmake/testdata/functions/infiletest.pro)0
-rw-r--r--tests/auto/tools/qmakelib/testdata/include/inc.pri8
-rw-r--r--tests/auto/tools/qmakelib/testdata/mkspecs/fake-g++/qmake.conf1
-rw-r--r--tests/auto/tools/qmakelib/testdata/mkspecs/features/default_post.prf1
-rw-r--r--tests/auto/tools/qmakelib/testdata/mkspecs/features/default_pre.prf1
-rw-r--r--tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_post.prf1
-rw-r--r--tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_pre.prf1
-rw-r--r--tests/auto/tools/qmakelib/testdata/mkspecs/features/testfeat.prf1
-rw-r--r--tests/auto/tools/qmakelib/tst_qmakelib.cpp2059
-rw-r--r--tests/auto/tools/qmakelib/tst_qmakelib.h111
-rw-r--r--tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp32
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp62
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp8
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp8
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp78
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp34
-rw-r--r--tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp62
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST121
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp57
-rw-r--r--tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp66
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp2
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp45
-rw-r--r--tests/auto/widgets/widgets/qmenu/BLACKLIST2
-rw-r--r--tests/auto/widgets/widgets/qmenubar/BLACKLIST2
96 files changed, 6168 insertions, 3230 deletions
diff --git a/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro
index 21cab8f67d..7b374505ce 100644
--- a/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro
+++ b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro
@@ -1,3 +1,4 @@
+CONFIG += testcase
QT += testlib core-private
QT -= gui
diff --git a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
index f792b34d48..3b730d97f9 100644
--- a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
+++ b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
@@ -151,7 +151,7 @@ void tst_QBuffer::readBlock()
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
b.open(QIODevice::WriteOnly);
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
- QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::read (QBuffer): WriteOnly device");
QCOMPARE(b.read(a, arraySize), (qint64) -1); // no read access
b.close();
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 98963108be..5025dd38db 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -2334,7 +2334,7 @@ void tst_QFile::readFromWriteOnlyFile()
QFile file("writeonlyfile");
QVERIFY(file.open(QFile::WriteOnly));
char c;
- QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::read (QFile, \"writeonlyfile\"): WriteOnly device");
QCOMPARE(file.read(&c, 1), qint64(-1));
}
@@ -2343,7 +2343,7 @@ void tst_QFile::writeToReadOnlyFile()
QFile file("readonlyfile");
QVERIFY(file.open(QFile::ReadOnly));
char c = 0;
- QTest::ignoreMessage(QtWarningMsg, "QIODevice::write: ReadOnly device");
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::write (QFile, \"readonlyfile\"): ReadOnly device");
QCOMPARE(file.write(&c, 1), qint64(-1));
}
diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
index f756588e80..565ca18899 100644
--- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
+++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
@@ -224,7 +224,7 @@ void tst_QIODevice::unget()
buf[0] = '@';
buf[1] = '@';
QTest::ignoreMessage(QtWarningMsg,
- "QIODevice::readLine: Called with maxSize < 2");
+ "QIODevice::readLine (QBuffer): Called with maxSize < 2");
QCOMPARE(buffer.readLine(buf, 1), qint64(-1));
QCOMPARE(buffer.readLine(buf, 2), qint64(i < 4 ? 1 : -1));
switch (i) {
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
index bef3d3a012..27614e0eb8 100644
--- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
@@ -57,11 +57,16 @@ private slots:
void waitForLock();
void staleLockFromCrashedProcess_data();
void staleLockFromCrashedProcess();
+ void staleLockFromCrashedProcessReusedPid();
void staleShortLockFromBusyProcess();
void staleLongLockFromBusyProcess();
void staleLockRace();
void noPermissions();
void noPermissionsWindows();
+ void corruptedLockFile();
+
+private:
+ static bool overwritePidInLockFile(const QString &filePath, qint64 pid);
public:
QString m_helperApp;
@@ -276,6 +281,30 @@ void tst_QLockFile::staleLockFromCrashedProcess()
#endif // !QT_NO_PROCESS
}
+void tst_QLockFile::staleLockFromCrashedProcessReusedPid()
+{
+#if defined(QT_NO_PROCESS)
+ QSKIP("This test requires QProcess support");
+#elif defined(Q_OS_WINRT) || defined(Q_OS_WINCE) || defined(Q_OS_IOS)
+ QSKIP("We cannot retrieve information about other processes on this platform.");
+#else
+ const QString fileName = dir.path() + "/staleLockFromCrashedProcessReusedPid";
+
+ int ret = QProcess::execute(m_helperApp, QStringList() << fileName << "-crash");
+ QCOMPARE(ret, int(QLockFile::NoError));
+ QVERIFY(QFile::exists(fileName));
+ QVERIFY(overwritePidInLockFile(fileName, QCoreApplication::applicationPid()));
+
+ QLockFile secondLock(fileName);
+ qint64 pid = 0;
+ secondLock.getLockInfo(&pid, 0, 0);
+ QCOMPARE(pid, QCoreApplication::applicationPid());
+ secondLock.setStaleLockTime(0);
+ QVERIFY(secondLock.tryLock());
+ QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
+#endif // !QT_NO_PROCESS
+}
+
void tst_QLockFile::staleShortLockFromBusyProcess()
{
#ifdef QT_NO_PROCESS
@@ -480,5 +509,41 @@ void tst_QLockFile::noPermissionsWindows()
QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError));
}
+void tst_QLockFile::corruptedLockFile()
+{
+ const QString fileName = dir.path() + "/corruptedLockFile";
+
+ {
+ // Create a empty file. Typically the result of a computer crash or hard disk full.
+ QFile file(fileName);
+ QVERIFY(file.open(QFile::WriteOnly));
+ }
+
+ QLockFile secondLock(fileName);
+ secondLock.setStaleLockTime(100);
+ QVERIFY(secondLock.tryLock(10000));
+ QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
+}
+
+bool tst_QLockFile::overwritePidInLockFile(const QString &filePath, qint64 pid)
+{
+ QFile f(filePath);
+ if (!f.open(QFile::ReadWrite)) {
+ qWarning("Cannot open %s.", qPrintable(filePath));
+ return false;
+ }
+ QByteArray buf = f.readAll();
+ int i = buf.indexOf('\n');
+ if (i < 0) {
+ qWarning("Unexpected lockfile content.");
+ return false;
+ }
+ buf.remove(0, i);
+ buf.prepend(QByteArray::number(pid));
+ f.seek(0);
+ f.resize(buf.size());
+ return f.write(buf) == buf.size();
+}
+
QTEST_MAIN(tst_QLockFile)
#include "tst_qlockfile.moc"
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index ff4963a960..924db17c04 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -112,6 +112,22 @@ void tst_QCoreApplication::qAppName()
// The application name should still be available after destruction;
// global statics often rely on this.
QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1(appName));
+
+ // Setting the appname before creating the application should work (QTBUG-45283)
+ const QString wantedAppName("my app name");
+ {
+ int argc = 1;
+ char *argv[] = { const_cast<char*>(appName) };
+ QCoreApplication::setApplicationName(wantedAppName);
+ TestApplication app(argc, argv);
+ QCOMPARE(::qAppName(), QString::fromLatin1(appName));
+ QCOMPARE(QCoreApplication::applicationName(), wantedAppName);
+ }
+ QCOMPARE(QCoreApplication::applicationName(), wantedAppName);
+
+ // Restore to initial value
+ QCoreApplication::setApplicationName(QString());
+ QCOMPARE(QCoreApplication::applicationName(), QString());
}
void tst_QCoreApplication::argc()
diff --git a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
index 17b00ebf63..5a10cf51e6 100644
--- a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
+++ b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
@@ -91,5 +91,13 @@ void tst_QMetaEnum::valuesToKeys()
QCOMPARE(me.valueToKeys(windowFlags), expected);
}
+Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<tst_QMetaEnum::SuperEnum>::Value);
+Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::WindowFlags>::Value);
+Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::Orientation>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<int>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<QObject>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<QObject*>::Value);
+Q_STATIC_ASSERT(!QtPrivate::IsQEnumHelper<void>::Value);
+
QTEST_MAIN(tst_QMetaEnum)
#include "tst_qmetaenum.moc"
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index b3333c6d68..9cdb1f47f8 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -142,8 +142,14 @@ public:
class CustomGadget {
Q_GADGET
};
+class CustomGadget_NonDefaultConstructible {
+ Q_GADGET
+public:
+ CustomGadget_NonDefaultConstructible(int) {};
+};
class CustomNonQObject {};
+class GadgetDerived : public CustomGadget {};
void tst_QMetaType::defined()
{
@@ -153,11 +159,12 @@ void tst_QMetaType::defined()
QCOMPARE(int(QMetaTypeId2<int*>::Defined), 0);
QCOMPARE(int(QMetaTypeId2<CustomQObject::CustomQEnum>::Defined), 1);
QCOMPARE(int(QMetaTypeId2<CustomGadget>::Defined), 1);
+ QVERIFY(!QMetaTypeId2<GadgetDerived>::Defined);
QVERIFY(int(QMetaTypeId2<CustomQObject*>::Defined));
QVERIFY(!QMetaTypeId2<CustomQObject>::Defined);
QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined);
QVERIFY(!QMetaTypeId2<CustomNonQObject*>::Defined);
- QVERIFY(!QMetaTypeId2<CustomGadget*>::Defined);
+ QVERIFY(!QMetaTypeId2<CustomGadget_NonDefaultConstructible>::Defined);
}
struct Bar
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 263cc5a07a..3ec84b5198 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -128,6 +128,7 @@ private slots:
void connectWithReference();
void connectManyArguments();
void connectForwardDeclare();
+ void connectNoDefaultConstructorArg();
void returnValue_data();
void returnValue();
void returnValue2_data();
@@ -5227,6 +5228,29 @@ void tst_QObject::connectForwardDeclare()
QVERIFY(connect(&ob, &ForwardDeclareArguments::mySignal, &ob, &ForwardDeclareArguments::mySlot, Qt::QueuedConnection));
}
+class NoDefaultConstructor
+{
+ Q_GADGET
+public:
+ NoDefaultConstructor(int) {}
+};
+
+class NoDefaultContructorArguments : public QObject
+{
+ Q_OBJECT
+signals:
+ void mySignal(const NoDefaultConstructor&);
+public slots:
+ void mySlot(const NoDefaultConstructor&) {}
+};
+
+void tst_QObject::connectNoDefaultConstructorArg()
+{
+ NoDefaultContructorArguments ob;
+ // it should compile
+ QVERIFY(connect(&ob, &NoDefaultContructorArguments::mySignal, &ob, &NoDefaultContructorArguments::mySlot, Qt::QueuedConnection));
+}
+
class ReturnValue : public QObject {
friend class tst_QObject;
Q_OBJECT
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 96d0a62f6b..1292c3b98f 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -247,6 +247,9 @@ private slots:
void qtbug_44963();
void qtbug_44783();
+ void internalTransition();
+ void conflictingTransition();
+ void qtbug_46059();
};
class TestState : public QState
@@ -256,10 +259,12 @@ public:
Entry,
Exit
};
- TestState(QState *parent)
- : QState(parent) {}
- TestState(ChildMode mode)
- : QState(mode) {}
+ TestState(QState *parent, const QString &objectName = QString())
+ : QState(parent)
+ { setObjectName(objectName); }
+ TestState(ChildMode mode, const QString &objectName = QString())
+ : QState(mode)
+ { setObjectName(objectName); }
QList<QPair<int, Event> > events;
protected:
virtual void onEntry(QEvent *) {
@@ -273,9 +278,9 @@ protected:
class TestTransition : public QAbstractTransition
{
public:
- TestTransition(QAbstractState *target)
+ TestTransition(QAbstractState *target, const QString &objectName = QString())
: QAbstractTransition()
- { setTargetState(target); }
+ { setTargetState(target); setObjectName(objectName); }
QList<int> triggers;
protected:
virtual bool eventTest(QEvent *) {
@@ -1352,15 +1357,16 @@ void tst_QStateMachine::stateEntryAndExit()
{
QStateMachine machine;
- TestState *s1 = new TestState(&machine);
- TestState *s11 = new TestState(s1);
- TestState *s12 = new TestState(s1);
- TestState *s2 = new TestState(&machine);
+ TestState *s1 = new TestState(&machine, "s1");
+ TestState *s11 = new TestState(s1, "s11");
+ TestState *s12 = new TestState(s1, "s12");
+ TestState *s2 = new TestState(&machine, "s2");
QFinalState *s3 = new QFinalState(&machine);
+ s3->setObjectName("s3");
s1->setInitialState(s11);
- TestTransition *t1 = new TestTransition(s12);
+ TestTransition *t1 = new TestTransition(s12, "t1");
s11->addTransition(t1);
- TestTransition *t2 = new TestTransition(s2);
+ TestTransition *t2 = new TestTransition(s2, "t2");
s12->addTransition(t2);
s2->addTransition(s3);
@@ -6335,5 +6341,149 @@ void tst_QStateMachine::qtbug_44783()
QVERIFY(machine.isRunning());
}
+void tst_QStateMachine::internalTransition()
+{
+ SignalEmitter emitter;
+
+ QStateMachine machine;
+ QState *s = new QState(&machine);
+ QState *s1 = new QState(s);
+ QState *s11 = new QState(s1);
+
+ DEFINE_ACTIVE_SPY(s);
+ DEFINE_ACTIVE_SPY(s1);
+ DEFINE_ACTIVE_SPY(s11);
+
+ machine.setInitialState(s);
+ s->setInitialState(s1);
+ s1->setInitialState(s11);
+ QSignalTransition *t = s1->addTransition(&emitter, SIGNAL(signalWithNoArg()), s11);
+ t->setObjectName("s1->s11");
+ t->setTransitionType(QAbstractTransition::InternalTransition);
+
+ s->setObjectName("s");
+ s1->setObjectName("s1");
+ s11->setObjectName("s11");
+
+ machine.start();
+
+ QTRY_COMPARE(machine.configuration().contains(s), true);
+ QTRY_COMPARE(machine.configuration().contains(s1), true);
+ QTRY_COMPARE(machine.configuration().contains(s11), true);
+ TEST_ACTIVE_CHANGED(s, 1);
+ TEST_ACTIVE_CHANGED(s1, 1);
+ TEST_ACTIVE_CHANGED(s11, 1);
+
+ emitter.emitSignalWithNoArg();
+
+ QTRY_COMPARE(machine.configuration().contains(s), true);
+ QTRY_COMPARE(machine.configuration().contains(s1), true);
+ QTRY_COMPARE(machine.configuration().contains(s11), true);
+ TEST_ACTIVE_CHANGED(s11, 3);
+ TEST_ACTIVE_CHANGED(s1, 1); // external transitions will return 3, internal transitions should return 1.
+ TEST_ACTIVE_CHANGED(s, 1);
+}
+
+void tst_QStateMachine::conflictingTransition()
+{
+ SignalEmitter emitter;
+
+ QStateMachine machine;
+ QState b(QState::ParallelStates, &machine);
+ QState c(&b);
+ QState d(QState::ParallelStates, &b);
+ QState e(&d);
+ QState e1(&e);
+ QState e2(&e);
+ QState f(&d);
+ QState f1(&f);
+ QState f2(&f);
+ QState a1(&machine);
+
+ machine.setInitialState(&b);
+ e.setInitialState(&e1);
+ f.setInitialState(&f1);
+ c.addTransition(&emitter, SIGNAL(signalWithNoArg()), &a1)->setObjectName("c->a1");
+ e1.addTransition(&emitter, SIGNAL(signalWithNoArg()), &e2)->setObjectName("e1->e2");
+ f1.addTransition(&emitter, SIGNAL(signalWithNoArg()), &f2)->setObjectName("f1->f2");
+
+ b.setObjectName("b");
+ c.setObjectName("c");
+ d.setObjectName("d");
+ e.setObjectName("e");
+ e1.setObjectName("e1");
+ e2.setObjectName("e2");
+ f.setObjectName("f");
+ f1.setObjectName("f1");
+ f2.setObjectName("f2");
+ a1.setObjectName("a1");
+
+ machine.start();
+
+ QTRY_COMPARE(machine.configuration().contains(&b), true);
+ QTRY_COMPARE(machine.configuration().contains(&c), true);
+ QTRY_COMPARE(machine.configuration().contains(&d), true);
+ QTRY_COMPARE(machine.configuration().contains(&e), true);
+ QTRY_COMPARE(machine.configuration().contains(&e1), true);
+ QTRY_COMPARE(machine.configuration().contains(&e2), false);
+ QTRY_COMPARE(machine.configuration().contains(&f), true);
+ QTRY_COMPARE(machine.configuration().contains(&f1), true);
+ QTRY_COMPARE(machine.configuration().contains(&f2), false);
+ QTRY_COMPARE(machine.configuration().contains(&a1), false);
+
+ emitter.emitSignalWithNoArg();
+
+ QTRY_COMPARE(machine.configuration().contains(&b), true);
+ QTRY_COMPARE(machine.configuration().contains(&c), true);
+ QTRY_COMPARE(machine.configuration().contains(&d), true);
+ QTRY_COMPARE(machine.configuration().contains(&e), true);
+ QTRY_COMPARE(machine.configuration().contains(&e1), false);
+ QTRY_COMPARE(machine.configuration().contains(&e2), true);
+ QTRY_COMPARE(machine.configuration().contains(&f), true);
+ QTRY_COMPARE(machine.configuration().contains(&f1), false);
+ QTRY_COMPARE(machine.configuration().contains(&f2), true);
+ QTRY_COMPARE(machine.configuration().contains(&a1), false);
+
+ QVERIFY(machine.isRunning());
+}
+
+void tst_QStateMachine::qtbug_46059()
+{
+ QStateMachine machine;
+ QState a(&machine);
+ QState b(&a);
+ QState c(&a);
+ QState success(&a);
+ QState failure(&machine);
+
+ machine.setInitialState(&a);
+ a.setInitialState(&b);
+ b.addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), &c));
+ c.addTransition(new EventTransition(QEvent::Type(QEvent::User + 2), &success));
+ b.addTransition(new EventTransition(QEvent::Type(QEvent::User + 2), &failure));
+
+ machine.start();
+ QCoreApplication::processEvents();
+
+ QTRY_COMPARE(machine.configuration().contains(&a), true);
+ QTRY_COMPARE(machine.configuration().contains(&b), true);
+ QTRY_COMPARE(machine.configuration().contains(&c), false);
+ QTRY_COMPARE(machine.configuration().contains(&failure), false);
+ QTRY_COMPARE(machine.configuration().contains(&success), false);
+
+ machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 0)), QStateMachine::HighPriority);
+ machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)), QStateMachine::HighPriority);
+ machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 2)), QStateMachine::NormalPriority);
+ QCoreApplication::processEvents();
+
+ QTRY_COMPARE(machine.configuration().contains(&a), true);
+ QTRY_COMPARE(machine.configuration().contains(&b), false);
+ QTRY_COMPARE(machine.configuration().contains(&c), false);
+ QTRY_COMPARE(machine.configuration().contains(&failure), false);
+ QTRY_COMPARE(machine.configuration().contains(&success), true);
+
+ QVERIFY(machine.isRunning());
+}
+
QTEST_MAIN(tst_QStateMachine)
#include "tst_qstatemachine.moc"
diff --git a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
index 01855a730e..76687bd478 100644
--- a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
+++ b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
@@ -43,6 +43,8 @@ class tst_QContiguousCache : public QObject
{
Q_OBJECT
private slots:
+ void assignment();
+
void empty();
void swap();
@@ -64,6 +66,16 @@ private slots:
QTEST_MAIN(tst_QContiguousCache)
+void tst_QContiguousCache::assignment()
+{
+ // compile-only test: QTBUG-45783
+ QContiguousCache<int> cc1, cc2;
+ // copy:
+ cc1 = cc2;
+ // move:
+ cc1 = qMove(cc2);
+}
+
void tst_QContiguousCache::empty()
{
QContiguousCache<int> c(10);
diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
index 11c292db91..a07247316e 100644
--- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
+++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
@@ -39,10 +39,7 @@
#include <QtDBus/private/qdbusutil_p.h>
#include <QtDBus/private/qdbusconnection_p.h>
-
-#define QT_LINKED_LIBDBUS
-#include <QtDBus/private/qdbusutil_p.h>
-#include <QtDBus/private/qdbusconnection_p.h>
+#include <QtDBus/private/qdbus_symbols_p.h>
static const char serviceName[] = "org.qtproject.autotests.qpong";
static const char objectPath[] = "/org/qtproject/qpong";
@@ -85,10 +82,8 @@ private slots:
void sendCallErrors_data();
void sendCallErrors();
-#ifdef DBUS_TYPE_UNIX_FD
void receiveUnknownType_data();
void receiveUnknownType();
-#endif
void demarshallPrimitives_data();
void demarshallPrimitives();
@@ -1017,7 +1012,6 @@ void tst_QDBusMarshall::sendCallErrors()
QCOMPARE(reply.errorMessage(), errorMsg);
}
-#ifdef DBUS_TYPE_UNIX_FD
// If DBUS_TYPE_UNIX_FD is not defined, it means the current system's D-Bus library is too old for this test
void tst_QDBusMarshall::receiveUnknownType_data()
{
@@ -1075,6 +1069,27 @@ public:
}
};
+// mostly the same as qdbusintegrator.cpp:connectionCapabilies
+static bool canSendUnixFd(DBusConnection *connection)
+{
+ typedef dbus_bool_t (*can_send_type_t)(DBusConnection *, int);
+ static can_send_type_t can_send_type = 0;
+
+#if defined(QT_LINKED_LIBDBUS)
+# if DBUS_VERSION-0 >= 0x010400
+ can_send_type = dbus_connection_can_send_type;
+# endif
+#else
+ // run-time check if the next functions are available
+ can_send_type = (can_send_type_t)qdbus_resolve_conditionally("dbus_connection_can_send_type");
+#endif
+
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+#endif
+ return can_send_type && can_send_type(connection, DBUS_TYPE_UNIX_FD);
+}
+
void tst_QDBusMarshall::receiveUnknownType()
{
QDBusConnection con = QDBusConnection::sessionBus();
@@ -1088,7 +1103,8 @@ void tst_QDBusMarshall::receiveUnknownType()
QVERIFY2(rawcon.data(), error.name);
// check if this bus supports passing file descriptors
- if (!q_dbus_connection_can_send_type(rawcon.data(), DBUS_TYPE_UNIX_FD))
+
+ if (!canSendUnixFd(rawcon.data()))
QSKIP("Your session bus does not allow sending Unix file descriptors");
// make sure this QDBusConnection won't handle Unix file descriptors
@@ -1184,7 +1200,6 @@ void tst_QDBusMarshall::receiveUnknownType()
QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId);
}
}
-#endif
void tst_QDBusMarshall::demarshallPrimitives_data()
{
diff --git a/tests/auto/dbus/qdbustype/tst_qdbustype.cpp b/tests/auto/dbus/qdbustype/tst_qdbustype.cpp
index ced73dbf3b..63444b61ad 100644
--- a/tests/auto/dbus/qdbustype/tst_qdbustype.cpp
+++ b/tests/auto/dbus/qdbustype/tst_qdbustype.cpp
@@ -87,8 +87,19 @@ static void addFixedTypes()
QTest::newRow("int64") << DBUS_TYPE_INT64_AS_STRING << true << true;
QTest::newRow("uint64") << DBUS_TYPE_UINT64_AS_STRING << true << true;
QTest::newRow("double") << DBUS_TYPE_DOUBLE_AS_STRING << true << true;
+
#ifdef DBUS_TYPE_UNIX_FD_AS_STRING
- QTest::newRow("unixfd") << DBUS_TYPE_UNIX_FD_AS_STRING << true << true;
+# ifndef QT_LINKED_LIBDBUS
+ // We have got the macro from dbus_minimal_p.h, so we need to check if
+ // the library recognizes this as valid type first.
+ // The following function was added for Unix FD support, so if it is
+ // present, so is support for Unix FDs.
+ bool supportsUnixFds = qdbus_resolve_conditionally("dbus_connection_can_send_type");
+# else
+ bool supportsUnixFds = true;
+# endif
+ if (supportsUnixFds)
+ QTest::newRow("unixfd") << DBUS_TYPE_UNIX_FD_AS_STRING << true << true;
#endif
}
diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_QTBUG-45865.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_QTBUG-45865.jpg
new file mode 100644
index 0000000000..97deae3e25
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/jpeg_exif_QTBUG-45865.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 2931185c8b..da29a57f98 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -184,6 +184,8 @@ private slots:
void exifOrientation_data();
void exifOrientation();
+ void exif_QTBUG45865();
+
void cleanupFunctions();
void devicePixelRatio();
@@ -2816,31 +2818,56 @@ void tst_QImage::invertPixelsRGB()
void tst_QImage::exifOrientation_data()
{
QTest::addColumn<QString>("fileName");
- QTest::newRow("Orientation 1, Intel format") << m_prefix + "jpeg_exif_orientation_value_1.jpg";
- QTest::newRow("Orientation 2, Intel format") << m_prefix + "jpeg_exif_orientation_value_2.jpg";
- QTest::newRow("Orientation 3, Intel format") << m_prefix + "jpeg_exif_orientation_value_3.jpg";
- QTest::newRow("Orientation 4, Intel format") << m_prefix + "jpeg_exif_orientation_value_4.jpg";
- QTest::newRow("Orientation 5, Intel format") << m_prefix + "jpeg_exif_orientation_value_5.jpg";
- QTest::newRow("Orientation 6, Intel format") << m_prefix + "jpeg_exif_orientation_value_6.jpg";
- QTest::newRow("Orientation 6, Motorola format") << m_prefix + "jpeg_exif_orientation_value_6_motorola.jpg";
- QTest::newRow("Orientation 7, Intel format") << m_prefix + "jpeg_exif_orientation_value_7.jpg";
- QTest::newRow("Orientation 8, Intel format") << m_prefix + "jpeg_exif_orientation_value_8.jpg";
-}
+ QTest::addColumn<int>("orientation");
+ QTest::newRow("Orientation 1, Intel format") << m_prefix + "jpeg_exif_orientation_value_1.jpg" << (int)QImageIOHandler::TransformationNone;
+ QTest::newRow("Orientation 2, Intel format") << m_prefix + "jpeg_exif_orientation_value_2.jpg" << (int)QImageIOHandler::TransformationMirror;
+ QTest::newRow("Orientation 3, Intel format") << m_prefix + "jpeg_exif_orientation_value_3.jpg" << (int)QImageIOHandler::TransformationRotate180;
+ QTest::newRow("Orientation 4, Intel format") << m_prefix + "jpeg_exif_orientation_value_4.jpg" << (int)QImageIOHandler::TransformationFlip;
+ QTest::newRow("Orientation 5, Intel format") << m_prefix + "jpeg_exif_orientation_value_5.jpg" << (int)QImageIOHandler::TransformationFlipAndRotate90;
+ QTest::newRow("Orientation 6, Intel format") << m_prefix + "jpeg_exif_orientation_value_6.jpg" << (int)QImageIOHandler::TransformationRotate90;
+ QTest::newRow("Orientation 6, Motorola format") << m_prefix + "jpeg_exif_orientation_value_6_motorola.jpg" << (int)QImageIOHandler::TransformationRotate90;
+ QTest::newRow("Orientation 7, Intel format") << m_prefix + "jpeg_exif_orientation_value_7.jpg" << (int)QImageIOHandler::TransformationMirrorAndRotate90;
+ QTest::newRow("Orientation 8, Intel format") << m_prefix + "jpeg_exif_orientation_value_8.jpg" << (int)QImageIOHandler::TransformationRotate270;
+}
+
+QT_BEGIN_NAMESPACE
+extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient);
+QT_END_NAMESPACE
+QT_USE_NAMESPACE
void tst_QImage::exifOrientation()
{
QFETCH(QString, fileName);
+ QFETCH(int, orientation);
- QImage img;
+ QImageReader imageReader(fileName);
+ imageReader.setAutoTransform(true);
+ QCOMPARE(imageReader.transformation(), orientation);
+ QImage img = imageReader.read();
QRgb px;
-
- QVERIFY(img.load(fileName));
+ QVERIFY(!img.isNull());
px = img.pixel(0, 0);
QVERIFY(qRed(px) > 250 && qGreen(px) < 5 && qBlue(px) < 5);
px = img.pixel(img.width() - 1, 0);
QVERIFY(qRed(px) < 5 && qGreen(px) < 5 && qBlue(px) > 250);
+
+ QImageReader imageReader2(fileName);
+ QCOMPARE(imageReader2.autoTransform(), false);
+ QCOMPARE(imageReader2.transformation(), orientation);
+ QImage img2 = imageReader2.read();
+ qt_imageTransform(img2, imageReader2.transformation());
+ QCOMPARE(img, img2);
+}
+
+void tst_QImage::exif_QTBUG45865()
+{
+ QFile file(m_prefix + "jpeg_exif_QTBUG-45865.jpg");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QByteArray byteArray = file.readAll();
+ QImage image = QImage::fromData(byteArray);
+ QCOMPARE(image.size(), QSize(5, 8));
}
static void cleanupFunction(void* info)
diff --git a/tests/auto/gui/kernel/qtouchevent/BLACKLIST b/tests/auto/gui/kernel/qtouchevent/BLACKLIST
new file mode 100644
index 0000000000..8e78d7e41f
--- /dev/null
+++ b/tests/auto/gui/kernel/qtouchevent/BLACKLIST
@@ -0,0 +1,6 @@
+[basicRawEventTranslation]
+linux
+[multiPointRawEventTranslationOnTouchScreen]
+linux
+[multiPointRawEventTranslationOnTouchPad]
+linux
diff --git a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
index 7136611165..b1e3c10724 100644
--- a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
+++ b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
@@ -1,3 +1,5 @@
+CONFIG += testcase
+osx: CONFIG += insignificant_test # QTBUG-46266, crashes
SOURCES=tst_qtouchevent.cpp
TARGET=tst_qtouchevent
QT += testlib widgets gui-private
diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
index fe11f39242..aa1f573aa9 100644
--- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
+++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
@@ -31,11 +31,16 @@
**
****************************************************************************/
-#include <QtGui>
-#include <QtWidgets>
+#include <QtWidgets/QDesktopWidget>
+#include <QtWidgets/QGraphicsItem>
+#include <QtWidgets/QGraphicsScene>
+#include <QtWidgets/QGraphicsView>
+#include <QtWidgets/QGraphicsWidget>
+#include <QtWidgets/QWidget>
#include <QtTest>
#include <qpa/qwindowsysteminterface.h>
+// FIXME: Use static functions of QWindowSystemInterface introduced with HighDPI scaling in 5.6 instead.
static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt)
{
QWindowSystemInterface::TouchPoint p;
@@ -72,8 +77,7 @@ public:
ulong timestamp;
QTouchDevice *deviceFromEvent;
- tst_QTouchEventWidget()
- : QWidget()
+ explicit tst_QTouchEventWidget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
{
reset();
}
@@ -88,7 +92,7 @@ public:
deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
}
- bool event(QEvent *event)
+ bool event(QEvent *event) Q_DECL_OVERRIDE
{
switch (event->type()) {
case QEvent::TouchBegin:
@@ -142,8 +146,8 @@ public:
bool deleteInTouchBegin, deleteInTouchUpdate, deleteInTouchEnd;
tst_QTouchEventGraphicsItem **weakpointer;
- tst_QTouchEventGraphicsItem()
- : QGraphicsItem(), weakpointer(0)
+ explicit tst_QTouchEventGraphicsItem(QGraphicsItem *parent = Q_NULLPTR)
+ : QGraphicsItem(parent), weakpointer(0)
{
reset();
}
@@ -165,10 +169,10 @@ public:
deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false;
}
- QRectF boundingRect() const { return QRectF(0, 0, 10, 10); }
- void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) { }
+ QRectF boundingRect() const Q_DECL_OVERRIDE { return QRectF(0, 0, 10, 10); }
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) Q_DECL_OVERRIDE { }
- bool sceneEvent(QEvent *event)
+ bool sceneEvent(QEvent *event) Q_DECL_OVERRIDE
{
switch (event->type()) {
case QEvent::TouchBegin:
@@ -214,9 +218,9 @@ class tst_QTouchEvent : public QObject
Q_OBJECT
public:
tst_QTouchEvent();
- ~tst_QTouchEvent() { }
private slots:
+ void cleanup();
void touchDisabledByDefault();
void touchEventAcceptedByDefault();
void touchBeginPropagatesWhenIgnored();
@@ -236,15 +240,18 @@ private:
QTouchDevice *touchPadDevice;
};
-tst_QTouchEvent::tst_QTouchEvent()
+tst_QTouchEvent::tst_QTouchEvent() : touchScreenDevice(new QTouchDevice), touchPadDevice(new QTouchDevice)
{
- touchScreenDevice = new QTouchDevice;
- touchPadDevice = new QTouchDevice;
touchPadDevice->setType(QTouchDevice::TouchPad);
QWindowSystemInterface::registerTouchDevice(touchScreenDevice);
QWindowSystemInterface::registerTouchDevice(touchPadDevice);
}
+void tst_QTouchEvent::cleanup()
+{
+ QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
+}
+
void tst_QTouchEvent::touchDisabledByDefault()
{
// QWidget
@@ -261,8 +268,7 @@ void tst_QTouchEvent::touchDisabledByDefault()
Qt::NoModifier,
Qt::TouchPointPressed,
touchPoints);
- bool res = QApplication::sendEvent(&widget, &touchEvent);
- QVERIFY(!res);
+ QVERIFY(!QApplication::sendEvent(&widget, &touchEvent));
QVERIFY(!touchEvent.isAccepted());
}
@@ -290,8 +296,7 @@ void tst_QTouchEvent::touchDisabledByDefault()
Qt::NoModifier,
Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << touchPoint));
- bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
- QVERIFY(!res);
+ QVERIFY(!QApplication::sendEvent(view.viewport(), &touchEvent));
QVERIFY(!touchEvent.isAccepted());
QVERIFY(!item.seenTouchBegin);
}
@@ -299,7 +304,7 @@ void tst_QTouchEvent::touchDisabledByDefault()
void tst_QTouchEvent::touchEventAcceptedByDefault()
{
- if (qApp->platformName().toLower() == QLatin1String("wayland"))
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
// QWidget
@@ -317,16 +322,14 @@ void tst_QTouchEvent::touchEventAcceptedByDefault()
Qt::NoModifier,
Qt::TouchPointPressed,
touchPoints);
- bool res = QApplication::sendEvent(&widget, &touchEvent);
- QVERIFY(res);
- QVERIFY(touchEvent.isAccepted());
+ QVERIFY(QApplication::sendEvent(&widget, &touchEvent));
+ QVERIFY(!touchEvent.isAccepted()); // Qt 5.X ignores touch events.
// tst_QTouchEventWidget does handle, sending succeeds
tst_QTouchEventWidget touchWidget;
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
touchEvent.ignore();
- res = QApplication::sendEvent(&touchWidget, &touchEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(&touchWidget, &touchEvent));
QVERIFY(touchEvent.isAccepted());
}
@@ -355,8 +358,7 @@ void tst_QTouchEvent::touchEventAcceptedByDefault()
Qt::NoModifier,
Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << touchPoint));
- bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent));
QVERIFY(touchEvent.isAccepted());
QVERIFY(item.seenTouchBegin);
}
@@ -383,8 +385,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
Qt::NoModifier,
Qt::TouchPointPressed,
touchPoints);
- bool res = QApplication::sendEvent(&grandchild, &touchEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent));
QVERIFY(touchEvent.isAccepted());
QVERIFY(grandchild.seenTouchBegin);
QVERIFY(child.seenTouchBegin);
@@ -398,8 +399,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
grandchild.setAttribute(Qt::WA_AcceptTouchEvents, false);
touchEvent.ignore();
- res = QApplication::sendEvent(&grandchild, &touchEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent));
QVERIFY(touchEvent.isAccepted());
QVERIFY(!grandchild.seenTouchBegin);
QVERIFY(child.seenTouchBegin);
@@ -435,8 +435,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
Qt::NoModifier,
Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << touchPoint));
- bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent));
QVERIFY(touchEvent.isAccepted());
QVERIFY(grandchild.seenTouchBegin);
QVERIFY(child.seenTouchBegin);
@@ -471,8 +470,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored()
Qt::NoModifier,
Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << touchPoint));
- bool res = QApplication::sendEvent(view.viewport(), &touchEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent));
QVERIFY(touchEvent.isAccepted());
QVERIFY(!grandchild.seenTouchBegin);
QVERIFY(child.seenTouchBegin);
@@ -499,8 +497,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
Qt::NoModifier,
Qt::TouchPointPressed,
touchPoints);
- bool res = QApplication::sendEvent(&child, &touchBeginEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(&child, &touchBeginEvent));
QVERIFY(touchBeginEvent.isAccepted());
QVERIFY(child.seenTouchBegin);
QVERIFY(!window.seenTouchBegin);
@@ -511,8 +508,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
Qt::NoModifier,
Qt::TouchPointMoved,
touchPoints);
- res = QApplication::sendEvent(&child, &touchUpdateEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(&child, &touchUpdateEvent));
QVERIFY(!touchUpdateEvent.isAccepted());
QVERIFY(child.seenTouchUpdate);
QVERIFY(!window.seenTouchUpdate);
@@ -523,8 +519,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
Qt::NoModifier,
Qt::TouchPointReleased,
touchPoints);
- res = QApplication::sendEvent(&child, &touchEndEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(&child, &touchEndEvent));
QVERIFY(!touchEndEvent.isAccepted());
QVERIFY(child.seenTouchEnd);
QVERIFY(!window.seenTouchEnd);
@@ -558,8 +553,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
Qt::NoModifier,
Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << touchPoint));
- bool res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
QVERIFY(touchBeginEvent.isAccepted());
QVERIFY(child.seenTouchBegin);
QVERIFY(!root.seenTouchBegin);
@@ -571,8 +565,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
Qt::NoModifier,
Qt::TouchPointMoved,
(QList<QTouchEvent::TouchPoint>() << touchPoint));
- res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
// the scene accepts the event, since it found an item to send the event to
QVERIFY(!touchUpdateEvent.isAccepted());
QVERIFY(child.seenTouchUpdate);
@@ -585,8 +578,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate()
Qt::NoModifier,
Qt::TouchPointReleased,
(QList<QTouchEvent::TouchPoint>() << touchPoint));
- res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
- QVERIFY(res);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
// the scene accepts the event, since it found an item to send the event to
QVERIFY(!touchEndEvent.isAccepted());
QVERIFY(child.seenTouchEnd);
@@ -601,17 +593,20 @@ QPointF normalized(const QPointF &pos, const QRectF &rect)
void tst_QTouchEvent::basicRawEventTranslation()
{
- if (qApp->platformName().toLower() == QLatin1String("wayland"))
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
tst_QTouchEventWidget touchWidget;
+ touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
touchWidget.setGeometry(100, 100, 400, 300);
+ touchWidget.show();
+ QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
QPointF pos = touchWidget.rect().center();
QPointF screenPos = touchWidget.mapToGlobal(pos.toPoint());
QPointF delta(10, 10);
- QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+ QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
QTouchEvent::TouchPoint rawTouchPoint;
rawTouchPoint.setId(0);
@@ -726,24 +721,24 @@ void tst_QTouchEvent::basicRawEventTranslation()
void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
{
- if (qApp->platformName().toLower() == QLatin1String("wayland"))
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
tst_QTouchEventWidget touchWidget;
+ touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
touchWidget.setGeometry(100, 100, 400, 300);
- tst_QTouchEventWidget leftWidget;
- leftWidget.setParent(&touchWidget);
+ tst_QTouchEventWidget leftWidget(&touchWidget);
leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
leftWidget.setGeometry(0, 100, 100, 100);
- leftWidget.show();
- tst_QTouchEventWidget rightWidget;
- rightWidget.setParent(&touchWidget);
+ tst_QTouchEventWidget rightWidget(&touchWidget);
rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
rightWidget.setGeometry(300, 100, 100, 100);
- rightWidget.show();
+
+ touchWidget.show();
+ QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
QPointF leftPos = leftWidget.rect().center();
QPointF rightPos = rightWidget.rect().center();
@@ -751,8 +746,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
- QPointF delta(10, 10);
- QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+ QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
QList<QTouchEvent::TouchPoint> rawTouchPoints;
rawTouchPoints.append(QTouchEvent::TouchPoint(0));
@@ -956,24 +950,25 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen()
void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
{
- if (qApp->platformName().toLower() == QLatin1String("wayland"))
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
tst_QTouchEventWidget touchWidget;
+ touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
touchWidget.setGeometry(100, 100, 400, 300);
- tst_QTouchEventWidget leftWidget;
- leftWidget.setParent(&touchWidget);
+ tst_QTouchEventWidget leftWidget(&touchWidget);
leftWidget.setAttribute(Qt::WA_AcceptTouchEvents);
leftWidget.setGeometry(0, 100, 100, 100);
- leftWidget.show();
+ leftWidget.acceptTouchBegin =true;
- tst_QTouchEventWidget rightWidget;
- rightWidget.setParent(&touchWidget);
+ tst_QTouchEventWidget rightWidget(&touchWidget);
rightWidget.setAttribute(Qt::WA_AcceptTouchEvents);
rightWidget.setGeometry(300, 100, 100, 100);
- rightWidget.show();
+
+ touchWidget.show();
+ QVERIFY(QTest::qWaitForWindowActive(&touchWidget));
QPointF leftPos = leftWidget.rect().center();
QPointF rightPos = rightWidget.rect().center();
@@ -981,8 +976,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint());
QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint());
QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint());
- QPointF delta(10, 10);
- QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
+ QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
QList<QTouchEvent::TouchPoint> rawTouchPoints;
rawTouchPoints.append(QTouchEvent::TouchPoint(0));
@@ -1003,7 +997,8 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
QVERIFY(!touchWidget.seenTouchBegin);
QVERIFY(!touchWidget.seenTouchUpdate);
QVERIFY(!touchWidget.seenTouchEnd);
- QVERIFY(leftWidget.seenTouchBegin);
+ QEXPECT_FAIL("", "QTBUG-46266, fails in Qt 5", Abort);
+ QVERIFY(!leftWidget.seenTouchBegin);
QVERIFY(!leftWidget.seenTouchUpdate);
QVERIFY(!leftWidget.seenTouchEnd);
QVERIFY(!rightWidget.seenTouchBegin);
@@ -1186,19 +1181,15 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
void tst_QTouchEvent::deleteInEventHandler()
{
- if (qApp->platformName().toLower() == QLatin1String("wayland"))
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
// QWidget
{
QWidget window;
- tst_QTouchEventWidget *child1, *child2, *child3;
- child1 = new tst_QTouchEventWidget;
- child2 = new tst_QTouchEventWidget;
- child3 = new tst_QTouchEventWidget;
- child1->setParent(&window);
- child2->setParent(&window);
- child3->setParent(&window);
+ QPointer<tst_QTouchEventWidget> child1 = new tst_QTouchEventWidget(&window);
+ QPointer<tst_QTouchEventWidget> child2 = new tst_QTouchEventWidget(&window);
+ QPointer<tst_QTouchEventWidget> child3 = new tst_QTouchEventWidget(&window);
child1->setAttribute(Qt::WA_AcceptTouchEvents);
child2->setAttribute(Qt::WA_AcceptTouchEvents);
child3->setAttribute(Qt::WA_AcceptTouchEvents);
@@ -1223,47 +1214,43 @@ void tst_QTouchEvent::deleteInEventHandler()
Qt::NoModifier,
Qt::TouchPointReleased,
touchPoints);
- QPointer<QWidget> p;
- bool res;
-
touchBeginEvent.ignore();
- p = child1;
- res = QApplication::sendEvent(child1, &touchBeginEvent);
+ QVERIFY(QApplication::sendEvent(child1, &touchBeginEvent));
// event is handled, but widget should be deleted
- QVERIFY(res && touchBeginEvent.isAccepted() && p.isNull());
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(child1.isNull());
touchBeginEvent.ignore();
- p = child2;
- res = QApplication::sendEvent(child2, &touchBeginEvent);
- QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
+ QVERIFY(QApplication::sendEvent(child2, &touchBeginEvent));
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(!child2.isNull());
touchUpdateEvent.ignore();
- res = QApplication::sendEvent(child2, &touchUpdateEvent);
- QVERIFY(res && touchUpdateEvent.isAccepted() && p.isNull());
+ QVERIFY(QApplication::sendEvent(child2, &touchUpdateEvent));
+ QVERIFY(touchUpdateEvent.isAccepted());
+ QVERIFY(child2.isNull());
touchBeginEvent.ignore();
- p = child3;
- res = QApplication::sendEvent(child3, &touchBeginEvent);
- QVERIFY(res && touchBeginEvent.isAccepted() && !p.isNull());
+ QVERIFY(QApplication::sendEvent(child3, &touchBeginEvent));
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(!child3.isNull());
touchUpdateEvent.ignore();
- res = QApplication::sendEvent(child3, &touchUpdateEvent);
- QVERIFY(res && touchUpdateEvent.isAccepted() && !p.isNull());
+ QVERIFY(QApplication::sendEvent(child3, &touchUpdateEvent));
+ QVERIFY(touchUpdateEvent.isAccepted());
+ QVERIFY(!child3.isNull());
touchEndEvent.ignore();
- res = QApplication::sendEvent(child3, &touchEndEvent);
- QVERIFY(res && touchEndEvent.isAccepted() && p.isNull());
+ QVERIFY(QApplication::sendEvent(child3, &touchEndEvent));
+ QVERIFY(touchEndEvent.isAccepted());
+ QVERIFY(child3.isNull());
}
// QGraphicsView
{
QGraphicsScene scene;
QGraphicsView view(&scene);
- tst_QTouchEventGraphicsItem *root, *child1, *child2, *child3;
- root = new tst_QTouchEventGraphicsItem;
- child1 = new tst_QTouchEventGraphicsItem;
- child2 = new tst_QTouchEventGraphicsItem;
- child3 = new tst_QTouchEventGraphicsItem;
- child1->setParentItem(root);
- child2->setParentItem(root);
- child3->setParentItem(root);
+ QScopedPointer<tst_QTouchEventGraphicsItem> root(new tst_QTouchEventGraphicsItem);
+ tst_QTouchEventGraphicsItem *child1 = new tst_QTouchEventGraphicsItem(root.data());
+ tst_QTouchEventGraphicsItem *child2 = new tst_QTouchEventGraphicsItem(root.data());
+ tst_QTouchEventGraphicsItem *child3 = new tst_QTouchEventGraphicsItem(root.data());
child1->setZValue(1.);
child2->setZValue(0.);
child3->setZValue(-1.);
@@ -1274,7 +1261,7 @@ void tst_QTouchEvent::deleteInEventHandler()
child2->deleteInTouchUpdate = true;
child3->deleteInTouchEnd = true;
- scene.addItem(root);
+ scene.addItem(root.data());
view.resize(200, 200);
view.fitInView(scene.sceneRect());
@@ -1302,71 +1289,75 @@ void tst_QTouchEvent::deleteInEventHandler()
Qt::NoModifier,
Qt::TouchPointReleased,
touchPoints);
- bool res;
child1->weakpointer = &child1;
touchBeginEvent.ignore();
- res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
- QVERIFY(res && touchBeginEvent.isAccepted() && !child1);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(!child1);
touchUpdateEvent.ignore();
- res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
- QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
+ QVERIFY(!touchUpdateEvent.isAccepted()); // Qt 5.X ignores touch events.
+ QVERIFY(!child1);
touchEndEvent.ignore();
- res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
- QVERIFY(res && touchUpdateEvent.isAccepted() && !child1);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
+ QVERIFY(!touchUpdateEvent.isAccepted());
+ QVERIFY(!child1);
child2->weakpointer = &child2;
touchBeginEvent.ignore();
- res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
- QVERIFY(res && touchBeginEvent.isAccepted() && child2);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(child2);
touchUpdateEvent.ignore();
- res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
- QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
+ QVERIFY(!touchUpdateEvent.isAccepted());
+ QVERIFY(!child2);
touchEndEvent.ignore();
- res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
- QVERIFY(res && !touchUpdateEvent.isAccepted() && !child2);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
+ QVERIFY(!touchUpdateEvent.isAccepted());
+ QVERIFY(!child2);
child3->weakpointer = &child3;
- res = QApplication::sendEvent(view.viewport(), &touchBeginEvent);
- QVERIFY(res && touchBeginEvent.isAccepted() && child3);
- res = QApplication::sendEvent(view.viewport(), &touchUpdateEvent);
- QVERIFY(res && !touchUpdateEvent.isAccepted() && child3);
- res = QApplication::sendEvent(view.viewport(), &touchEndEvent);
- QVERIFY(res && !touchEndEvent.isAccepted() && !child3);
-
- delete root;
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent));
+ QVERIFY(touchBeginEvent.isAccepted());
+ QVERIFY(child3);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchUpdateEvent));
+ QVERIFY(!touchUpdateEvent.isAccepted());
+ QVERIFY(child3);
+ QVERIFY(QApplication::sendEvent(view.viewport(), &touchEndEvent));
+ QVERIFY(!touchEndEvent.isAccepted());
+ QVERIFY(!child3);
}
}
void tst_QTouchEvent::deleteInRawEventTranslation()
{
- if (qApp->platformName().toLower() == QLatin1String("wayland"))
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
tst_QTouchEventWidget touchWidget;
+ touchWidget.setWindowTitle(QTest::currentTestFunction());
touchWidget.setAttribute(Qt::WA_AcceptTouchEvents);
touchWidget.setGeometry(100, 100, 300, 300);
- tst_QTouchEventWidget *leftWidget = new tst_QTouchEventWidget;
- leftWidget->setParent(&touchWidget);
+ QPointer<tst_QTouchEventWidget> leftWidget = new tst_QTouchEventWidget(&touchWidget);
leftWidget->setAttribute(Qt::WA_AcceptTouchEvents);
leftWidget->setGeometry(0, 100, 100, 100);
leftWidget->deleteInTouchBegin = true;
- leftWidget->show();
- tst_QTouchEventWidget *centerWidget = new tst_QTouchEventWidget;
- centerWidget->setParent(&touchWidget);
+ QPointer<tst_QTouchEventWidget> centerWidget = new tst_QTouchEventWidget(&touchWidget);
centerWidget->setAttribute(Qt::WA_AcceptTouchEvents);
centerWidget->setGeometry(100, 100, 100, 100);
centerWidget->deleteInTouchUpdate = true;
- centerWidget->show();
- tst_QTouchEventWidget *rightWidget = new tst_QTouchEventWidget;
- rightWidget->setParent(&touchWidget);
+ QPointer<tst_QTouchEventWidget> rightWidget = new tst_QTouchEventWidget(&touchWidget);
rightWidget->setAttribute(Qt::WA_AcceptTouchEvents);
rightWidget->setGeometry(200, 100, 100, 100);
rightWidget->deleteInTouchEnd = true;
- rightWidget->show();
+
+ touchWidget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&touchWidget));
QPointF leftPos = leftWidget->rect().center();
QPointF centerPos = centerWidget->rect().center();
@@ -1374,9 +1365,7 @@ void tst_QTouchEvent::deleteInRawEventTranslation()
QPointF leftScreenPos = leftWidget->mapToGlobal(leftPos.toPoint());
QPointF centerScreenPos = centerWidget->mapToGlobal(centerPos.toPoint());
QPointF rightScreenPos = rightWidget->mapToGlobal(rightPos.toPoint());
- QRectF screenGeometry = qApp->desktop()->screenGeometry(&touchWidget);
-
- QPointer<QWidget> pl = leftWidget, pc = centerWidget, pr = rightWidget;
+ QRectF screenGeometry = QApplication::desktop()->screenGeometry(&touchWidget);
QList<QTouchEvent::TouchPoint> rawTouchPoints;
rawTouchPoints.append(QTouchEvent::TouchPoint(0));
@@ -1398,7 +1387,9 @@ void tst_QTouchEvent::deleteInRawEventTranslation()
touchScreenDevice,
touchPointList(rawTouchPoints));
QCoreApplication::processEvents();
- QVERIFY(pl.isNull() && !pc.isNull() && !pr.isNull());
+ QVERIFY(leftWidget.isNull());
+ QVERIFY(!centerWidget.isNull());
+ QVERIFY(!rightWidget.isNull());
// generate update events on all widget, the center widget should die
rawTouchPoints[0].setState(Qt::TouchPointMoved);
@@ -1455,14 +1446,13 @@ void tst_QTouchEvent::touchBeginWithGraphicsWidget()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
- tst_QTouchEventGraphicsItem *root;
- root = new tst_QTouchEventGraphicsItem;
+ QScopedPointer<tst_QTouchEventGraphicsItem> root(new tst_QTouchEventGraphicsItem);
root->setAcceptTouchEvents(true);
- scene.addItem(root);
+ scene.addItem(root.data());
- QGraphicsWidget *glassWidget = new QGraphicsWidget;
+ QScopedPointer<QGraphicsWidget> glassWidget(new QGraphicsWidget);
glassWidget->setMinimumSize(100, 100);
- scene.addItem(glassWidget);
+ scene.addItem(glassWidget.data());
view.resize(200, 200);
view.show();
@@ -1478,7 +1468,7 @@ void tst_QTouchEvent::touchBeginWithGraphicsWidget()
.release(0, view.mapFromScene(root->mapToScene(3,3)), view.viewport())
.release(1, view.mapFromScene(root->mapToScene(6,6)), view.viewport());
- QCOMPARE(root->touchBeginCounter, 1);
+ QTRY_COMPARE(root->touchBeginCounter, 1);
QCOMPARE(root->touchUpdateCounter, 1);
QCOMPARE(root->touchEndCounter, 1);
QCOMPARE(root->touchUpdatePoints.size(), 2);
@@ -1498,17 +1488,13 @@ void tst_QTouchEvent::touchBeginWithGraphicsWidget()
QCOMPARE(root->touchBeginCounter, 0);
QCOMPARE(root->touchUpdateCounter, 0);
QCOMPARE(root->touchEndCounter, 0);
-
-
- delete root;
- delete glassWidget;
}
class WindowTouchEventFilter : public QObject
{
Q_OBJECT
public:
- bool eventFilter(QObject *obj, QEvent *event);
+ bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
struct TouchInfo {
QList<QTouchEvent::TouchPoint> points;
QEvent::Type lastSeenType;
@@ -1537,18 +1523,18 @@ void tst_QTouchEvent::testQGuiAppDelivery()
device->setType(QTouchDevice::TouchScreen);
QWindowSystemInterface::registerTouchDevice(device);
- QWindow *w = new QWindow;
- w->setGeometry(100, 100, 100, 100);
- w->show();
- QVERIFY(QTest::qWaitForWindowExposed(w));
+ QWindow w;
+ w.setGeometry(100, 100, 100, 100);
+ w.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
WindowTouchEventFilter filter;
- w->installEventFilter(&filter);
+ w.installEventFilter(&filter);
QList<QWindowSystemInterface::TouchPoint> points;
// Pass empty list, should be ignored.
- QWindowSystemInterface::handleTouchEvent(w, 0, points);
+ QWindowSystemInterface::handleTouchEvent(&w, 0, points);
QCoreApplication::processEvents();
QCOMPARE(filter.d.isEmpty(), true);
@@ -1559,12 +1545,12 @@ void tst_QTouchEvent::testQGuiAppDelivery()
points.append(tp);
// Pass 0 as device, should be ignored.
- QWindowSystemInterface::handleTouchEvent(w, 0, points);
+ QWindowSystemInterface::handleTouchEvent(&w, 0, points);
QCoreApplication::processEvents();
QCOMPARE(filter.d.isEmpty(), true);
// Now the real thing.
- QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchBegin
+ QWindowSystemInterface::handleTouchEvent(&w, device, points); // TouchBegin
QCoreApplication::processEvents();
QCOMPARE(filter.d.count(), 1);
QCOMPARE(filter.d.contains(device), true);
@@ -1572,7 +1558,7 @@ void tst_QTouchEvent::testQGuiAppDelivery()
QCOMPARE(filter.d.value(device).lastSeenType, QEvent::TouchBegin);
points[0].state = Qt::TouchPointMoved;
- QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchUpdate
+ QWindowSystemInterface::handleTouchEvent(&w, device, points); // TouchUpdate
QCoreApplication::processEvents();
QCOMPARE(filter.d.count(), 1);
QCOMPARE(filter.d.contains(device), true);
@@ -1580,7 +1566,7 @@ void tst_QTouchEvent::testQGuiAppDelivery()
QCOMPARE(filter.d.value(device).lastSeenType, QEvent::TouchUpdate);
points[0].state = Qt::TouchPointReleased;
- QWindowSystemInterface::handleTouchEvent(w, device, points); // TouchEnd
+ QWindowSystemInterface::handleTouchEvent(&w, device, points); // TouchEnd
QCoreApplication::processEvents();
QCOMPARE(filter.d.count(), 1);
QCOMPARE(filter.d.contains(device), true);
@@ -1597,13 +1583,13 @@ void tst_QTouchEvent::testMultiDevice()
deviceTwo->setType(QTouchDevice::TouchScreen);
QWindowSystemInterface::registerTouchDevice(deviceTwo);
- QWindow *w = new QWindow;
- w->setGeometry(100, 100, 100, 100);
- w->show();
- QVERIFY(QTest::qWaitForWindowExposed(w));
+ QWindow w;
+ w.setGeometry(100, 100, 100, 100);
+ w.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
WindowTouchEventFilter filter;
- w->installEventFilter(&filter);
+ w.installEventFilter(&filter);
QList<QWindowSystemInterface::TouchPoint> pointsOne, pointsTwo;
@@ -1620,8 +1606,8 @@ void tst_QTouchEvent::testMultiDevice()
tp.area = QRectF(140, 140, 20, 20);
pointsTwo.append(tp);
- QWindowSystemInterface::handleTouchEvent(w, deviceOne, pointsOne);
- QWindowSystemInterface::handleTouchEvent(w, deviceTwo, pointsTwo);
+ QWindowSystemInterface::handleTouchEvent(&w, deviceOne, pointsOne);
+ QWindowSystemInterface::handleTouchEvent(&w, deviceTwo, pointsTwo);
QCoreApplication::processEvents();
QCOMPARE(filter.d.contains(deviceOne), true);
diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST
new file mode 100644
index 0000000000..ee9709e68b
--- /dev/null
+++ b/tests/auto/gui/kernel/qwindow/BLACKLIST
@@ -0,0 +1,6 @@
+[positioning:default]
+ubuntu-14.04
+[modalWindowPosition]
+ubuntu-14.04
+[modalWithChildWindow]
+ubuntu-14.04
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 517f7fe3bd..666bedc8c2 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -470,6 +470,9 @@ private Q_SLOTS:
void ioHttpChangeMaxRedirects();
void ioHttpRedirectErrors_data();
void ioHttpRedirectErrors();
+#ifndef QT_NO_SSL
+ void putWithServerClosingConnectionImmediately();
+#endif
// NOTE: This test must be last!
void parentingRepliesToTheApp();
@@ -4744,18 +4747,22 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
class SslServer : public QTcpServer {
Q_OBJECT
public:
- SslServer() : socket(0) {};
+ SslServer() : socket(0), m_ssl(true) {}
void incomingConnection(qintptr socketDescriptor) {
QSslSocket *serverSocket = new QSslSocket;
serverSocket->setParent(this);
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
+ connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
+ if (!m_ssl) {
+ emit newPlainConnection(serverSocket);
+ return;
+ }
QString testDataDir = QFileInfo(QFINDTESTDATA("rfc3252.txt")).absolutePath();
if (testDataDir.isEmpty())
testDataDir = QCoreApplication::applicationDirPath();
connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot()));
- connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
serverSocket->setProtocol(QSsl::AnyProtocol);
connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), serverSocket, SLOT(ignoreSslErrors()));
serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem");
@@ -4766,11 +4773,12 @@ public:
}
}
signals:
- void newEncryptedConnection();
+ void newEncryptedConnection(QSslSocket *s);
+ void newPlainConnection(QSslSocket *s);
public slots:
void encryptedSlot() {
socket = (QSslSocket*) sender();
- emit newEncryptedConnection();
+ emit newEncryptedConnection(socket);
}
void readyReadSlot() {
// for the incoming sockets, not the server socket
@@ -4779,6 +4787,7 @@ public slots:
public:
QSslSocket *socket;
+ bool m_ssl;
};
// very similar to ioPostToHttpUploadProgress but for SSL
@@ -4806,7 +4815,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
QNetworkReplyPtr reply(manager.post(request, sourceFile));
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
- connect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply.data(), SLOT(ignoreSslErrors()));
// get the request started and the incoming socket connected
@@ -4814,7 +4823,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
QVERIFY(!QTestEventLoop::instance().timeout());
QTcpSocket *incomingSocket = server.socket;
QVERIFY(incomingSocket);
- disconnect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ disconnect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop()));
incomingSocket->setReadBufferSize(1*1024);
@@ -8147,6 +8156,159 @@ void tst_QNetworkReply::ioHttpRedirectErrors()
QCOMPARE(spy.count(), 1);
QVERIFY(reply->error() == error);
}
+#ifndef QT_NO_SSL
+
+class PutWithServerClosingConnectionImmediatelyHandler: public QObject
+{
+ Q_OBJECT
+public:
+ bool m_parsedHeaders;
+ QByteArray m_receivedData;
+ QByteArray m_expectedData;
+ QSslSocket *m_socket;
+ PutWithServerClosingConnectionImmediatelyHandler(QSslSocket *s, QByteArray expected) :m_parsedHeaders(false), m_expectedData(expected), m_socket(s)
+ {
+ m_socket->setParent(this);
+ connect(m_socket, SIGNAL(readyRead()), SLOT(readyReadSlot()));
+ connect(m_socket, SIGNAL(disconnected()), SLOT(disconnectedSlot()));
+ }
+signals:
+ void correctFileUploadReceived();
+ void corruptFileUploadReceived();
+
+public slots:
+ void closeDelayed() {
+ m_socket->close();
+ }
+
+ void readyReadSlot()
+ {
+ QByteArray data = m_socket->readAll();
+ m_receivedData += data;
+ if (!m_parsedHeaders && m_receivedData.contains("\r\n\r\n")) {
+ m_parsedHeaders = true;
+ QTimer::singleShot(qrand()%10, this, SLOT(closeDelayed())); // simulate random network latency
+ // This server simulates a web server connection closing, e.g. because of Apaches MaxKeepAliveRequests or KeepAliveTimeout
+ // In this case QNAM needs to re-send the upload data but it had a bug which then corrupts the upload
+ // This test catches that.
+ }
+
+ }
+ void disconnectedSlot()
+ {
+ if (m_parsedHeaders) {
+ //qDebug() << m_receivedData.left(m_receivedData.indexOf("\r\n\r\n"));
+ m_receivedData = m_receivedData.mid(m_receivedData.indexOf("\r\n\r\n")+4); // check only actual data
+ }
+ if (m_receivedData.length() > 0 && !m_expectedData.startsWith(m_receivedData)) {
+ // We had received some data but it is corrupt!
+ qDebug() << "CORRUPT" << m_receivedData.count();
+
+ // Use this to track down the pattern of the corruption and conclude the source
+// QFile a("/tmp/corrupt");
+// a.open(QIODevice::WriteOnly);
+// a.write(m_receivedData);
+// a.close();
+
+// QFile b("/tmp/correct");
+// b.open(QIODevice::WriteOnly);
+// b.write(m_expectedData);
+// b.close();
+ //exit(1);
+ emit corruptFileUploadReceived();
+ } else {
+ emit correctFileUploadReceived();
+ }
+ }
+};
+
+class PutWithServerClosingConnectionImmediatelyServer: public SslServer
+{
+ Q_OBJECT
+public:
+ int m_correctUploads;
+ int m_corruptUploads;
+ int m_repliesFinished;
+ int m_expectedReplies;
+ QByteArray m_expectedData;
+ PutWithServerClosingConnectionImmediatelyServer() : SslServer(), m_correctUploads(0), m_corruptUploads(0), m_repliesFinished(0), m_expectedReplies(0)
+ {
+ QObject::connect(this, SIGNAL(newEncryptedConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
+ QObject::connect(this, SIGNAL(newPlainConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*)));
+ }
+
+public slots:
+ void createHandlerForConnection(QSslSocket* s) {
+ PutWithServerClosingConnectionImmediatelyHandler *handler = new PutWithServerClosingConnectionImmediatelyHandler(s, m_expectedData);
+ handler->setParent(this);
+ QObject::connect(handler, SIGNAL(correctFileUploadReceived()), this, SLOT(increaseCorrect()));
+ QObject::connect(handler, SIGNAL(corruptFileUploadReceived()), this, SLOT(increaseCorrupt()));
+ }
+ void increaseCorrect() {
+ m_correctUploads++;
+ }
+ void increaseCorrupt() {
+ m_corruptUploads++;
+ }
+ void replyFinished() {
+ m_repliesFinished++;
+ if (m_repliesFinished == m_expectedReplies) {
+ QTestEventLoop::instance().exitLoop();
+ }
+ }
+};
+
+
+
+void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
+{
+ const int numUploads = 40;
+ qint64 wantedSize = 512*1024; // 512 kB
+ QByteArray sourceFile;
+ for (int i = 0; i < wantedSize; ++i) {
+ sourceFile += (char)'a' +(i%26);
+ }
+ bool withSsl = false;
+
+ for (int s = 0; s <= 1; s++) {
+ withSsl = (s == 1);
+ // Test also needs to run several times because of 9c2ecf89
+ for (int j = 0; j < 20; j++) {
+ // emulate a minimal https server
+ PutWithServerClosingConnectionImmediatelyServer server;
+ server.m_ssl = withSsl;
+ server.m_expectedData = sourceFile;
+ server.m_expectedReplies = numUploads;
+ server.listen(QHostAddress(QHostAddress::LocalHost), 0);
+
+ for (int i = 0; i < numUploads; i++) {
+ // create the request
+ QUrl url = QUrl(QString("http%1://127.0.0.1:%2/file=%3").arg(withSsl ? "s" : "").arg(server.serverPort()).arg(i));
+ QNetworkRequest request(url);
+ QNetworkReply *reply = manager.put(request, sourceFile);
+ connect(reply, SIGNAL(sslErrors(QList<QSslError>)), reply, SLOT(ignoreSslErrors()));
+ connect(reply, SIGNAL(finished()), &server, SLOT(replyFinished()));
+ reply->setParent(&server);
+ }
+
+ // get the request started and the incoming socket connected
+ QTestEventLoop::instance().enterLoop(10);
+
+ //qDebug() << "correct=" << server.m_correctUploads << "corrupt=" << server.m_corruptUploads << "expected=" <<numUploads;
+
+ // Sanity check because ecause of 9c2ecf89 most replies will error out but we want to make sure at least some of them worked
+ QVERIFY(server.m_correctUploads > 5);
+ // Because actually important is that we don't get any corruption:
+ QCOMPARE(server.m_corruptUploads, 0);
+
+ server.close();
+ }
+ }
+
+
+}
+
+#endif
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
diff --git a/tests/auto/network/kernel/qhostinfo/BLACKLIST b/tests/auto/network/kernel/qhostinfo/BLACKLIST
deleted file mode 100644
index ea4b64d7c2..0000000000
--- a/tests/auto/network/kernel/qhostinfo/BLACKLIST
+++ /dev/null
@@ -1,3 +0,0 @@
-# QTBUG-23837
-[abortHostLookupInDifferentThread]
-opensuse-13.1 64bit
diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
index 9762e8244c..599e475beb 100644
--- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
@@ -126,7 +126,6 @@ private slots:
void cache();
void abortHostLookup();
- void abortHostLookupInDifferentThread();
protected slots:
void resultsReady(const QHostInfo &);
@@ -621,25 +620,5 @@ public:
int id;
};
-void tst_QHostInfo::abortHostLookupInDifferentThread()
-{
- //reset counter
- lookupsDoneCounter = 0;
- bool valid = false;
- int id = -1;
- QHostInfo result = qt_qhostinfo_lookup("a-single" TEST_DOMAIN, this, SLOT(resultsReady(QHostInfo)), &valid, &id);
- QVERIFY(!valid);
- QThread thread;
- LookupAborter aborter;
- aborter.id = id;
- aborter.moveToThread(&thread);
- connect(&thread, SIGNAL(started()), &aborter, SLOT(abort()));
- //it is assumed that the DNS request/response in the backend is slower than it takes to schedule the thread and call abort
- thread.start();
- QVERIFY(thread.wait(5000));
- QTestEventLoop::instance().enterLoop(5);
- QCOMPARE(lookupsDoneCounter, 0);
-}
-
QTEST_MAIN(tst_QHostInfo)
#include "tst_qhostinfo.moc"
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index d95f2fa546..b823b87125 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -404,8 +404,8 @@ void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthent
void tst_QSslSocket::constructing()
{
- const char readNotOpenMessage[] = "QIODevice::read: device not open";
- const char writeNotOpenMessage[] = "QIODevice::write: device not open";
+ const char readNotOpenMessage[] = "QIODevice::read (QSslSocket): device not open";
+ const char writeNotOpenMessage[] = "QIODevice::write (QSslSocket): device not open";
if (!QSslSocket::supportsSsl())
return;
@@ -443,13 +443,13 @@ void tst_QSslSocket::constructing()
QCOMPARE(socket.read(0, 0), qint64(-1));
QTest::ignoreMessage(QtWarningMsg, readNotOpenMessage);
QVERIFY(socket.readAll().isEmpty());
- QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine: Called with maxSize < 2");
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine (QSslSocket): Called with maxSize < 2");
QCOMPARE(socket.readLine(0, 0), qint64(-1));
char buf[10];
QCOMPARE(socket.readLine(buf, sizeof(buf)), qint64(-1));
- QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: Cannot call seek on a sequential device");
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek (QSslSocket): Cannot call seek on a sequential device");
QVERIFY(!socket.reset());
- QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: Cannot call seek on a sequential device");
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek (QSslSocket): Cannot call seek on a sequential device");
QVERIFY(!socket.seek(2));
QCOMPARE(socket.size(), qint64(0));
QVERIFY(!socket.waitForBytesWritten(10));
diff --git a/tests/auto/other/baselineexample/baselineexample.pro b/tests/auto/other/baselineexample/baselineexample.pro
deleted file mode 100644
index c1c4b31bfe..0000000000
--- a/tests/auto/other/baselineexample/baselineexample.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator 2010-12-09T14:55:13
-#
-#-------------------------------------------------
-
-QT += testlib widgets
-
-TARGET = tst_baselineexample
-CONFIG += console
-CONFIG -= app_bundle
-
-TEMPLATE = app
-
-SOURCES += tst_baselineexample.cpp
-DEFINES += SRCDIR=\\\"$$PWD/\\\"
-
-include($$PWD/../../../baselineserver/shared/qbaselinetest.pri)
-DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/other/baselineexample/tst_baselineexample.cpp b/tests/auto/other/baselineexample/tst_baselineexample.cpp
deleted file mode 100644
index 9059989015..0000000000
--- a/tests/auto/other/baselineexample/tst_baselineexample.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qbaselinetest.h>
-#include <QPushButton>
-
-class tst_BaselineExample : public QObject
-{
- Q_OBJECT
-
-public:
- tst_BaselineExample();
-
-private Q_SLOTS:
- void testBasicUsage();
- void testMultipleImages();
- void testDataDriven_data();
- void testDataDriven();
- void testDataDrivenChecksum_data();
- void testDataDrivenChecksum();
-};
-
-
-tst_BaselineExample::tst_BaselineExample()
-{
-}
-
-
-void tst_BaselineExample::testBasicUsage()
-{
- // Generate an image:
- QPushButton b("Press me!");
- b.resize(100, 50);
- b.show();
- QVERIFY(QTest::qWaitForWindowExposed(&b));
- QImage img1 = b.grab().toImage();
- QVERIFY(!img1.isNull());
-
- // Compare it to baseline on server:
- QBASELINE_CHECK(img1, "button");
-}
-
-
-void tst_BaselineExample::testMultipleImages()
-{
- QPushButton b("Press me!");
- b.resize(100, 50);
- b.show();
- QVERIFY(QTest::qWaitForWindowExposed(&b));
- QBASELINE_CHECK(b.grab().toImage(), "text1");
-
- b.setText("Kick me!");
- QTest::qWait(50);
- QBASELINE_CHECK(b.grab().toImage(), "text2");
-}
-
-
-void tst_BaselineExample::testDataDriven_data()
-{
- QTest::addColumn<QString>("label");
- QBaselineTest::newRow("short") << "Ok!";
- QBaselineTest::newRow("long") << "A really long button text that just does not seem to end";
- QBaselineTest::newRow("empty") << "";
- QBaselineTest::newRow("signs") << "!@#$%^&*()_";
- QBaselineTest::newRow("html") << "<b>BOLD</b>";
-}
-
-
-void tst_BaselineExample::testDataDriven()
-{
- QFETCH(QString, label);
- QPushButton b(label);
- b.resize(100, 50);
- b.show();
- QVERIFY(QTest::qWaitForWindowExposed(&b));
- QBASELINE_TEST(b.grab().toImage());
-}
-
-
-void tst_BaselineExample::testDataDrivenChecksum_data()
-{
- QTest::addColumn<QString>("label");
-
- const int numItems = 5;
- const char *tags[numItems] = {"short", "long", "empty", "signs", "html"};
- const char *labels[numItems] = {"Ok!", "A really long button text that just does not seem to end", "", "!@#$%^&*()_", "<b>BOLD</b>"};
-
- for (int i = 0; i<numItems; i++) {
- quint16 checksum = qChecksum(labels[i], qstrlen(labels[i]));
- QBaselineTest::newRow(tags[i], checksum) << labels[i];
- }
-}
-
-
-void tst_BaselineExample::testDataDrivenChecksum()
-{
- QFETCH(QString, label);
- QPushButton b(label);
- b.resize(100, 50);
- b.show();
- QVERIFY(QTest::qWaitForWindowExposed(&b));
- QBASELINE_TEST(b.grab().toImage());
-}
-
-
-QTEST_MAIN(tst_BaselineExample);
-
-#include "tst_baselineexample.moc"
diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro
index a5ed4c5f31..8c911da2e0 100644
--- a/tests/auto/other/other.pro
+++ b/tests/auto/other/other.pro
@@ -1,7 +1,6 @@
TEMPLATE=subdirs
SUBDIRS=\
# atwrapper \ # QTBUG-19452
- baselineexample \
compiler \
gestures \
lancelot \
@@ -26,7 +25,6 @@ SUBDIRS=\
toolsupport \
!qtHaveModule(widgets): SUBDIRS -= \
- baselineexample \
gestures \
lancelot \
languagechange \
@@ -41,7 +39,6 @@ SUBDIRS=\
qaccessibilitymac \
!qtHaveModule(network): SUBDIRS -= \
- baselineexample \
lancelot \
networkselftest \
qnetworkaccessmanager_and_qprogressdialog \
diff --git a/tests/auto/testlib/selftests/blacklisted/BLACKLIST b/tests/auto/testlib/selftests/blacklisted/BLACKLIST
new file mode 100644
index 0000000000..36b7699cbd
--- /dev/null
+++ b/tests/auto/testlib/selftests/blacklisted/BLACKLIST
@@ -0,0 +1,12 @@
+[pass]
+*
+[skip]
+*
+[fail]
+*
+[xpass]
+*
+[xfail]
+*
+[messages]
+*
diff --git a/tests/auto/testlib/selftests/blacklisted/blacklisted.pro b/tests/auto/testlib/selftests/blacklisted/blacklisted.pro
new file mode 100644
index 0000000000..5bd22910b1
--- /dev/null
+++ b/tests/auto/testlib/selftests/blacklisted/blacklisted.pro
@@ -0,0 +1,7 @@
+SOURCES += tst_blacklisted.cpp
+QT = core testlib-private
+
+mac: CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = blacklisted
diff --git a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
new file mode 100644
index 0000000000..f1df285a51
--- /dev/null
+++ b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QCoreApplication>
+#include <QtTest/QtTest>
+#include <private/qtestlog_p.h>
+
+class tst_Blacklisted : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void pass();
+ void skip();
+ void fail();
+ void xfail();
+ void xpass();
+
+ // This test function must be last, as it calls qFatal().
+ void messages();
+};
+
+// All the tests below have been blacklisted in blacklisted/BLACKLIST
+
+void tst_Blacklisted::pass()
+{
+ QVERIFY(true);
+}
+
+void tst_Blacklisted::skip()
+{
+ QSKIP("This test should SKIP");
+}
+
+void tst_Blacklisted::fail()
+{
+ QVERIFY2(false, "This test should BFAIL");
+}
+
+void tst_Blacklisted::xfail()
+{
+ QEXPECT_FAIL("", "This test should XFAIL then BFAIL", Abort);
+ QVERIFY(false);
+}
+
+void tst_Blacklisted::xpass()
+{
+ QEXPECT_FAIL("", "This test should XPASS", Abort);
+ QVERIFY2(true, "This test should XPASS, blacklist ignored for XPASS");
+}
+
+void tst_Blacklisted::messages()
+{
+ qWarning("This is a warning that should not appear in silent test output");
+ QWARN("This is an internal testlib warning that should not appear in silent test output");
+ qDebug("This is a debug message that should not appear in silent test output");
+ qCritical("This is a critical message that should not appear in silent test output");
+ qInfo("This is an info message that should not appear in silent test output");
+ QTestLog::info("This is an internal testlib info message that should not appear in silent test output", __FILE__, __LINE__);
+ qFatal("This is a fatal error message that should still appear in silent test output");
+}
+
+QTEST_MAIN(tst_Blacklisted)
+#include "tst_blacklisted.moc"
diff --git a/tests/auto/testlib/selftests/expected_blacklisted.txt b/tests/auto/testlib/selftests/expected_blacklisted.txt
new file mode 100644
index 0000000000..3afd93b0cc
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_blacklisted.txt
@@ -0,0 +1,26 @@
+********* Start testing of tst_Blacklisted *********
+Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
+PASS : tst_Blacklisted::initTestCase()
+BPASS : tst_Blacklisted::pass()
+SKIP : tst_Blacklisted::skip() This test should SKIP
+ Loc: [tst_blacklisted.cpp(62)]
+BFAIL : tst_Blacklisted::fail() 'false' returned FALSE. (This test should BFAIL)
+ Loc: [tst_blacklisted.cpp(67)]
+XFAIL : tst_Blacklisted::xfail() This test should XFAIL then BFAIL
+ Loc: [tst_blacklisted.cpp(73)]
+BPASS : tst_Blacklisted::xfail()
+XPASS : tst_Blacklisted::xpass() 'true' returned TRUE unexpectedly. (This test should XPASS, blacklist ignored for XPASS)
+ Loc: [tst_blacklisted.cpp(79)]
+QWARN : tst_Blacklisted::messages() This is a warning that should not appear in silent test output
+WARNING: tst_Blacklisted::messages() This is an internal testlib warning that should not appear in silent test output
+ Loc: [tst_blacklisted.cpp(85)]
+QDEBUG : tst_Blacklisted::messages() This is a debug message that should not appear in silent test output
+QSYSTEM: tst_Blacklisted::messages() This is a critical message that should not appear in silent test output
+QINFO : tst_Blacklisted::messages() This is an info message that should not appear in silent test output
+INFO : tst_Blacklisted::messages() This is an internal testlib info message that should not appear in silent test output
+ Loc: [tst_blacklisted.cpp(89)]
+QFATAL : tst_Blacklisted::messages() This is a fatal error message that should still appear in silent test output
+BFAIL : tst_Blacklisted::messages() Received a fatal error.
+ Loc: [Unknown file(0)]
+Totals: 1 passed, 1 failed, 1 skipped, 4 blacklisted
+********* Finished testing of tst_Blacklisted *********
diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri
index 7b706735a9..7404a1c49b 100644
--- a/tests/auto/testlib/selftests/selftests.pri
+++ b/tests/auto/testlib/selftests/selftests.pri
@@ -8,6 +8,7 @@ SUBPROGRAMS = \
benchliboptions \
benchlibtickcounter \
benchlibwalltime \
+ blacklisted \
cmptest \
commandlinedata \
counting \
diff --git a/tests/auto/testlib/selftests/selftests.qrc b/tests/auto/testlib/selftests/selftests.qrc
index ba567f1fb4..715e255e76 100644
--- a/tests/auto/testlib/selftests/selftests.qrc
+++ b/tests/auto/testlib/selftests/selftests.qrc
@@ -151,5 +151,6 @@
<file>expected_xunit.txt</file>
<file>expected_xunit.xml</file>
<file>expected_xunit.xunitxml</file>
+ <file>expected_blacklisted.txt</file>
</qresource>
</RCC>
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index a5840d16d2..5e97a9cfe4 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -352,6 +352,7 @@ void tst_Selftests::runSubTest_data()
<< "benchlibcounting"
<< "benchlibeventcounter"
<< "benchliboptions"
+ << "blacklisted"
<< "cmptest"
<< "commandlinedata"
<< "counting"
@@ -470,6 +471,9 @@ void tst_Selftests::runSubTest_data()
if (subtest == "benchliboptions") {
continue;
}
+ if (subtest == "blacklisted") {
+ continue;
+ }
if (subtest == "printdatatags") {
continue;
}
@@ -503,7 +507,8 @@ void tst_Selftests::runSubTest_data()
const bool crashes = subtest == QLatin1String("assert") || subtest == QLatin1String("exceptionthrow")
|| subtest == QLatin1String("fetchbogus") || subtest == QLatin1String("crashedterminate")
- || subtest == QLatin1String("crashes") || subtest == QLatin1String("silent");
+ || subtest == QLatin1String("crashes") || subtest == QLatin1String("silent")
+ || subtest == QLatin1String("blacklisted");
QTest::newRow(qPrintable(QString("%1 %2").arg(subtest).arg(loggerSet.name)))
<< subtest
<< loggers
@@ -612,6 +617,7 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge
&& subdir != QLatin1String("fetchbogus")
&& subdir != QLatin1String("xunit")
#ifdef Q_CC_MINGW
+ && subdir != QLatin1String("blacklisted") // calls qFatal()
&& subdir != QLatin1String("silent") // calls qFatal()
#endif
&& subdir != QLatin1String("benchlibcallgrind"))
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 00e5c60b29..350c6142d2 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -87,6 +87,18 @@ struct QTBUG_31218_Derived : QTBUG_31218<-1<0> {};
class QTBUG_45790 : Bug() { };
#endif
+class CreatableGadget
+{
+ Q_GADGET
+public:
+ Q_INVOKABLE CreatableGadget()
+ {
+ CreatableGadget::qt_static_metacall((QObject*)this, QMetaObject::ReadProperty, -1, Q_NULLPTR);
+ }
+};
+
+CreatableGadget creatableGadget; // Force the compiler to use the constructor
+
struct MyStruct {};
struct MyStruct2 {};
@@ -680,7 +692,7 @@ void tst_Moc::oldStyleCasts()
QStringList args;
args << "-c" << "-x" << "c++" << "-Wold-style-cast" << "-I" << "."
- << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" << "-";
+ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-";
proc.start("gcc", args);
QVERIFY(proc.waitForStarted());
proc.write(mocOut);
@@ -750,7 +762,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension()
QStringList args;
args << "-c" << "-x" << "c++" << "-I" << ".."
- << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIE" << "-";
+ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-";
proc.start("gcc", args);
QVERIFY(proc.waitForStarted());
proc.write(mocOut);
@@ -1029,7 +1041,7 @@ void tst_Moc::ignoreOptionClashes()
// If -pthread wasn't ignored, it was parsed as a prefix of "thread/", which breaks compilation.
QStringList gccArgs;
gccArgs << "-c" << "-x" << "c++" << "-I" << ".."
- << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIE" << "-";
+ << "-I" << qtIncludePath << "-I" << includeDir << "-o" << "/dev/null" << "-fPIC" << "-";
proc.start("gcc", gccArgs);
QVERIFY(proc.waitForStarted());
proc.write(mocOut);
@@ -1870,6 +1882,13 @@ void tst_Moc::warnings_data()
<< 1
<< QString()
<< QString("standard input:5: Error: Class declaration lacks Q_OBJECT macro.");
+
+ QTest::newRow("QTBUG-46210: crash on invalid macro")
+ << QByteArray("#define Foo(a, b, c) a b c #a #b #c a##b##c #d\n Foo(45);")
+ << QStringList()
+ << 1
+ << QString("IGNORE_ALL_STDOUT")
+ << QString(":2: Error: '#' is not followed by a macro parameter");
}
void tst_Moc::warnings()
diff --git a/tests/auto/tools/qmake/testdata/comments/comments.pro b/tests/auto/tools/qmake/testdata/comments/comments.pro
deleted file mode 100644
index 510ab95ab3..0000000000
--- a/tests/auto/tools/qmake/testdata/comments/comments.pro
+++ /dev/null
@@ -1,31 +0,0 @@
-LIST = 1 2 3 4 #a comment
-!equals( LIST, 1 2 3 4 ) {
- message( "FAILED: inline comment" )
-}
-
-LIST = 1 \
- 2 \
-# 3 \
- 4
-!equals( LIST, 1 2 4 ) {
- message( "FAILED: commented out continuation" )
-}
-
-LIST = 1 \
- 2 \#comment
- 3 \
- 4
-!equals( LIST, 1 2 3 4 ) {
- message( "FAILED: comment at end of continuation")
-}
-
-
-LIST = 1 2 3 4#comment
-!equals( LIST, 1 2 3 4 ) {
- message( "FAILED: no space before comment" )
-}
-
-LIST = 1 2 3 4$${LITERAL_HASH}five
-!equals( LIST, 1 2 3 4$${LITERAL_HASH}five ) {
- message( "FAILED: using LITERAL_HASH" )
-}
diff --git a/tests/auto/tools/qmake/testdata/func_export/func_export.pro b/tests/auto/tools/qmake/testdata/func_export/func_export.pro
deleted file mode 100644
index fc3818985b..0000000000
--- a/tests/auto/tools/qmake/testdata/func_export/func_export.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-defineTest(doExport) {
- EXPORTED += $$1
- export(EXPORTED)
-}
-
-defineTest(callDoExport) {
- doExport(bar)
- doExport(baz)
- EXPORTED = oink
- !isEqual(EXPORTED, "oink") {
- message( "FAILED: function-scope exports [$$EXPORTED] != oink" )
- }
-}
-
-doExport(foo)
-callDoExport()
-!isEqual(EXPORTED, "foo bar baz") {
- message( "FAILED: global-scope exports [$$EXPORTED] != foo bar baz" )
-}
diff --git a/tests/auto/tools/qmake/testdata/func_variables/func_variables.pro b/tests/auto/tools/qmake/testdata/func_variables/func_variables.pro
deleted file mode 100644
index cc13437f4a..0000000000
--- a/tests/auto/tools/qmake/testdata/func_variables/func_variables.pro
+++ /dev/null
@@ -1,49 +0,0 @@
-defineTest(testVariable) {
- varname=$$1
- value=$$eval($$varname)
- RESULT=$$value
- export(RESULT)
-}
-
-defineTest(callTest) {
- myvar=$$1
- testVariable(myvar)
-}
-
-defineTest(callTestExport) {
- myvar=$$1
- export(myvar)
- testVariable(myvar)
-}
-
-defineTest(callTestExportChange) {
- myvar=foo
- export(myvar)
- myvar=$$1
- testVariable(myvar)
-}
-
-value=direct
-myvar=$$value
-testVariable(myvar)
-!isEqual(RESULT,$$value) {
- message( "FAILED: result [$$RESULT] != $$value" )
-}
-
-value=export
-callTestExport($$value)
-!isEqual(RESULT,$$value) {
- message( "FAILED: result [$$RESULT] != $$value" )
-}
-
-value=export_and_change
-callTestExportChange($$value)
-!isEqual(RESULT,$$value) {
- message( "FAILED: result [$$RESULT] != $$value" )
-}
-
-value=local
-callTest($$value)
-!isEqual(RESULT,$$value) {
- message( "FAILED: result [$$RESULT] != $$value" )
-}
diff --git a/tests/auto/tools/qmake/testdata/functions/1.cpp b/tests/auto/tools/qmake/testdata/functions/1.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/1.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/2.cpp b/tests/auto/tools/qmake/testdata/functions/2.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/2.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/functions.pro b/tests/auto/tools/qmake/testdata/functions/functions.pro
deleted file mode 100644
index 5db8036188..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/functions.pro
+++ /dev/null
@@ -1,184 +0,0 @@
-VAR = qt thread
-
-defineTest(testReplace) {
- !isEqual(1, $$2):message("FAILED: $$3: got $$1, expected $${2}.")
-}
-
-#count
-!count( VAR, 2 ) {
- message( "FAILED: count function: $$VAR" )
-}
-
-#contains
-!contains( VAR, thread ) {
- message( "FAILED: contains function: $$VAR" )
-}
-
-#exists
-!exists( functions.pro ) {
- message( "FAILED: exists function" )
-}
-
-#isEmpty
-isEmpty( VAR ) {
- message( "FAILED: isEmpty function: $VAR" )
-}
-
-#files
-!equals($$list($$files(one/*.cpp)), "one/1.cpp one/2.cpp") {
- message( "FAILED: files function: one/*.cpp" )
-}
-!equals($$list($$files(one/1*.cpp)), "one/1.cpp") {
- message( "FAILED: files function: one/1*.cpp" )
-}
-!equals($$list($$files(two/*.cpp)), "two/1.cpp two/2.cpp") {
- message( "FAILED: files function: two/*.cpp" )
-}
-!equals($$list($$files(three/wildcard*.cpp)), "three/wildcard21.cpp three/wildcard22.cpp") {
- message( "FAILED: files function: three/wildcard*.cpp" )
-}
-!equals($$list($$files(*.cpp)), "1.cpp 2.cpp wildcard21.cpp wildcard22.cpp") {
- message( "FAILED: files function: *.cpp" )
-}
-!equals($$list($$files(wildcard*.cpp)), "wildcard21.cpp wildcard22.cpp") {
- message( "FAILED: files function: wildcard*.cpp" )
-}
-
-#infile
-!infile( infiletest.pro, DEFINES, QT_DLL ){
- message( "FAILED: infile function" )
-}
-
-#include
-include( infiletest.pro, "", true )
-!contains( DEFINES, QT_DLL ) {
- message( "FAILED: include function: $$DEFINES" )
-}
-
-#replace
-VERSION=1.0.0
-VERSION_replaced=$$replace(VERSION,\\.,_)
-!isEqual(VERSION_replaced, 1_0_0) {
- message( "FAILED: replace function: $$VERSION_replaced" )
-}
-
-#test functions
-defineTest(myTestFunction) {
- RESULT =
- list=$$1
- for(l, list) {
- RESULT += $$l
- }
- export(RESULT)
-}
-myTestFunction(oink baa moo)
-!equals($$list($$member(RESULT, 0)), "oink") {
- message("FAILED: myTestFunction: $$RESULT")
-}
-myTestFunction("oink baa" moo)
-!equals($$list($$member(RESULT, 0)), "oink baa") {
- message("FAILED: myTestFunction: $$RESULT")
-}
-myTestFunction(oink "baa moo")
-!equals($$list($$member(RESULT, 0)), "oink") {
- message("FAILED: myTestFunction: $$RESULT")
-}
-myTestFunction("oink baa moo")
-!equals($$list($$member(RESULT, 0)), "oink baa moo") {
- message("FAILED: myTestFunction: $$RESULT")
-}
-
-#recursive
-defineReplace(myRecursiveReplaceFunction) {
- RESULT =
- list = $$1
- RESULT += $$member(list, 0)
- list -= $$RESULT
- !isEmpty(list):RESULT += $$myRecursiveReplaceFunction($$list)
- return($$RESULT)
-}
-RESULT = $$myRecursiveReplaceFunction(oink baa moo)
-!isEqual(RESULT, "oink baa moo") {
- message( "FAILED: myRecursiveReplaceFunction [$$RESULT] != oink baa moo" )
-}
-
-moo = "this is a test" "for real"
-fn = $$OUT_PWD/testdir/afile
-write_file($$fn, moo)|message("FAILED: write_file() failed")
-exists($$fn)|message("FAILED: write_file() didn't write anything")
-mooout = $$cat($$fn, line)
-equals(moo, $$mooout)|message("FAILED: write_file() wrote something wrong")
-moo += "another line"
-write_file($$fn, moo)|message("FAILED: write_file() failed (take 2)")
-mooout = $$cat($$fn, line)
-equals(moo, $$mooout)|message("FAILED: write_file() wrote something wrong (take 2)")
-mooadd = "yet another line"
-write_file($$fn, mooadd, append)|message("FAILED: write_file() failed (append)")
-moo += $$mooadd
-mooout = $$cat($$fn, line)
-equals(moo, $$mooout)|message("FAILED: write_file() wrote something wrong when appending")
-
-pn = $$OUT_PWD/testpath/subdir
-mkpath($$pn)|message("FAILED: mkpath() failed")
-exists($$pn)|message("FAILED: mkpath() didn't create anything")
-
-in = easy "less easy" sca$${LITERAL_HASH}ry crazy$$escape_expand(\\t\\r\\n) $$escape_expand(\\t)shit \'no\"way\\here
-out = "easy \"less easy\" sca\$\${LITERAL_HASH}ry crazy\$\$escape_expand(\\\\t\\\\r\\\\n) \$\$escape_expand(\\\\t)shit \\\'no\\\"way\\\\here"
-testReplace($$val_escape(in), $$out, "val_escape")
-
-testReplace($$shadowed($$PWD/something), $$OUT_PWD/something, "shadowed")
-testReplace($$shadowed($$PWD), $$OUT_PWD, "shadowed (take 2)")
-
-#format_number
-spc = " "
-testReplace($$format_number(13), 13, "simple number format")
-testReplace($$format_number(-13), -13, "negative number format")
-testReplace($$format_number(13, ibase=16), 19, "hex input number format")
-testReplace($$format_number(13, obase=16), d, "hex output number format")
-testReplace($$format_number(13, width=5), " $$spc 13", "right aligned number format")
-testReplace($$format_number(13, width=5 leftalign), "13 $$spc ", "left aligned number format")
-testReplace($$format_number(13, width=5 zeropad), "00013", "zero-padded number format")
-testReplace($$format_number(13, width=5 alwayssign), "$$spc +13", "always signed number format")
-testReplace($$format_number(13, width=5 alwayssign zeropad), "+0013", "zero-padded always signed number format")
-testReplace($$format_number(13, width=5 padsign), " $$spc 13", "sign-padded number format")
-testReplace($$format_number(13, width=5 padsign zeropad), " 0013", "zero-padded sign-padded number format")
-
-testReplace($$clean_path("c:$${DIR_SEPARATOR}crazy//path/../trolls"), "c:/crazy/trolls", "clean_path")
-
-testReplace($$shell_path("/crazy/trolls"), "$${QMAKE_DIR_SEP}crazy$${QMAKE_DIR_SEP}trolls", "shell_path")
-testReplace($$system_path("/crazy/trolls"), "$${DIR_SEPARATOR}crazy$${DIR_SEPARATOR}trolls", "system_path")
-
-testReplace($$absolute_path("crazy/trolls"), "$$PWD/crazy/trolls", "absolute_path")
-testReplace($$absolute_path("crazy/trolls", "/fake/path"), "/fake/path/crazy/trolls", "absolute_path with base")
-testReplace($$absolute_path(""), "$$PWD", "absolute_path of empty")
-testReplace($$relative_path($$_PRO_FILE_PWD_), $$basename($$_PRO_FILE_), "relative_path")
-testReplace($$relative_path("/fake/trolls", "/fake/path"), "../trolls", "relative_path with base")
-testReplace($$relative_path(""), "", "relative_path of empty")
-
-#this test is very rudimentary. the backend function is thoroughly tested in qt creator
-in = "some nasty & ugly\" path & thing\\"
-out_cmd = "\"some nasty & ugly\\\" path ^& thing\\\\^\""
-out_sh = "'some nasty & ugly\" path & thing\\'"
-equals(QMAKE_HOST.os, Windows): \
- out = $$out_cmd
-else: \
- out = $$out_sh
-testReplace($$system_quote($$in), $$out, "system_quote")
-!equals(QMAKE_DIR_SEP, /): \
- out = $$out_cmd
-else: \
- out = $$out_sh
-testReplace($$shell_quote($$in), $$out, "shell_quote")
-
-testReplace($$reverse($$list(one two three)), three two one, "reverse")
-
-testReplace($$cat(textfile), hi '"holla he"' 'hu!')
-
-MOD.a.depends =
-MOD.b.depends =
-MOD.b.priority = 1
-MOD.c.depends = a b
-testReplace($$resolve_depends($$list(c), "MOD."), c b a)
-MOD.a.priority = 1
-MOD.b.priority = 0
-testReplace($$resolve_depends($$list(c), "MOD."), c a b)
diff --git a/tests/auto/tools/qmake/testdata/functions/one/1.cpp b/tests/auto/tools/qmake/testdata/functions/one/1.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/one/1.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/one/2.cpp b/tests/auto/tools/qmake/testdata/functions/one/2.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/one/2.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/textfile b/tests/auto/tools/qmake/testdata/functions/textfile
deleted file mode 100644
index a8248ed6f8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/textfile
+++ /dev/null
@@ -1 +0,0 @@
-hi "holla he" hu!
diff --git a/tests/auto/tools/qmake/testdata/functions/three/wildcard21.cpp b/tests/auto/tools/qmake/testdata/functions/three/wildcard21.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/three/wildcard21.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/three/wildcard22.cpp b/tests/auto/tools/qmake/testdata/functions/three/wildcard22.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/three/wildcard22.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/two/1.cpp b/tests/auto/tools/qmake/testdata/functions/two/1.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/two/1.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/two/2.cpp b/tests/auto/tools/qmake/testdata/functions/two/2.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/two/2.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/wildcard21.cpp b/tests/auto/tools/qmake/testdata/functions/wildcard21.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/wildcard21.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/functions/wildcard22.cpp b/tests/auto/tools/qmake/testdata/functions/wildcard22.cpp
deleted file mode 100644
index 8bdc2e59e8..0000000000
--- a/tests/auto/tools/qmake/testdata/functions/wildcard22.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/tests/auto/tools/qmake/testdata/include_function/existing_file.pri b/tests/auto/tools/qmake/testdata/include_function/existing_file.pri
deleted file mode 100644
index 8b9aaca340..0000000000
--- a/tests/auto/tools/qmake/testdata/include_function/existing_file.pri
+++ /dev/null
@@ -1,3 +0,0 @@
-QT =
-CONFIG = console
-SOURCES = main.cpp
diff --git a/tests/auto/tools/qmake/testdata/include_function/include_existing_file.pro b/tests/auto/tools/qmake/testdata/include_function/include_existing_file.pro
deleted file mode 100644
index 424062a9ac..0000000000
--- a/tests/auto/tools/qmake/testdata/include_function/include_existing_file.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-# Test to see if include(), by default, succeeds when the specific file
-# to include exists
-include(existing_file.pri)
-
-# Test to see if by specifying full set of parameters to include()
-# succeeds when the specified filed to include exists
-include(existing_file.pri, "", false)
diff --git a/tests/auto/tools/qmake/testdata/include_function/include_missing_file.pro b/tests/auto/tools/qmake/testdata/include_function/include_missing_file.pro
deleted file mode 100644
index 0b59981240..0000000000
--- a/tests/auto/tools/qmake/testdata/include_function/include_missing_file.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-# Test to see if include(), by default, fails when the specific file
-# to include does not exist
-include(missing_file.pri)
diff --git a/tests/auto/tools/qmake/testdata/include_function/include_missing_file2.pro b/tests/auto/tools/qmake/testdata/include_function/include_missing_file2.pro
deleted file mode 100644
index 542b9ff516..0000000000
--- a/tests/auto/tools/qmake/testdata/include_function/include_missing_file2.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-# Specifying full set of parameters to include() to test that a warning
-# is shown for this non-existing file.
-include(missing_file.pri, "", false)
diff --git a/tests/auto/tools/qmake/testdata/include_function/main.cpp b/tests/auto/tools/qmake/testdata/include_function/main.cpp
deleted file mode 100644
index 68e9c98e77..0000000000
--- a/tests/auto/tools/qmake/testdata/include_function/main.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-int main(int /*argc*/, char ** /*argv*/)
-{
- return 0;
-}
diff --git a/tests/auto/tools/qmake/testdata/json/json.pro b/tests/auto/tools/qmake/testdata/json/json.pro
deleted file mode 100644
index 33440b3209..0000000000
--- a/tests/auto/tools/qmake/testdata/json/json.pro
+++ /dev/null
@@ -1,26 +0,0 @@
-jsontext = $$cat($$PWD/test.json)
-parseJson(jsontext, json)
-
-# print all keys
-message(json._KEYS_ $${json._KEYS_})
-
-# print array
-message(json.array._KEYS_ $${json.array._KEYS_})
-for(key, json.array._KEYS_): \
- message(json.array.$${key} $$eval(json.array.$${key}))
-
-# print object
-message(json.object._KEYS_ $${json.object._KEYS_})
-for(key, json.object._KEYS_): \
- message(json.object.$${key} $$eval(json.object.$${key}))
-
-# print value tyes
-message(json.string: $${json.string})
-message(json.number: $${json.number})
-message(json.true: $${json.true})
-message(json.false: $${json.false})
-message(json.null: $${json.null})
-
-# check that booleans work
-$${json.true}: message(json.true is true)
-!$${json.false}: message(json.false is false)
diff --git a/tests/auto/tools/qmake/testdata/json/test.json b/tests/auto/tools/qmake/testdata/json/test.json
deleted file mode 100644
index cc82908eba..0000000000
--- a/tests/auto/tools/qmake/testdata/json/test.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "array" : ["arrayItem1", "arrayItem2", "arrayItem3"],
- "object" : { "key1" : "objectValue1", "key2" : "objectValue2" },
- "string" : "test string",
- "number" : 999,
- "true" : true,
- "false" :false,
- "null" : null
-}
diff --git a/tests/auto/tools/qmake/testdata/operators/operators.pro b/tests/auto/tools/qmake/testdata/operators/operators.pro
deleted file mode 100644
index 463fa73d81..0000000000
--- a/tests/auto/tools/qmake/testdata/operators/operators.pro
+++ /dev/null
@@ -1,23 +0,0 @@
-VAR = qt thread
-
-VAR += debug
-!contains( VAR, debug ) {
- message( "FAILED: +=" )
-}
-
-VAR -= thread
-contains( VAR, thread ) {
- message( "FAILED: -=" )
-}
-
-VAR = thread
-VAR *= thread
-!count( VAR, 1 ) {
- message( "FAILED: *=" )
-}
-
-VAR = thread QT_DLL debug
-VAR ~= s/QT_+/Q_
-!contains( VAR, Q_DLL ) {
- message( "FAILED: ~=" )
-}
diff --git a/tests/auto/tools/qmake/testdata/variables/variables.pro b/tests/auto/tools/qmake/testdata/variables/variables.pro
deleted file mode 100644
index e4b9eaa884..0000000000
--- a/tests/auto/tools/qmake/testdata/variables/variables.pro
+++ /dev/null
@@ -1,12 +0,0 @@
-VAR = 1 2 3 4 5
-JOINEDVAR = $$join( VAR, "-GLUE-", "-BEFORE-", "-AFTER-" )
-!contains( JOINEDVAR, -BEFORE-1-GLUE-2-GLUE-3-GLUE-4-GLUE-5-AFTER- ) {
- message( "FAILED: join [$$JOINEDVAR != -BEFORE-1-GLUE-2-GLUE-3-GLUE-4-GLUE-5-AFTER-]" )
-}
-
-# To test member we need to use join
-NEWVAR = $$member( VAR, 4 ) $$member( VAR, 3 ) $$member( VAR, 2 )
-JOINEDNEWVAR = $$join( NEWVAR, "-" )
-!contains( JOINEDNEWVAR, 5-4-3 ) {
- message( "FAILED: member [$$JOINEDNEWVAR != 5-4-3]" )
-}
diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp
index 48c6c0ac84..ac94d1a2b9 100644
--- a/tests/auto/tools/qmake/tst_qmake.cpp
+++ b/tests/auto/tools/qmake/tst_qmake.cpp
@@ -68,12 +68,6 @@ private slots:
void simple_dll();
void subdirs();
void subdir_via_pro_file_extra_target();
- void functions();
- void operators();
- void variables();
- void func_export();
- void func_variables();
- void comments();
void duplicateLibraryEntries();
void export_across_file_boundaries();
void include_dir();
@@ -88,11 +82,9 @@ private slots:
#if defined(Q_OS_MAC)
void bundle_spaces();
#endif
- void includefunction();
void substitutes();
void project();
void proFileCache();
- void json();
void resources();
private:
@@ -262,43 +254,6 @@ void tst_qmake::subdir_via_pro_file_extra_target()
QVERIFY( test_compiler.make( workDir, "extratarget" ));
}
-void tst_qmake::functions()
-{
- QString workDir = base_path + "/testdata/functions";
- QString buildDir = base_path + "/testdata/functions_build";
- QVERIFY( test_compiler.qmake( workDir, "functions", buildDir ));
-}
-
-void tst_qmake::operators()
-{
- QString workDir = base_path + "/testdata/operators";
- QVERIFY( test_compiler.qmake( workDir, "operators" ));
-}
-
-void tst_qmake::variables()
-{
- QString workDir = base_path + "/testdata/variables";
- QVERIFY(test_compiler.qmake( workDir, "variables" ));
-}
-
-void tst_qmake::func_export()
-{
- QString workDir = base_path + "/testdata/func_export";
- QVERIFY(test_compiler.qmake( workDir, "func_export" ));
-}
-
-void tst_qmake::func_variables()
-{
- QString workDir = base_path + "/testdata/func_variables";
- QVERIFY(test_compiler.qmake( workDir, "func_variables" ));
-}
-
-void tst_qmake::comments()
-{
- QString workDir = base_path + "/testdata/comments";
- QVERIFY(test_compiler.qmake( workDir, "comments" ));
-}
-
void tst_qmake::duplicateLibraryEntries()
{
QVERIFY(true);
@@ -499,26 +454,6 @@ void tst_qmake::bundle_spaces()
}
#endif // defined(Q_OS_MAC)
-void tst_qmake::includefunction()
-{
- QString workDir = base_path + "/testdata/include_function";
- QRegExp warningMsg("Cannot read .*: No such file or directory");
- QVERIFY(test_compiler.qmake( workDir, "include_existing_file"));
- QVERIFY(!test_compiler.commandOutput().contains(warningMsg));
-
- // test include() usage on a missing file
- test_compiler.clearCommandOutput();
- workDir = base_path + "/testdata/include_function";
- QVERIFY(test_compiler.qmake( workDir, "include_missing_file" ));
- QVERIFY(test_compiler.commandOutput().contains(warningMsg));
-
- // test include() usage on a missing file when all function parameters are used
- test_compiler.clearCommandOutput();
- workDir = base_path + "/testdata/include_function";
- QVERIFY(test_compiler.qmake( workDir, "include_missing_file2" ));
- QVERIFY(test_compiler.commandOutput().contains(warningMsg));
-}
-
void tst_qmake::substitutes()
{
QString workDir = base_path + "/testdata/substitutes";
@@ -564,34 +499,6 @@ void tst_qmake::proFileCache()
QVERIFY( test_compiler.qmake( workDir, "pro_file_cache" ));
}
-void tst_qmake::json()
-{
- QString workDir = base_path + "/testdata/json";
- QVERIFY( test_compiler.qmake( workDir, "json.pro" ));
- QString output = test_compiler.commandOutput();
-
- // all keys
- QVERIFY(output.contains("json._KEYS_ array false null number object string true"));
- // array
- QVERIFY(output.contains("json.array._KEYS_ 0 1 2"));
- QVERIFY(output.contains("json.array.0 arrayItem1"));
- QVERIFY(output.contains("json.array.1 arrayItem2"));
- QVERIFY(output.contains("json.array.2 arrayItem3"));
- // object
- QVERIFY(output.contains("json.object._KEYS_ key1 key2"));
- QVERIFY(output.contains("json.object.key1 objectValue1"));
- QVERIFY(output.contains("json.object.key1 objectValue1"));
- // value types
- QVERIFY(output.contains("json.string: test string"));
- QVERIFY(output.contains("json.number: 999"));
- QVERIFY(output.contains("json.true: true"));
- QVERIFY(output.contains("json.false: false"));
- QVERIFY(output.contains("json.null:"));
- // functional booleans
- QVERIFY(output.contains("json.true is true"));
- QVERIFY(output.contains("json.false is false"));
-}
-
void tst_qmake::resources()
{
QString workDir = base_path + "/testdata/resources";
diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp
new file mode 100644
index 0000000000..fab2cdce17
--- /dev/null
+++ b/tests/auto/tools/qmakelib/evaltest.cpp
@@ -0,0 +1,2513 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tst_qmakelib.h"
+
+#include <proitems.h>
+#include <qmakevfs.h>
+#include <qmakeparser.h>
+#include <qmakeglobals.h>
+#include <qmakeevaluator.h>
+
+void tst_qmakelib::addAssignments()
+{
+ QTest::newRow("assignment")
+ << "VAR = foo bar baz"
+ << "VAR = foo bar baz"
+ << ""
+ << true;
+
+ QTest::newRow("appending")
+ << "VAR = foo bar baz\nVAR += foo gaz gaz"
+ << "VAR = foo bar baz foo gaz gaz"
+ << ""
+ << true;
+
+ QTest::newRow("unique appending")
+ << "VAR = foo bar baz\nVAR *= foo gaz gaz"
+ << "VAR = foo bar baz gaz"
+ << ""
+ << true;
+
+ QTest::newRow("removing")
+ << "VAR = foo bar foo baz\nVAR -= foo gaz gaz"
+ << "VAR = bar baz"
+ << ""
+ << true;
+
+ // Somewhat unexpectedly, the g modifier is implicit within each element.
+ QTest::newRow("replacing")
+ << "VAR = foo bar foo baz\nVAR ~= s,o,0,"
+ << "VAR = f00 bar foo baz"
+ << ""
+ << true;
+
+ // Consistently with the "there are no empty elements", what becomes empty gets zapped.
+ QTest::newRow("replacing with nothing")
+ << "VAR = foo bar foo baz\nVAR ~= s,foo,,"
+ << "VAR = bar foo baz"
+ << ""
+ << true;
+
+ QTest::newRow("replacing case-insensitively")
+ << "VAR = foO bar foo baz\nVAR ~= s,o,0,i"
+ << "VAR = f00 bar foo baz"
+ << ""
+ << true;
+
+ // In all elements, not all within each/one/??? element.
+ QTest::newRow("replacing globally")
+ << "VAR = foo bar foo baz\nVAR ~= s,o,0,g"
+ << "VAR = f00 bar f00 baz"
+ << ""
+ << true;
+
+ // Replacing with the same string counts as no match.
+ // This is rather questionable ...
+ QTest::newRow("replacing with same")
+ << "VAR = foo bar foo baz\nVAR ~= s,ba[rz],bar,"
+ << "VAR = foo bar foo bar"
+ << ""
+ << true;
+
+ QTest::newRow("replacing with auto-quote")
+ << "VAR = foo [bar] foo baz\nVAR ~= s,[bar],bar,q"
+ << "VAR = foo bar foo baz"
+ << ""
+ << true;
+
+ QTest::newRow("replacing with expansions")
+ << "VAR = foo bar foo baz\nPAT = foo\nREPL = 'yee haw'\nVAR ~= s,$$PAT,$$REPL,"
+ << "VAR = 'yee haw' bar foo baz"
+ << ""
+ << true;
+
+ QTest::newRow("~= with bad function")
+ << "VAR ~= m/foo/"
+ << ""
+ << "##:1: The ~= operator can handle only the s/// function."
+ << true; // rather questionable
+
+ QTest::newRow("~= s with bad number of arguments")
+ << "VAR ~= s/bla\nVAR ~= s/bla/foo//"
+ << ""
+ << "##:1: The s/// function expects 3 or 4 arguments.\n"
+ "##:2: The s/// function expects 3 or 4 arguments."
+ << true; // rather questionable
+}
+
+void tst_qmakelib::addExpansions()
+{
+ QTest::newRow("expand variable")
+ << "V1 = foo\nVAR = $$V1"
+ << "VAR = foo"
+ << ""
+ << true;
+
+ QTest::newRow("expand property")
+ << "VAR = $$[P1]"
+ << "VAR = 'prop val'"
+ << ""
+ << true;
+
+ QTest::newRow("expand environment variable")
+ << "VAR = $$(E1)"
+ << "VAR = 'env var'"
+ << ""
+ << true;
+
+ // These test addStr/addStr.
+
+ QTest::newRow("expand: str $$(env)")
+ << "VAR = foo $$(E1)"
+ << "VAR = foo 'env var'"
+ << ""
+ << true;
+
+ QTest::newRow("expand: str$$(env)")
+ << "VAR = foo$$(E1)"
+ << "VAR = 'fooenv var'"
+ << ""
+ << true;
+
+ QTest::newRow("expand: 'str $$(env)'")
+ << "VAR = 'foo $$(E1)'"
+ << "VAR = 'foo env var'"
+ << ""
+ << true;
+
+ // These test addStr/addStrList
+
+ QTest::newRow("expand: str $$var")
+ << "V1 = foo barbaz\nVAR = str $$V1"
+ << "VAR = str foo barbaz"
+ << ""
+ << true;
+
+ QTest::newRow("expand: $$var str")
+ << "V1 = foo barbaz\nVAR = $$V1 str"
+ << "VAR = foo barbaz str"
+ << ""
+ << true;
+
+ QTest::newRow("expand: str$$var")
+ << "V1 = foo barbaz\nVAR = str$$V1"
+ << "VAR = strfoo barbaz"
+ << ""
+ << true;
+
+ QTest::newRow("expand: $${var}str")
+ << "V1 = foo barbaz\nVAR = $${V1}str"
+ << "VAR = foo barbazstr"
+ << ""
+ << true;
+
+ QTest::newRow("expand: 'str $$var'")
+ << "V1 = foo barbaz\nVAR = 'str $$V1'"
+ << "VAR = 'str foo barbaz'"
+ << ""
+ << true;
+
+ QTest::newRow("expand: '$$var str'")
+ << "V1 = foo barbaz\nVAR = '$$V1 str'"
+ << "VAR = 'foo barbaz str'"
+ << ""
+ << true;
+
+ // Same again in joined context
+
+ QTest::newRow("expand joined: str $$(env)")
+ << "VAR = $$quote(foo $$(E1))"
+ << "VAR = 'foo env var'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: str$$(env)")
+ << "VAR = $$quote(foo$$(E1))"
+ << "VAR = 'fooenv var'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: 'str $$(env)'")
+ << "VAR = $$quote('foo $$(E1)')"
+ << "VAR = 'foo env var'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: str $$var")
+ << "V1 = foo barbaz\nVAR = $$quote(str $$V1)"
+ << "VAR = 'str foo barbaz'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: $$var str")
+ << "V1 = foo barbaz\nVAR = $$quote($$V1 str)"
+ << "VAR = 'foo barbaz str'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: str$$var")
+ << "V1 = foo barbaz\nVAR = $$quote(str$$V1)"
+ << "VAR = 'strfoo barbaz'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: $${var}str")
+ << "V1 = foo barbaz\nVAR = $$quote($${V1}str)"
+ << "VAR = 'foo barbazstr'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: 'str $$var'")
+ << "V1 = foo barbaz\nVAR = $$quote('str $$V1')"
+ << "VAR = 'str foo barbaz'"
+ << ""
+ << true;
+
+ QTest::newRow("expand joined: '$$var str'")
+ << "V1 = foo barbaz\nVAR = $$quote('$$V1 str')"
+ << "VAR = 'foo barbaz str'"
+ << ""
+ << true;
+
+ // Variable expansions on LHS
+
+ QTest::newRow("indirect assign: $$var")
+ << "V = VAR\n$$V = foo"
+ << "VAR = foo"
+ << ""
+ << true;
+
+ QTest::newRow("indirect assign: fix$$var")
+ << "V = AR\nV$$V = foo"
+ << "VAR = foo"
+ << ""
+ << true;
+
+ QTest::newRow("indirect assign: $${var}fix")
+ << "V = VA\n$${V}R = foo"
+ << "VAR = foo"
+ << ""
+ << true;
+
+ QTest::newRow("indirect assign: eval")
+ << "V = VAR\n$$eval(V) = foo"
+ << "VAR = foo"
+ << ""
+ << true;
+
+ QTest::newRow("indirect assign: multiple")
+ << "V = FOO BAR\n$$V = foo"
+ << ""
+ << "##:2: Left hand side of assignment must expand to exactly one word."
+ << true;
+}
+
+void tst_qmakelib::addControlStructs()
+{
+ QTest::newRow("true")
+ << "true: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("false")
+ << "false: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("true-config")
+ << "CONFIG += test\ntest: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("false-config")
+ << "test: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("true-wildcard")
+ << "CONFIG += testing\ntest*: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("false-wildcard")
+ << "test*: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("true-else")
+ << "true: VAR1 = 1\nelse: VAR2 = 1"
+ << "VAR1 = 1\nVAR2 = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("false-else")
+ << "false: VAR1 = 1\nelse: VAR2 = 1"
+ << "VAR1 = UNDEF\nVAR2 = 1"
+ << ""
+ << true;
+
+ QTest::newRow("true-else-true-else")
+ << "true: VAR1 = 1\nelse: true: VAR2 = 1\nelse: VAR3 = 1"
+ << "VAR1 = 1\nVAR2 = UNDEF\nVAR3 = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("true-else-false-else")
+ << "true: VAR1 = 1\nelse: false: VAR2 = 1\nelse: VAR3 = 1"
+ << "VAR1 = 1\nVAR2 = UNDEF\nVAR3 = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("false-else-true-else")
+ << "false: VAR1 = 1\nelse: true: VAR2 = 1\nelse: VAR3 = 1"
+ << "VAR1 = UNDEF\nVAR2 = 1\nVAR3 = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("false-else-false-else")
+ << "false: VAR1 = 1\nelse: false: VAR2 = 1\nelse: VAR3 = 1"
+ << "VAR1 = UNDEF\nVAR2 = UNDEF\nVAR3 = 1"
+ << ""
+ << true;
+
+ QTest::newRow("true-{false-else}-else")
+ << "true {\nfalse: VAR1 = 1\nelse: VAR2 = 1\n}\nelse: VAR3 = 1"
+ << "VAR1 = UNDEF\nVAR2 = 1\nVAR3 = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("NOT-true")
+ << "!true: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("NOT-false")
+ << "!false: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("true-AND-true")
+ << "true:true: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("true-AND-false")
+ << "true:false: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("false-AND-true")
+ << "false:true: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("false-OR-false")
+ << "false|false: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("true-OR-false")
+ << "true|false: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("false-OR-true")
+ << "false|true: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("NOT-false-AND-true")
+ << "!false:true: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("true-AND-message")
+ << "true:message(hi): VAR = 1"
+ << "VAR = 1"
+ << "Project MESSAGE: hi"
+ << true;
+
+ QTest::newRow("false-AND-message")
+ << "false:message(hi): VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("true-OR-message")
+ << "true|message(hi): VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("false-OR-message")
+ << "false|message(hi): VAR = 1"
+ << "VAR = 1"
+ << "Project MESSAGE: hi"
+ << true;
+
+ QTest::newRow("true-OR-message-AND-false")
+ << "true|message(hi):false: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("false-OR-message-AND-false")
+ << "false|message(hi):false: VAR = 1"
+ << "VAR = UNDEF"
+ << "Project MESSAGE: hi"
+ << true;
+
+ QTest::newRow("true (indirect)")
+ << "TEST = true\n$$TEST: VAR = 1"
+ << "VAR = 1"
+ << ""
+ << true;
+
+ QTest::newRow("false (indirect)")
+ << "TEST = false\n$$TEST: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ // Yes, this is not supposed to work
+ QTest::newRow("true|false (indirect)")
+ << "TEST = true|false\n$$TEST: VAR = 1"
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("for (var, var)")
+ << "IN = one two three\nfor (IT, IN) { OUT += $$IT }"
+ << "OUT = one two three"
+ << ""
+ << true;
+
+ QTest::newRow("for (var, range)")
+ << "for (IT, 1..3) { OUT += $$IT }"
+ << "OUT = 1 2 3"
+ << ""
+ << true;
+
+ QTest::newRow("for (var, reverse-range)")
+ << "for (IT, 3..1) { OUT += $$IT }"
+ << "OUT = 3 2 1"
+ << ""
+ << true;
+
+ // This syntax is rather ridiculous.
+ QTest::newRow("for (ever)")
+ << "for (ever) {}"
+ << ""
+ << "##:1: Ran into infinite loop (> 1000 iterations)."
+ << true;
+
+ // This is even worse.
+ QTest::newRow("for (VAR, forever)")
+ << "for (VAR, forever) { OUT = $$VAR }"
+ << "OUT = 999"
+ << "##:1: Ran into infinite loop (> 1000 iterations)."
+ << true;
+
+ QTest::newRow("for (garbage)")
+ << "for (garbage) { OUT = FAIL }"
+ << "OUT = UNDEF"
+ << "##:1: Invalid loop expression."
+ << true;
+
+ QTest::newRow("next()")
+ << "IN = one two three\nfor (IT, IN) {\nequals(IT, two):next()\nOUT += $$IT\n}"
+ << "OUT = one three"
+ << ""
+ << true;
+
+ QTest::newRow("nested next()")
+ << "IN = one two three\nfor (IT, IN) {\nfor (NIT, IN):next()\nOUT += $$IT\n}"
+ << "OUT = one two three"
+ << ""
+ << true;
+
+ QTest::newRow("break()")
+ << "IN = one two three\nfor (IT, IN) {\nequals(IT, three):break()\nOUT += $$IT\n}"
+ << "OUT = one two"
+ << ""
+ << true;
+
+ QTest::newRow("nested break()")
+ << "IN = one two three\nfor (IT, IN) {\nfor (NIT, IN):break()\nOUT += $$IT\n}"
+ << "OUT = one two three"
+ << ""
+ << true;
+
+ QTest::newRow("defineReplace()")
+ << "defineReplace(func) { return($$1 + $$2) }\n"
+ "VAR = $$func(test me, \"foo bar\")"
+ << "VAR = test me + 'foo bar'"
+ << ""
+ << true;
+
+ QTest::newRow("defineTest()")
+ << "defineTest(func) { return($$1) }\n"
+ "func(true): VAR += true\n"
+ "func(false): VAR += false"
+ << "VAR = true"
+ << ""
+ << true;
+
+ QTest::newRow("true-AND-defineTest()")
+ << "true: defineTest(func)\n"
+ "defined(func): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("false-AND-defineTest()")
+ << "false: defineTest(func)\n"
+ "defined(func): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("true-OR-defineTest()")
+ << "true| defineTest(func)\n"
+ "defined(func): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("false-OR-defineTest()")
+ << "false| defineTest(func)\n"
+ "defined(func): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("variable scoping")
+ << "defineTest(func) {\n"
+ "VAR1 = modified\n!equals(VAR1, modified): return(false)\n"
+ "VAR2 += modified\n!equals(VAR2, original modified): return(false)\n"
+ "VAR3 = new var\n!equals(VAR3, new var): return(false)\n"
+ "return(true)\n"
+ "}\n"
+ "VAR1 = pristine\nVAR2 = original\nfunc(): OK = 1"
+ << "OK = 1\nVAR1 = pristine\nVAR2 = original\nVAR3 = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("ARGC and ARGS")
+ << "defineTest(func) {\n"
+ "export(ARGC)\n"
+ "export(ARGS)\n"
+ "}\n"
+ "func(test me, \"foo bar\")"
+ << "ARGC = 2\nARGS = test me 'foo bar'"
+ << ""
+ << true;
+
+ QTest::newRow("recursion")
+ << "defineReplace(func) {\n"
+ "RET = *$$member(1, 0)*\n"
+ "REST = $$member(1, 1, -1)\n"
+ "!isEmpty(REST): RET += $$func($$REST)\n"
+ "return($$RET)\n"
+ "}\n"
+ "VAR = $$func(you are ...)"
+ << "VAR = *you* *are* *...*"
+ << ""
+ << true;
+
+ QTest::newRow("top-level return()")
+ << "VAR = good\nreturn()\nVAR = bad"
+ << "VAR = good"
+ << ""
+ << true;
+
+ QTest::newRow("return() from function")
+ << "defineTest(func) {\nVAR = good\nexport(VAR)\nreturn()\nVAR = bad\nexport(VAR)\n}\n"
+ "func()"
+ << "VAR = good"
+ << ""
+ << true;
+
+ QTest::newRow("return() from nested function")
+ << "defineTest(inner) {\nVAR = initial\nexport(VAR)\nreturn()\nVAR = bad\nexport(VAR)\n}\n"
+ "defineTest(outer) {\ninner()\nVAR = final\nexport(VAR)\n}\n"
+ "outer()"
+ << "VAR = final"
+ << ""
+ << true;
+}
+
+void tst_qmakelib::addReplaceFunctions(const QString &qindir)
+{
+ QTest::newRow("$$member(): empty")
+ << "IN = \nVAR = $$member(IN)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): too short")
+ << "IN = one two three\nVAR = $$member(IN, 1, 5)"
+ << "VAR =" // this is actually kinda stupid
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): ok")
+ << "IN = one two three four five six seven\nVAR = $$member(IN, 1, 4)"
+ << "VAR = two three four five"
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): ok (default start)")
+ << "IN = one two three\nVAR = $$member(IN)"
+ << "VAR = one"
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): ok (default end)")
+ << "IN = one two three\nVAR = $$member(IN, 2)"
+ << "VAR = three"
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): negative")
+ << "IN = one two three four five six seven\nVAR = $$member(IN, -4, -3)"
+ << "VAR = four five"
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): inverse")
+ << "IN = one two three four five six seven\nVAR = $$member(IN, 4, 1)"
+ << "VAR = five four three two"
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): dots")
+ << "IN = one two three four five six seven\nVAR = $$member(IN, 1..4)"
+ << "VAR = two three four five"
+ << ""
+ << true;
+
+ QTest::newRow("$$member(): bad number of arguments")
+ << "VAR = $$member(1, 2, 3, 4)"
+ << "VAR ="
+ << "##:1: member(var, start, end) requires one to three arguments."
+ << true;
+
+ QTest::newRow("$$member(): bad args (1)")
+ << "IN = one two three\nVAR = $$member(IN, foo, 4)"
+ << "VAR ="
+ << "##:2: member() argument 2 (start) 'foo' invalid."
+ << true;
+
+ QTest::newRow("$$member(): bad args (2)")
+ << "IN = one two three\nVAR = $$member(IN, foo..4)"
+ << "VAR ="
+ << "##:2: member() argument 2 (start) 'foo..4' invalid."
+ << true;
+
+ QTest::newRow("$$member(): bad args (3)")
+ << "IN = one two three\nVAR = $$member(IN, 4, foo)"
+ << "VAR ="
+ << "##:2: member() argument 3 (end) 'foo' invalid."
+ << true;
+
+ QTest::newRow("$$member(): bad args (4)")
+ << "IN = one two three\nVAR = $$member(IN, 4..foo)"
+ << "VAR ="
+ << "##:2: member() argument 2 (start) '4..foo' invalid."
+ << true;
+
+ QTest::newRow("$$first(): empty")
+ << "IN = \nVAR = $$first(IN)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$first(): one")
+ << "IN = one\nVAR = $$first(IN)"
+ << "VAR = one"
+ << ""
+ << true;
+
+ QTest::newRow("$$first(): multiple")
+ << "IN = one two three\nVAR = $$first(IN)"
+ << "VAR = one"
+ << ""
+ << true;
+
+ QTest::newRow("$$first(): bad number of arguments")
+ << "VAR = $$first(1, 2)"
+ << "VAR ="
+ << "##:1: first(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$last(): empty")
+ << "IN = \nVAR = $$last(IN)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$last(): one")
+ << "IN = one\nVAR = $$last(IN)"
+ << "VAR = one"
+ << ""
+ << true;
+
+ QTest::newRow("$$last(): multiple")
+ << "IN = one two three\nVAR = $$last(IN)"
+ << "VAR = three"
+ << ""
+ << true;
+
+ QTest::newRow("$$last(): bad number of arguments")
+ << "VAR = $$last(1, 2)"
+ << "VAR ="
+ << "##:1: last(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$size()")
+ << "IN = one two three\nVAR = $$size(IN)"
+ << "VAR = 3"
+ << ""
+ << true;
+
+ QTest::newRow("$$size(): bad number of arguments")
+ << "VAR = $$size(1, 2)"
+ << "VAR ="
+ << "##:1: size(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$fromfile(): right var")
+ << "VAR = $$fromfile(" + qindir + "/fromfile/infile.prx, DEFINES)"
+ << "VAR = QT_DLL"
+ << ""
+ << true;
+
+ QTest::newRow("$$fromfile(): wrong var")
+ << "VAR = $$fromfile(" + qindir + "/fromfile/infile.prx, INCLUDES)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$fromfile(): bad file")
+ << "VAR = $$fromfile(" + qindir + "/fromfile/badfile.prx, DEFINES)"
+ << "VAR ="
+ << "Project ERROR: fail!"
+ << true;
+
+ QTest::newRow("$$fromfile(): bad number of arguments")
+ << "VAR = $$fromfile(1) \\\n$$fromfile(1, 2, 3)"
+ << "VAR ="
+ << "##:1: fromfile(file, variable) requires two arguments.\n"
+ "##:2: fromfile(file, variable) requires two arguments."
+ << true;
+
+ QTest::newRow("$$eval()")
+ << "IN = one two three\nVAR = $$eval(IN)"
+ << "VAR = one two three"
+ << ""
+ << true;
+
+ QTest::newRow("$$eval(): bad number of arguments")
+ << "VAR = $$eval(1, 2)"
+ << "VAR ="
+ << "##:1: eval(variable) requires one argument."
+ << true;
+
+ QTest::newRow("$$list()")
+ << "VARNAME = $$list(one, two three, 'four five')\nVAR = $$eval($$VARNAME)"
+ << "VAR = one two three four five" // total nonsense ...
+ << ""
+ << true;
+
+ QTest::newRow("$$sprintf()")
+ << "VAR = $$sprintf(hello %1 %2, you, there)"
+ << "VAR = 'hello you there'"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): simple number format")
+ << "VAR = $$format_number(13)"
+ << "VAR = 13"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): negative number format")
+ << "VAR = $$format_number(-13)"
+ << "VAR = -13"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): hex input number format")
+ << "VAR = $$format_number(13, ibase=16)"
+ << "VAR = 19"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): hex output number format")
+ << "VAR = $$format_number(13, obase=16)"
+ << "VAR = d"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): right aligned number format")
+ << "VAR = $$format_number(13, width=5)"
+ << "VAR = ' 13'"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): left aligned number format")
+ << "VAR = $$format_number(13, width=5 leftalign)"
+ << "VAR = '13 '"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): zero-padded number format")
+ << "VAR = $$format_number(13, width=5 zeropad)"
+ << "VAR = 00013"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): always signed number format")
+ << "VAR = $$format_number(13, width=5 alwayssign)"
+ << "VAR = ' +13'"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): zero-padded always signed number format")
+ << "VAR = $$format_number(13, width=5 alwayssign zeropad)"
+ << "VAR = +0013"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): sign-padded number format")
+ << "VAR = $$format_number(13, width=5 padsign)"
+ << "VAR = ' 13'"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): zero-padded sign-padded number format")
+
+ << "VAR = $$format_number(13, width=5 padsign zeropad)"
+ << "VAR = ' 0013'"
+ << ""
+ << true;
+
+ QTest::newRow("$$format_number(): bad number of arguments")
+ << "VAR = $$format_number(13, 1, 2)"
+ << "VAR ="
+ << "##:1: format_number(number[, options...]) requires one or two arguments."
+ << true;
+
+ QTest::newRow("$$format_number(): invalid option")
+ << "VAR = $$format_number(13, foo=bar)"
+ << "VAR ="
+ << "##:1: format_number(): invalid format option foo=bar."
+ << true;
+
+ QTest::newRow("$$join(): empty")
+ << "IN = \nVAR = $$join(IN, //)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$join(): multiple")
+ << "IN = one two three\nVAR = $$join(IN, //)"
+ << "VAR = one//two//three"
+ << ""
+ << true;
+
+ QTest::newRow("$$join(): multiple surrounded")
+ << "IN = one two three\nVAR = $$join(IN, //, <<, >>)"
+ << "VAR = <<one//two//three>>"
+ << ""
+ << true;
+
+ QTest::newRow("$$join(): bad number of arguments")
+ << "VAR = $$join(1, 2, 3, 4, 5)"
+ << "VAR ="
+ << "##:1: join(var, glue, before, after) requires one to four arguments."
+ << true;
+
+ QTest::newRow("$$split(): default sep")
+ << "IN = 'one/two three' 'four / five'\nVAR = $$split(IN)"
+ << "VAR = one/two three four / five"
+ << ""
+ << true;
+
+ QTest::newRow("$$split(): specified sep")
+ << "IN = 'one/two three' 'four / five'\nVAR = $$split(IN, /)"
+ << "VAR = one 'two three' 'four ' ' five'"
+ << ""
+ << true;
+
+ QTest::newRow("$$split(): bad number of arguments")
+ << "VAR = $$split(1, 2, 3)"
+ << "VAR ="
+ << "##:1: split(var, sep) requires one or two arguments."
+ << true;
+
+ QTest::newRow("$$basename(): empty")
+ << "IN = \nVAR = $$basename(IN)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$basename(): bare")
+ << "IN = file\nVAR = $$basename(IN)"
+ << "VAR = file"
+ << ""
+ << true;
+
+ QTest::newRow("$$basename(): relative")
+ << "IN = path/file\nVAR = $$basename(IN)"
+ << "VAR = file"
+ << ""
+ << true;
+
+ QTest::newRow("$$basename(): absolute")
+ << "IN = \\\\path\\\\file\nVAR = $$basename(IN)"
+ << "VAR = file"
+ << ""
+ << true;
+
+ QTest::newRow("$$basename(): bad number of arguments")
+ << "VAR = $$basename(1, 2)"
+ << "VAR ="
+ << "##:1: basename(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$dirname(): empty")
+ << "IN = \nVAR = $$dirname(IN)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$dirname(): bare")
+ << "IN = file\nVAR = $$dirname(IN)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$dirname(): relative")
+ << "IN = path/file\nVAR = $$dirname(IN)"
+ << "VAR = path"
+ << ""
+ << true;
+
+ QTest::newRow("$$dirname(): absolute")
+ << "IN = \\\\path\\\\file\nVAR = $$dirname(IN)"
+ << "VAR = \\\\path"
+ << ""
+ << true;
+
+ QTest::newRow("$$dirname(): bad number of arguments")
+ << "VAR = $$dirname(1, 2)"
+ << "VAR ="
+ << "##:1: dirname(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$section(): explicit end")
+ << "IN = one~two~three~four~five~six\nVAR = $$section(IN, ~, 2, 4)"
+ << "VAR = three~four~five"
+ << ""
+ << true;
+
+ QTest::newRow("$$section(): implicit end")
+ << "IN = one~two~three~four~five~six\nVAR = $$section(IN, ~, 3)"
+ << "VAR = four~five~six"
+ << ""
+ << true;
+
+ QTest::newRow("$$section(): bad number of arguments")
+ << "VAR = $$section(1, 2) \\\n$$section(1, 2, 3, 4, 5)"
+ << "VAR ="
+ << "##:1: section(var) section(var, sep, begin, end) requires three or four arguments.\n"
+ "##:2: section(var) section(var, sep, begin, end) requires three or four arguments."
+ << true;
+
+ QTest::newRow("$$find()")
+ << "IN = foo bar baz blubb\nVAR = $$find(IN, ^ba)"
+ << "VAR = bar baz"
+ << ""
+ << true;
+
+ QTest::newRow("$$find(): bad number of arguments")
+ << "VAR = $$find(1) \\\n$$find(1, 2, 3)"
+ << "VAR ="
+ << "##:1: find(var, str) requires two arguments.\n"
+ "##:2: find(var, str) requires two arguments."
+ << true;
+
+ // FIXME: $$cat() & $$system(): There is no way to generate the newlines
+ // necessary for testing "multi-line" and "blob" mode adequately.
+ // Note: these functions have *different* splitting behavior.
+
+ // This gives split_value_list() an exercise
+ QTest::newRow("$$cat(): default mode")
+ << "VAR = $$cat(" + qindir + "/cat/file2.txt)"
+ << "VAR = foo bar baz \"\\\"Hello, \\' world.\\\"\" post \"\\'Hello, \\\" world.\\'\" post \\\\\\\" \\\\\\' \\\\\\\\ \\\\a \\\\ nix \"\\\" \\\"\""
+ << ""
+ << true;
+
+ QTest::newRow("$$cat(): lines mode")
+ << "VAR = $$cat(" + qindir + "/cat/file1.txt, lines)"
+ << "VAR = '\"Hello, world.\"' 'foo bar baz'"
+ << ""
+ << true;
+
+ QTest::newRow("$$cat(): bad number of arguments")
+ << "VAR = $$cat(1, 2, 3)"
+ << "VAR ="
+ << "##:1: cat(file, singleline=true) requires one or two arguments."
+ << true;
+
+ QTest::newRow("$$system(): default mode")
+#ifdef Q_OS_WIN
+ << "VAR = $$system('echo Hello, ^\"world.&& echo foo^\" bar baz')"
+#else
+ << "VAR = $$system('echo Hello, \\\\\\\"world. && echo foo\\\\\\\" bar baz')"
+#endif
+ << "VAR = Hello, '\"world. foo\"' bar baz"
+ << ""
+ << true;
+
+ QTest::newRow("$$system(): lines mode")
+#ifdef Q_OS_WIN
+ << "VAR = $$system('echo Hello, ^\"world.&& echo foo^\" bar baz', lines)"
+#else
+ << "VAR = $$system('echo Hello, \\\\\\\"world. && echo foo\\\\\\\" bar baz', lines)"
+#endif
+ << "VAR = 'Hello, \"world.' 'foo\" bar baz'"
+ << ""
+ << true;
+
+ QTest::newRow("$$system(): bad number of arguments")
+ << "VAR = $$system(1, 2, 3)"
+ << "VAR ="
+ << "##:1: system(execute) requires one or two arguments."
+ << true;
+
+ QTest::newRow("$$unique()")
+ << "IN = foo bar foo baz\nVAR = $$unique(IN)"
+ << "VAR = foo bar baz"
+ << ""
+ << true;
+
+ QTest::newRow("$$unique(): bad number of arguments")
+ << "VAR = $$unique(1, 2)"
+ << "VAR ="
+ << "##:1: unique(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$reverse()")
+ << "IN = one two three\nVAR = $$reverse(IN)"
+ << "VAR = three two one"
+ << ""
+ << true;
+
+ QTest::newRow("$$reverse(): bad number of arguments")
+ << "VAR = $$reverse(1, 2)"
+ << "VAR ="
+ << "##:1: reverse(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$quote()")
+ << "VAR = $$quote(foo bar, 'foo bar')"
+ << "VAR = 'foo bar' 'foo bar'"
+ << ""
+ << true;
+
+ // FIXME: \n and \r go untested, because there is no way to get them into the
+ // expected result. And if there was one, this function would be unnecessary.
+ // In other news, the behavior of backslash escaping makes no sense.
+ QTest::newRow("$$escape_expand()")
+ << "VAR = $$escape_expand(foo\\\\ttab\\\\\\\\slash\\\\invalid, verbatim)"
+ << "VAR = 'foo\ttab\\\\\\\\slash\\\\invalid' verbatim"
+ << ""
+ << true;
+
+ QTest::newRow("$$upper()")
+ << "VAR = $$upper(kEwL, STuff)"
+ << "VAR = KEWL STUFF"
+ << ""
+ << true;
+
+ QTest::newRow("$$lower()")
+ << "VAR = $$lower(kEwL, STuff)"
+ << "VAR = kewl stuff"
+ << ""
+ << true;
+
+ QTest::newRow("$$title()")
+ << "VAR = $$title(kEwL, STuff)"
+ << "VAR = Kewl Stuff"
+ << ""
+ << true;
+
+ QTest::newRow("$$re_escape()")
+ << "VAR = $$re_escape(one, hey.*you[funny]+people)"
+ << "VAR = one hey\\\\.\\\\*you\\\\[funny\\\\]\\\\+people"
+ << ""
+ << true;
+
+ QTest::newRow("$$val_escape()")
+ << "IN = easy \"less easy\" sca$${LITERAL_HASH}ry"
+ " crazy$$escape_expand(\\\\t\\\\r\\\\n)"
+ " $$escape_expand(\\\\t)stuff \\'no\\\"way\\\\here\n"
+ "VAR = $$val_escape(IN)"
+ << "VAR = easy '\\\"less easy\\\"' sca\\$\\${LITERAL_HASH}ry"
+ " crazy\\$\\$escape_expand(\\\\\\\\t\\\\\\\\r\\\\\\\\n)"
+ " \\$\\$escape_expand(\\\\\\\\t)stuff \\\\\\'no\\\\\\\"way\\\\\\\\here"
+ << ""
+ << true;
+
+ QTest::newRow("$$val_escape(): bad number of arguments")
+ << "VAR = $$val_escape(1, 2)"
+ << "VAR ="
+ << "##:1: val_escape(var) requires one argument."
+ << true;
+
+ QTest::newRow("$$files(): non-recursive")
+ << "VAR = $$files(" + qindir + "/files/file*.txt)"
+ << "VAR = " + qindir + "/files/file1.txt "
+ + qindir + "/files/file2.txt"
+ << ""
+ << true;
+
+ QTest::newRow("$$files(): recursive")
+ << "VAR = $$files(" + qindir + "/files/file*.txt, true)"
+ << "VAR = " + qindir + "/files/file1.txt "
+ + qindir + "/files/file2.txt "
+ + qindir + "/files/dir/file1.txt "
+ + qindir + "/files/dir/file2.txt"
+ << ""
+ << true;
+
+ QTest::newRow("$$files(): bad number of arguments")
+ << "VAR = $$files(1, 2, 3)"
+ << "VAR ="
+ << "##:1: files(pattern, recursive=false) requires one or two arguments."
+ << true;
+
+#if 0
+ // FIXME: no emulated input layer
+ QTest::newRow("$$prompt()")
+ << "VAR = $$prompt(que)"
+ << "VAR = whatever"
+ << "Project PROMPT: que? "
+ << true;
+#endif
+
+ QTest::newRow("$$replace()")
+ << "IN = foo 'bar baz'\nVAR = $$replace(IN, \\\\bba, hello)"
+ << "VAR = foo 'hellor helloz'"
+ << ""
+ << true;
+
+ QTest::newRow("$$replace(): bad number of arguments")
+ << "VAR = $$replace(1, 2) \\\n$$replace(1, 2, 3, 4)"
+ << "VAR ="
+ << "##:1: replace(var, before, after) requires three arguments.\n"
+ "##:2: replace(var, before, after) requires three arguments."
+ << true;
+
+ QTest::newRow("$$sort_depends()")
+ << "foo.depends = bar baz\n"
+ "bar.depends = baz bak duck\n"
+ "baz.depends = bak\n"
+ "bak.depends = duck\n"
+ "VAR = $$sort_depends($$list(baz foo duck bar))"
+ << "VAR = foo bar baz duck"
+ << ""
+ << true;
+
+ QTest::newRow("$$resolve_depends(): basic")
+ << "foo.depends = bar baz\n"
+ "bar.depends = baz bak duck\n"
+ "baz.depends = bak\n"
+ "bak.depends = duck\n"
+ "VAR = $$resolve_depends($$list(baz foo duck bar))"
+ << "VAR = foo bar baz bak duck"
+ << ""
+ << true;
+
+ QTest::newRow("$$resolve_depends(): prefix and multiple suffixes")
+ << "MOD.foo.dep = bar baz\n"
+ "MOD.bar.dep = baz bak\n"
+ "MOD.bar.priv_dep = duck\n"
+ "MOD.baz.dep = bak\n"
+ "MOD.bak.dep = duck\n"
+ "VAR = $$resolve_depends($$list(baz foo duck bar), MOD., .dep .priv_dep)"
+ << "VAR = foo bar baz bak duck"
+ << ""
+ << true;
+
+ QTest::newRow("$$resolve_depends(): priorities: b first")
+ << "MOD.a.depends =\n"
+ "MOD.b.depends =\n"
+ "MOD.b.priority = 1\n"
+ "MOD.c.depends = a b\n"
+ "VAR = $$resolve_depends($$list(c), MOD.)"
+ << "VAR = c b a"
+ << ""
+ << true;
+
+ QTest::newRow("$$resolve_depends(): priorities: a first")
+ << "MOD.a.depends =\n"
+ "MOD.a.priority = 1\n"
+ "MOD.b.depends =\n"
+ "MOD.b.priority = 0\n"
+ "MOD.c.depends = a b\n"
+ "VAR = $$resolve_depends($$list(c), MOD.)"
+ << "VAR = c a b"
+ << ""
+ << true;
+
+ QTest::newRow("$$resolve_depends(): priorities: custom suffix")
+ << "MOD.a.depends =\n"
+ "MOD.a.prrt = 1\n"
+ "MOD.b.depends =\n"
+ "MOD.b.prrt = 0\n"
+ "MOD.c.depends = a b\n"
+ "VAR = $$resolve_depends($$list(c), MOD., .depends, .prrt)"
+ << "VAR = c a b"
+ << ""
+ << true;
+
+ QTest::newRow("$$resolve_depends(): bad number of arguments")
+ << "VAR = $$resolve_depends(1, 2, 3, 4, 5)"
+ << "VAR ="
+ << "##:1: resolve_depends(var, [prefix, [suffixes, [prio-suffix]]]) requires one to four arguments."
+ << true;
+
+ QTest::newRow("$$enumerate_vars()")
+ << "V1 = foo\nV2 = bar\nVAR = $$enumerate_vars()\n"
+ "count(VAR, 2, >=):contains(VAR, V1):contains(VAR, V2): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("$$shadowed(): bare")
+ << "VAR = $$shadowed(test.txt)"
+ << "VAR = " + QMakeEvaluator::quoteValue(ProString(m_outdir + "/test.txt"))
+ << ""
+ << true;
+
+ QTest::newRow("$$shadowed(): subdir")
+ << "VAR = $$shadowed(" + qindir + "/sub/test.txt)"
+ << "VAR = " + QMakeEvaluator::quoteValue(ProString(m_outdir + "/sub/test.txt"))
+ << ""
+ << true;
+
+ QTest::newRow("$$shadowed(): outside source dir")
+ << "VAR = $$shadowed(/some/random/path)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$shadowed(): bad number of arguments")
+ << "VAR = $$shadowed(1, 2)"
+ << "VAR ="
+ << "##:1: shadowed(path) requires one argument."
+ << true;
+
+ QTest::newRow("$$absolute_path(): relative file")
+ << "VAR = $$absolute_path(dir/file.ext)"
+ << "VAR = " + qindir + "/dir/file.ext"
+ << ""
+ << true;
+
+ QTest::newRow("$$absolute_path(): file & path")
+ << "VAR = $$absolute_path(dir/file.ext, /root/sub)"
+ << "VAR = /root/sub/dir/file.ext"
+ << ""
+ << true;
+
+ QTest::newRow("$$absolute_path(): absolute file & path")
+ << "VAR = $$absolute_path(/root/sub/dir/file.ext, /other)"
+ << "VAR = /root/sub/dir/file.ext"
+ << ""
+ << true;
+
+ QTest::newRow("$$absolute_path(): empty file & path")
+ << "VAR = $$absolute_path('', /root/sub)"
+ << "VAR = /root/sub"
+ << ""
+ << true;
+
+ QTest::newRow("$$absolute_path(): bad number of arguments")
+ << "VAR = $$absolute_path(1, 2, 3)"
+ << "VAR ="
+ << "##:1: absolute_path(path[, base]) requires one or two arguments."
+ << true;
+
+ QTest::newRow("$$relative_path(): relative file")
+ << "VAR = $$relative_path(dir/file.ext)"
+ << "VAR = dir/file.ext"
+ << ""
+ << true;
+
+ QTest::newRow("$$relative_path(): relative file to empty")
+ << "VAR = $$relative_path(dir/..)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$relative_path(): absolute file & path")
+ << "VAR = $$relative_path(/root/sub/dir/file.ext, /root/sub)"
+ << "VAR = dir/file.ext"
+ << ""
+ << true;
+
+ QTest::newRow("$$relative_path(): empty file & path")
+ << "VAR = $$relative_path('', /root/sub)"
+ << "VAR ="
+ << ""
+ << true;
+
+ QTest::newRow("$$relative_path(): bad number of arguments")
+ << "VAR = $$relative_path(1, 2, 3)"
+ << "VAR ="
+ << "##:1: relative_path(path[, base]) requires one or two arguments."
+ << true;
+
+ QTest::newRow("$$clean_path()")
+#ifdef Q_OS_WIN // This is actually kinda stupid.
+ << "VAR = $$clean_path(foo//bar\\\\../baz/)"
+#else
+ << "VAR = $$clean_path(foo//bar/../baz/)"
+#endif
+ << "VAR = foo/baz"
+ << ""
+ << true;
+
+ QTest::newRow("$$clean_path(): bad number of arguments")
+ << "VAR = $$clean_path(1, 2)"
+ << "VAR ="
+ << "##:1: clean_path(path) requires one argument."
+ << true;
+
+ QTest::newRow("$$system_path()")
+ << "VAR = $$system_path(foo/bar\\\\baz)"
+#ifdef Q_OS_WIN
+ << "VAR = foo\\\\bar\\\\baz"
+#else
+ << "VAR = foo/bar/baz"
+#endif
+ << ""
+ << true;
+
+ QTest::newRow("$$system_path(): bad number of arguments")
+ << "VAR = $$system_path(1, 2)"
+ << "VAR ="
+ << "##:1: system_path(path) requires one argument."
+ << true;
+
+ // This is is effectively $$system_path() in this test, as we load no specs
+ QTest::newRow("$$shell_path()")
+ << "VAR = $$shell_path(foo/bar\\\\baz)"
+#ifdef Q_OS_WIN
+ << "VAR = foo\\\\bar\\\\baz"
+#else
+ << "VAR = foo/bar/baz"
+#endif
+ << ""
+ << true;
+
+ QTest::newRow("$$shell_path(): bad number of arguments")
+ << "VAR = $$shell_path(1, 2)"
+ << "VAR ="
+ << "##:1: shell_path(path) requires one argument."
+ << true;
+
+ // The quoteArgs() test exercises this more thoroughly
+ QTest::newRow("$$system_quote()")
+ << "IN = \nVAR = $$system_quote(\"some nasty & ugly\\\" path & thing\\\\\")"
+#ifdef Q_OS_WIN
+ << "VAR = \"\\\"some nasty & ugly\\\\\\\" path ^& thing\\\\\\\\^\\\"\""
+#else
+ << "VAR = \"'some nasty & ugly\\\" path & thing\\\\'\""
+#endif
+ << ""
+ << true;
+
+ QTest::newRow("$$system_quote(): bad number of arguments")
+ << "VAR = $$system_quote(1, 2)"
+ << "VAR ="
+ << "##:1: system_quote(arg) requires one argument."
+ << true;
+
+ // This is is effectively $$system_path() in this test, as we load no specs
+ QTest::newRow("$$shell_quote()")
+ << "IN = \nVAR = $$shell_quote(\"some nasty & ugly\\\" path & thing\\\\\")"
+#ifdef Q_OS_WIN
+ << "VAR = \"\\\"some nasty & ugly\\\\\\\" path ^& thing\\\\\\\\^\\\"\""
+#else
+ << "VAR = \"'some nasty & ugly\\\" path & thing\\\\'\""
+#endif
+ << ""
+ << true;
+
+ QTest::newRow("$$shell_quote(): bad number of arguments")
+ << "VAR = $$shell_quote(1, 2)"
+ << "VAR ="
+ << "##:1: shell_quote(arg) requires one argument."
+ << true;
+
+ QTest::newRow("$$getenv()")
+ << "VAR = $$getenv(E1)"
+ << "VAR = 'env var'"
+ << ""
+ << true;
+
+ QTest::newRow("$$getenv(): bad number of arguments")
+ << "VAR = $$getenv(1, 2)"
+ << "VAR ="
+ << "##:1: getenv(arg) requires one argument."
+ << true;
+}
+
+void tst_qmakelib::addTestFunctions(const QString &qindir)
+{
+ QTest::newRow("defined(): found replace")
+ << "defineReplace(func) {}\ndefined(func): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("defined(): found test")
+ << "defineTest(func) {}\ndefined(func): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("defined(): not found")
+ << "defined(func): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("defined(replace): found")
+ << "defineReplace(func) {}\ndefined(func, replace): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("defined(replace): not found")
+ << "defineTest(func) {}\ndefined(func, replace): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("defined(test): found")
+ << "defineTest(func) {}\ndefined(func, test): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("defined(test): not found")
+ << "defineReplace(func) {}\ndefined(func, test): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("defined(var): found")
+ << "VAR = 1\ndefined(VAR, var): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("defined(var): not found")
+ << "defined(VAR, var): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("defined(): invalid type")
+ << "defined(VAR, nope): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: defined(function, type): unexpected type [nope]."
+ << true;
+
+ QTest::newRow("defined(): bad number of arguments")
+ << "defined(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: defined(function, [\"test\"|\"replace\"|\"var\"]) requires one or two arguments."
+ << true;
+
+ QTest::newRow("export()")
+ << "defineTest(func) {\n"
+ "VAR1 += different\nexport(VAR1)\n"
+ "unset(VAR2)\nexport(VAR2): OK = 1\nexport(OK)\n"
+ "VAR3 = new var\nexport(VAR3)\n"
+ "}\n"
+ "VAR1 = entirely\nVAR2 = set\nfunc()"
+ << "OK = 1\nVAR1 = entirely different\nVAR2 =\nVAR3 = new var"
+ << ""
+ << true;
+
+ QTest::newRow("export(): bad number of arguments")
+ << "export(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: export(variable) requires one argument."
+ << true;
+
+ QTest::newRow("infile(): found")
+ << "infile(" + qindir + "/fromfile/infile.prx, DEFINES): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("infile(): not found")
+ << "infile(" + qindir + "/fromfile/infile.prx, INCLUDES): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("infile(plain): found")
+ << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, QT_DLL): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("infile(plain): not found")
+ << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, NOPE): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("infile(regex): found")
+ << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, QT_.*): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("infile(regex): not found")
+ << "infile(" + qindir + "/fromfile/infile.prx, DEFINES, NO.*): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ // The early return is debatable, esp. as it's inconsistent with $$fromfile()
+ QTest::newRow("infile(): bad file")
+ << "infile(" + qindir + "/fromfile/badfile.prx, DEFINES): OK = 1\nOKE = 1"
+ << "OK = UNDEF\nOKE = UNDEF"
+ << "Project ERROR: fail!"
+ << false;
+
+ QTest::newRow("infile(): bad number of arguments")
+ << "infile(1): OK = 1\ninfile(1, 2, 3, 4): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: infile(file, var, [values]) requires two or three arguments.\n"
+ "##:2: infile(file, var, [values]) requires two or three arguments."
+ << true;
+
+ QTest::newRow("requires()")
+ << "requires(true, false, isEmpty(FOO), !isEmpty(BAR), true|false, true:false)"
+ << "QMAKE_FAILED_REQUIREMENTS = false !isEmpty(BAR) true:false"
+ << ""
+ << true;
+
+ // The sparator semantics are *very* questionable.
+ // The return value semantics are rather questionable.
+ QTest::newRow("eval()")
+ << "eval(FOO = one, two$$escape_expand(\\\\n)BAR = blah$$escape_expand(\\\\n)error(fail)$$escape_expand(\\\\n)BAZ = nope)"
+ << "FOO = one two\nBAR = blah\nBAZ = UNDEF"
+ << "Project ERROR: fail"
+ << true;
+
+ QTest::newRow("if(): true")
+ << "if(false|true): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("if(): true (space)")
+ << "if(false| true): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("if(): true (spaces)")
+ << "if( false | true ): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("if(): false")
+ << "if(false:true): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("if(): false (space)")
+ << "if(false: true): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("if(): false (spaces)")
+ << "if( false : true ): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("if(): bad number of arguments")
+ << "if(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: if(condition) requires one argument."
+ << true;
+
+ QTest::newRow("CONFIG(simple): true")
+ << "CONFIG = debug release\nCONFIG(debug): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("CONFIG(simple): false")
+ << "CONFIG = debug release\nCONFIG(nope): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("CONFIG(alt): true")
+ << "CONFIG = debug release\nCONFIG(release, debug|release): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("CONFIG(alt): false (presence)")
+ << "CONFIG = not here\nCONFIG(debug, debug|release): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("CONFIG(alt): false (order)")
+ << "CONFIG = debug release\nCONFIG(debug, debug|release): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("CONFIG(): bad number of arguments")
+ << "CONFIG(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: CONFIG(config) requires one or two arguments."
+ << true;
+
+ QTest::newRow("contains(simple plain): true")
+ << "VAR = one two three\ncontains(VAR, two): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("contains(simple plain): false")
+ << "VAR = one two three\ncontains(VAR, four): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("contains(simple regex): true")
+ << "VAR = one two three\ncontains(VAR, tw.*): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("contains(simple regex): false")
+ << "VAR = one two three\ncontains(VAR, fo.*): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("contains(alt plain): true")
+ << "VAR = one two three\ncontains(VAR, three, two|three): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("contains(alt plain): false (presence)")
+ << "VAR = one four five\ncontains(VAR, three, two|three): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("contains(alt plain): false (order)")
+ << "VAR = one two three\ncontains(VAR, two, two|three): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("contains(alt regex): true")
+ << "VAR = one two three\ncontains(VAR, th.*, two|three): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("contains(alt regex): false (presence)")
+ << "VAR = one four five\ncontains(VAR, th.*, two|three): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("contains(alt regex): false (order)")
+ << "VAR = one two three\ncontains(VAR, tw.*, two|three): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("contains(): bad number of arguments")
+ << "contains(1): OK = 1\ncontains(1, 2, 3, 4): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: contains(var, val) requires two or three arguments.\n"
+ "##:2: contains(var, val) requires two or three arguments."
+ << true;
+
+ QTest::newRow("count(): true")
+ << "VAR = one two three\ncount(VAR, 3): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("count(): false")
+ << "VAR = one two three\ncount(VAR, 4): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("count(operators): true")
+ << "VAR = one two three\n"
+ "count(VAR, 3, equals): OKE1 = 1\n"
+ "count(VAR, 3, isEqual): OKE2 = 1\n"
+ "count(VAR, 3, =): OKE3 = 1\n"
+ "count(VAR, 3, ==): OKE4 = 1\n"
+ "count(VAR, 2, greaterThan): OKG1 = 1\n"
+ "count(VAR, 2, >): OKG2 = 1\n"
+ "count(VAR, 2, >=): OKGE = 1\n"
+ "count(VAR, 4, lessThan): OKL1 = 1\n"
+ "count(VAR, 4, <): OKL2 = 1\n"
+ "count(VAR, 4, <=): OKLE = 1\n"
+ << "OKE1 = 1\nOKE2 = 1\nOKE3 = 1\nOKE4 = 1\n"
+ "OKG1 = 1\nOKG2 = 1\nOKGE = 1\n"
+ "OKL1 = 1\nOKL2 = 1\nOKLE = 1"
+ << ""
+ << true;
+
+ QTest::newRow("count(operators): false")
+ << "VAR = one two three\n"
+ "count(VAR, 4, equals): OKE1 = 1\n"
+ "count(VAR, 4, isEqual): OKE2 = 1\n"
+ "count(VAR, 4, =): OKE3 = 1\n"
+ "count(VAR, 4, ==): OKE4 = 1\n"
+ "count(VAR, 3, greaterThan): OKG1 = 1\n"
+ "count(VAR, 3, >): OKG2 = 1\n"
+ "count(VAR, 4, >=): OKGE = 1\n"
+ "count(VAR, 3, lessThan): OKL1 = 1\n"
+ "count(VAR, 3, <): OKL2 = 1\n"
+ "count(VAR, 2, <=): OKLE = 1\n"
+ << "OKE1 = UNDEF\nOKE2 = UNDEF\nOKE3 = UNDEF\nOKE4 = UNDEF\n"
+ "OKG1 = UNDEF\nOKG2 = UNDEF\nOKGE = UNDEF\n"
+ "OKL1 = UNDEF\nOKL2 = UNDEF\nOKLE = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("count(): bad operator")
+ << "VAR = one two three\ncount(VAR, 2, !!!): OK = 1"
+ << "OK = UNDEF"
+ << "##:2: Unexpected modifier to count(!!!)."
+ << true;
+
+ QTest::newRow("count(): bad number of arguments")
+ << "count(1): OK = 1\ncount(1, 2, 3, 4): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: count(var, count, op=\"equals\") requires two or three arguments.\n"
+ "##:2: count(var, count, op=\"equals\") requires two or three arguments."
+ << true;
+
+ QTest::newRow("greaterThan(int): true")
+ << "VAR = 20\ngreaterThan(VAR, 3): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("greaterThan(int): false")
+ << "VAR = 3\ngreaterThan(VAR, 20): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("greaterThan(string): true")
+ << "VAR = foo 3\ngreaterThan(VAR, foo 20): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("greaterThan(string): false")
+ << "VAR = foo 20\ngreaterThan(VAR, foo 3): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("greaterThan(): bad number of arguments")
+ << "greaterThan(1): OK = 1\ngreaterThan(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: greaterThan(variable, value) requires two arguments.\n"
+ "##:2: greaterThan(variable, value) requires two arguments."
+ << true;
+
+ QTest::newRow("lessThan(int): true")
+ << "VAR = 3\nlessThan(VAR, 20): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("lessThan(int): false")
+ << "VAR = 20\nlessThan(VAR, 3): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("lessThan(string): true")
+ << "VAR = foo 20\nlessThan(VAR, foo 3): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("lessThan(string): false")
+ << "VAR = foo 3\nlessThan(VAR, foo 20): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("lessThan(): bad number of arguments")
+ << "lessThan(1): OK = 1\nlessThan(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: lessThan(variable, value) requires two arguments.\n"
+ "##:2: lessThan(variable, value) requires two arguments."
+ << true;
+
+ QTest::newRow("equals(): true")
+ << "VAR = foo\nequals(VAR, foo): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("equals(): false")
+ << "VAR = foo\nequals(VAR, bar): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("equals(): bad number of arguments")
+ << "equals(1): OK = 1\nequals(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: equals(variable, value) requires two arguments.\n"
+ "##:2: equals(variable, value) requires two arguments."
+ << true;
+
+ // That's just an alias, so don't test much.
+ QTest::newRow("isEqual(): true")
+ << "VAR = foo\nisEqual(VAR, foo): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("clear(): top-level")
+ << "VAR = there\nclear(VAR): OK = 1"
+ << "OK = 1\nVAR ="
+ << ""
+ << true;
+
+ QTest::newRow("clear(): scoped")
+ << "defineTest(func) {\n"
+ "clear(VAR): OK = 1\nexport(OK)\n"
+ "equals(VAR, \"\"): OKE = 1\nexport(OKE)\n"
+ "}\n"
+ "VAR = there\nfunc()"
+ << "OK = 1\nOKE = 1"
+ << ""
+ << true;
+
+ QTest::newRow("clear(): absent")
+ << "clear(VAR): OK = 1"
+ << "OK = UNDEF\nVAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("clear(): bad number of arguments")
+ << "clear(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: clear(variable) requires one argument."
+ << true;
+
+ QTest::newRow("unset(): top-level")
+ << "VAR = there\nunset(VAR): OK = 1"
+ << "OK = 1\nVAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("unset(): scoped")
+ << "defineTest(func) {\n"
+ "unset(VAR): OK = 1\nexport(OK)\n"
+ "!defined(VAR, var): OKE = 1\nexport(OKE)\n"
+ "}\n"
+ "VAR = there\nfunc()"
+ << "OK = 1\nOKE = 1"
+ << ""
+ << true;
+
+ QTest::newRow("unset(): absent")
+ << "unset(VAR): OK = 1"
+ << "OK = UNDEF\nVAR = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("unset(): bad number of arguments")
+ << "unset(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: unset(variable) requires one argument."
+ << true;
+
+ // This function does not follow the established naming pattern.
+ QTest::newRow("parseJson()")
+ << "jsontext = \\\n"
+ " \"{\"\\\n"
+ " \" \\\"array\\\" : [\\\"arrayItem1\\\", \\\"arrayItem2\\\", \\\"arrayItem3\\\"],\"\\\n"
+ " \" \\\"object\\\" : { \\\"key1\\\" : \\\"objectValue1\\\", \\\"key2\\\" : \\\"objectValue2\\\" },\"\\\n"
+ " \" \\\"string\\\" : \\\"test string\\\",\"\\\n"
+ " \" \\\"number\\\" : 999,\"\\\n"
+ " \" \\\"true\\\" : true,\"\\\n"
+ " \" \\\"false\\\" :false,\"\"\\\n"
+ " \" \\\"null\\\" : null\"\"\\\n"
+ " \"}\"\n"
+ "parseJson(jsontext, json): OK = 1"
+ << "OK = 1\n"
+ "json._KEYS_ = array false null number object string true\n"
+ // array
+ "json.array._KEYS_ = 0 1 2\n"
+ "json.array.0 = arrayItem1\n"
+ "json.array.1 = arrayItem2\n"
+ "json.array.2 = arrayItem3\n"
+ // object
+ "json.object._KEYS_ = key1 key2\n"
+ "json.object.key1 = objectValue1\n"
+ "json.object.key1 = objectValue1\n"
+ // value types
+ "json.string = 'test string'\n"
+ "json.number = 999\n"
+ "json.true = true\n"
+ "json.false = false\n"
+ "json.null = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("parseJson(): bad input")
+ << "jsontext = not good\n"
+ "parseJson(jsontext, json): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("parseJson(): bad number of arguments")
+ << "parseJson(1): OK = 1\nparseJson(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: parseJson(variable, into) requires two arguments.\n"
+ "##:2: parseJson(variable, into) requires two arguments."
+ << true;
+
+ QTest::newRow("include()")
+ << "include(include/inc.pri): OK = 1\nfunc()"
+ << "OK = 1\nVAR = val\n.VAR = nope"
+ << "Project MESSAGE: say hi!"
+ << true;
+
+ QTest::newRow("include(): fail")
+ << "include(include/nope.pri): OK = 1"
+ << "OK = UNDEF"
+ << "Cannot read " + m_indir + "/include/nope.pri: No such file or directory"
+ << true;
+
+ QTest::newRow("include(): silent fail")
+ << "include(include/nope.pri, , true): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("include(into)")
+ << "SUB.MISS = 1\ninclude(include/inc.pri, SUB): OK = 1"
+ << "OK = 1\nSUB.VAR = val\nSUB..VAR = UNDEF\nSUB.MISS = UNDEF\n"
+ // As a side effect, we test some things that need full project setup
+ "SUB.MATCH = 1\nSUB.QMAKESPEC = " + qindir + "/mkspecs/fake-g++"
+ << ""
+ << true;
+
+ QTest::newRow("include(): bad number of arguments")
+ << "include(1, 2, 3, 4): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: include(file, [into, [silent]]) requires one, two or three arguments."
+ << true;
+
+ QTest::newRow("load()")
+ << "load(testfeat): OK = 1"
+ << "OK = 1\nVAR = foo bar"
+ << ""
+ << true;
+
+ QTest::newRow("load(): fail")
+ << "load(no_such_feature): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: Cannot find feature no_such_feature"
+ << true;
+
+ QTest::newRow("load(): silent fail")
+ << "load(no_such_feature, true): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("load(): bad number of arguments")
+ << "load(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: load(feature) requires one or two arguments."
+ << true;
+
+ // We don't test debug() and log(), because they print directly to stderr.
+
+ QTest::newRow("message()")
+ << "message('Hello, World!'): OK = 1\nOKE = 1"
+ << "OK = 1\nOKE = 1"
+ << "Project MESSAGE: Hello, World!"
+ << true;
+
+ // Don't test that for warning() and error(), as it's the same code path.
+ QTest::newRow("message(): bad number of arguments")
+ << "message(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: message(message) requires one argument."
+ << true;
+
+ QTest::newRow("warning()")
+ << "warning('World, be warned!'): OK = 1\nOKE = 1"
+ << "OK = 1\nOKE = 1"
+ << "Project WARNING: World, be warned!"
+ << true;
+
+ QTest::newRow("error()")
+ << "error('World, you FAIL!'): OK = 1\nOKE = 1"
+ << "OK = UNDEF\nOKE = UNDEF"
+ << "Project ERROR: World, you FAIL!"
+ << false;
+
+ QTest::newRow("system()")
+ << "system('"
+#ifdef Q_OS_WIN
+ "cd"
+#else
+ "pwd"
+#endif
+ "> '" + QMakeEvaluator::quoteValue(ProString(QDir::toNativeSeparators(
+ m_outdir + "/system_out.txt"))) + "): OK = 1\n"
+ "DIR = $$cat(" + QMakeEvaluator::quoteValue(ProString(
+ m_outdir + "/system_out.txt")) + ")"
+ << "OK = 1\nDIR = " + QMakeEvaluator::quoteValue(ProString(QDir::toNativeSeparators(m_indir)))
+ << ""
+ << true;
+
+ QTest::newRow("system(): fail")
+#ifdef Q_OS_WIN
+ << "system(no_such_cmd 2> NUL): OK = 1"
+#else
+ << "system(no_such_cmd 2> /dev/null): OK = 1"
+#endif
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("system(): bad number of arguments")
+ << "system(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: system(exec) requires one argument."
+ << true;
+
+ QTest::newRow("isEmpty(): true (empty)")
+ << "VAR =\nisEmpty(VAR): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("isEmpty(): true (undef)")
+ << "isEmpty(VAR): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("isEmpty(): false")
+ << "VAR = val\nisEmpty(VAR): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("isEmpty(): bad number of arguments")
+ << "isEmpty(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: isEmpty(var) requires one argument."
+ << true;
+
+ QTest::newRow("exists(plain): true")
+ << "exists(files/file1.txt): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("exists(plain): false")
+ << "exists(files/not_there.txt): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("exists(wildcard): true")
+ << "exists(files/fil*.txt): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("exists(wildcard): false")
+ << "exists(files/not_th*.txt): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("exists(): bad number of arguments")
+ << "exists(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: exists(file) requires one argument."
+ << true;
+
+ QString wpath = QMakeEvaluator::quoteValue(ProString(m_outdir + "/outdir/written.txt"));
+ QTest::newRow("write_file(): create")
+ << "VAR = 'this is text' 'yet again'\n"
+ "write_file(" + wpath + ", VAR): OK = 1\n"
+ "OUT = $$cat(" + wpath + ", lines)"
+ << "OK = 1\nOUT = 'this is text' 'yet again'"
+ << ""
+ << true;
+
+ QTest::newRow("write_file(): truncate")
+ << "VAR = 'other content'\n"
+ "write_file(" + wpath + ", VAR): OK = 1\n"
+ "OUT = $$cat(" + wpath + ", lines)"
+ << "OK = 1\nOUT = 'other content'"
+ << ""
+ << true;
+
+ QTest::newRow("write_file(): append")
+ << "VAR = 'one more line'\n"
+ "write_file(" + wpath + ", VAR, append): OK = 1\n"
+ "OUT = $$cat(" + wpath + ", lines)"
+ << "OK = 1\nOUT = 'other content' 'one more line'"
+ << ""
+ << true;
+
+ QString vpath = QMakeEvaluator::quoteValue(ProString(m_outdir));
+ QTest::newRow("write_file(): fail")
+ << "write_file(" + vpath + "): OK = 1"
+ << "OK = UNDEF"
+#ifdef Q_OS_WIN
+ << "##:1: Cannot write file " + QDir::toNativeSeparators(m_outdir) + ": Access is denied."
+#else
+ << "##:1: Cannot write file " + m_outdir + ": Is a directory"
+#endif
+ << true;
+
+ QTest::newRow("write_file(): bad number of arguments")
+ << "write_file(1, 2, 3, 4): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: write_file(name, [content var, [append]]) requires one to three arguments."
+ << true;
+
+ // FIXME: This doesn't test whether it actually works.
+ QTest::newRow("touch()")
+ << "touch(" + wpath + ", files/other.txt): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("touch(): missing target")
+ << "touch(/does/not/exist, files/other.txt): OK = 1"
+ << "OK = UNDEF"
+#ifdef Q_OS_WIN
+ << "##:1: Cannot open /does/not/exist: The system cannot find the path specified."
+#else
+ << "##:1: Cannot touch /does/not/exist: No such file or directory."
+#endif
+ << true;
+
+ QTest::newRow("touch(): missing reference")
+ << "touch(" + wpath + ", /does/not/exist): OK = 1"
+ << "OK = UNDEF"
+#ifdef Q_OS_WIN
+ << "##:1: Cannot open reference file /does/not/exist: The system cannot find the path specified."
+#else
+ << "##:1: Cannot stat() reference file /does/not/exist: No such file or directory."
+#endif
+ << true;
+
+ QTest::newRow("touch(): bad number of arguments")
+ << "touch(1): OK = 1\ntouch(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: touch(file, reffile) requires two arguments.\n"
+ "##:2: touch(file, reffile) requires two arguments."
+ << true;
+
+ QString apath = QMakeEvaluator::quoteValue(ProString(m_outdir + "/a/path"));
+ QTest::newRow("mkpath()")
+ << "mkpath(" + apath + "): OK = 1\n"
+ "exists(" + apath + "): OKE = 1"
+ << "OK = 1\nOKE = 1"
+ << ""
+ << true;
+
+ QString bpath = QMakeEvaluator::quoteValue(ProString(m_outdir + "/fail_me"));
+ QTest::newRow("mkpath(): fail")
+ << "write_file(" + bpath + ")|error(FAIL)\n"
+ "mkpath(" + bpath + "): OK = 1"
+ << "OK = UNDEF"
+ << "##:2: Cannot create directory " + QDir::toNativeSeparators(m_outdir + "/fail_me") + '.'
+ << true;
+
+ QTest::newRow("mkpath(): bad number of arguments")
+ << "mkpath(1, 2): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: mkpath(file) requires one argument."
+ << true;
+
+#if 0
+ // FIXME ... insanity lies ahead
+ QTest::newRow("cache()")
+ << ""
+ << ""
+ << ""
+ << true;
+#endif
+}
+
+void tst_qmakelib::proEval_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+ QTest::addColumn<QString>("msgs");
+ QTest::addColumn<bool>("ok");
+
+ QTest::newRow("empty")
+ << ""
+ << "VAR = UNDEF"
+ << ""
+ << true;
+
+ addAssignments();
+ addExpansions(); // Variable, etc. expansions on RHS
+ addControlStructs(); // Conditions, loops, custom functions
+
+ QString qindir = QMakeEvaluator::quoteValue(ProString(m_indir));
+ addReplaceFunctions(qindir); // Built-in replace functions
+ addTestFunctions(qindir); // Built-in test functions
+
+ // Some compound tests that verify compatibility with odd Qt 4 edge cases
+
+ QTest::newRow("empty (leading)")
+ << "defineTest(myMsg) { message(\"$$1\") }\n"
+ "XMPL = /this/is/a/test\n"
+ "message(split: $$split(XMPL, /))\n"
+ "message(split joined:$$split(XMPL, /))\n"
+ "message(\"split quoted: $$split(XMPL, /)\")\n"
+ "myMsg(my split: $$split(XMPL, /) :post)\n"
+ "myMsg(my split joined:$$split(XMPL, /):post)\n"
+ "myMsg(\"my split quoted: $$split(XMPL, /) post\")\n"
+ "OUT = word $$split(XMPL, /) done\n"
+ "message(\"assign split separate: $$OUT\")\n"
+ "OUT = word:$$split(XMPL, /):done\n"
+ "message(\"assign split joined: $$OUT\")\n"
+ "OUT = \"word $$split(XMPL, /) done\"\n"
+ "message(\"assign split quoted: $$OUT\")\n"
+ << ""
+ << "Project MESSAGE: split: this is a test\n"
+ "Project MESSAGE: split joined: this is a test\n"
+ "Project MESSAGE: split quoted: this is a test\n"
+ "Project MESSAGE: my split: this is a test :post\n"
+ "Project MESSAGE: my split joined: this is a test:post\n"
+ "Project MESSAGE: my split quoted: this is a test post\n"
+ "Project MESSAGE: assign split separate: word this is a test done\n"
+ "Project MESSAGE: assign split joined: word: this is a test:done\n"
+ "Project MESSAGE: assign split quoted: word this is a test done"
+ << true;
+
+ QTest::newRow("empty (multiple)")
+ << "defineTest(myMsg) { message(\"$$1\") }\n"
+ "XMPL = //this///is/a/////test\n"
+ "message(split: $$split(XMPL, /) :post)\n"
+ "message(split joined:$$split(XMPL, /):post)\n"
+ "message(\"split quoted: $$split(XMPL, /) post\")\n"
+ "myMsg(my split: $$split(XMPL, /) :post)\n"
+ "myMsg(my split joined:$$split(XMPL, /):post)\n"
+ "myMsg(\"my split quoted: $$split(XMPL, /) post\")\n"
+ "OUT = word $$split(XMPL, /) done\n"
+ "message(\"assign split separate: $$OUT\")\n"
+ "OUT = word:$$split(XMPL, /):done\n"
+ "message(\"assign split joined: $$OUT\")\n"
+ "OUT = \"word $$split(XMPL, /) done\"\n"
+ "message(\"assign split quoted: $$OUT\")\n"
+ << ""
+ << "Project MESSAGE: split: this is a test :post\n"
+ "Project MESSAGE: split joined: this is a test:post\n"
+ "Project MESSAGE: split quoted: this is a test post\n"
+ "Project MESSAGE: my split: this is a test :post\n"
+ "Project MESSAGE: my split joined: this is a test:post\n"
+ "Project MESSAGE: my split quoted: this is a test post\n"
+ "Project MESSAGE: assign split separate: word this is a test done\n"
+ "Project MESSAGE: assign split joined: word: this is a test:done\n"
+ "Project MESSAGE: assign split quoted: word this is a test done"
+ << true;
+}
+
+static QString formatValue(const ProStringList &vals)
+{
+ QString ret;
+
+ foreach (const ProString &str, vals) {
+ ret += QLatin1Char(' ');
+ ret += QMakeEvaluator::quoteValue(str);
+ }
+ return ret;
+}
+
+static void skipNoise(const ushort *&tokPtr)
+{
+ forever {
+ ushort tok = *tokPtr;
+ if (tok != TokLine)
+ break;
+ tokPtr += 2;
+ }
+}
+
+static bool compareState(QMakeEvaluator *eval, ProFile *out)
+{
+ bool ret = true;
+ const ushort *tokPtr = out->tokPtr();
+ forever {
+ skipNoise(tokPtr);
+ ushort tok = *tokPtr++;
+ if (!tok)
+ break;
+ if (tok != TokHashLiteral) {
+ qWarning("Expected output is malformed: not variable%s",
+ qPrintable(QMakeParser::formatProBlock(out->items())));
+ return false;
+ }
+ const ProKey &var = out->getHashStr(tokPtr);
+ tok = *tokPtr++;
+ if (tok != TokAssign) {
+ qWarning("Expected output is malformed: not assignment%s",
+ qPrintable(QMakeParser::formatProBlock(out->items())));
+ return false;
+ }
+ ProStringList value;
+ value.reserve(*tokPtr++);
+ forever {
+ skipNoise(tokPtr);
+ tok = *tokPtr++;
+ if (tok == TokValueTerminator)
+ break;
+ if (tok != (TokLiteral | TokNewStr)) {
+ qWarning("Expected output is malformed: not literal%s",
+ qPrintable(QMakeParser::formatProBlock(out->items())));
+ return false;
+ }
+ value << out->getStr(tokPtr);
+ }
+ ProValueMap::Iterator it;
+ ProValueMap *vmap = eval->findValues(var, &it);
+ if (value.length() == 1 && value.at(0) == "UNDEF") {
+ if (vmap) {
+ qWarning("Value of %s is incorrect.\n Actual:%s\nExpected: <UNDEFINED>",
+ qPrintable(var.toQString()),
+ qPrintable(formatValue(*it)));
+ ret = false;
+ }
+ } else {
+ if (!vmap) {
+ qWarning("Value of %s is incorrect.\n Actual: <UNDEFINED>\nExpected:%s",
+ qPrintable(var.toQString()),
+ qPrintable(formatValue(value)));
+ ret = false;
+ } else if (*it != value) {
+ qWarning("Value of %s is incorrect.\n Actual:%s\nExpected:%s",
+ qPrintable(var.toQString()),
+ qPrintable(formatValue(*it)), qPrintable(formatValue(value)));
+ ret = false;
+ }
+ }
+ }
+ return ret;
+}
+
+void tst_qmakelib::proEval()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+ QFETCH(QString, msgs);
+ QFETCH(bool, ok);
+
+ QString infile = m_indir + "/test.pro";
+ bool verified = true;
+ QMakeTestHandler handler;
+ handler.setExpectedMessages(msgs.replace("##:", infile + ':').split('\n', QString::SkipEmptyParts));
+ QMakeVfs vfs;
+ QMakeParser parser(0, &vfs, &handler);
+ QMakeGlobals globals;
+ globals.do_cache = false;
+ globals.xqmakespec = "fake-g++";
+ globals.environment = m_env;
+ globals.setProperties(m_prop);
+ globals.setDirectories(m_indir, m_outdir);
+ ProFile *outPro = parser.parsedProBlock(out, "out", 1, QMakeParser::FullGrammar);
+ if (!outPro->isOk()) {
+ qWarning("Expected output is malformed");
+ verified = false;
+ }
+ ProFile *pro = parser.parsedProBlock(in, infile, 1, QMakeParser::FullGrammar);
+ QMakeEvaluator visitor(&globals, &parser, &vfs, &handler);
+ visitor.setOutputDir(m_outdir);
+#ifdef Q_OS_WIN
+ visitor.m_dirSep = ProString("\\");
+#else
+ visitor.m_dirSep = ProString("/");
+#endif
+ QMakeEvaluator::VisitReturn ret
+ = visitor.visitProFile(pro, QMakeHandler::EvalAuxFile, QMakeEvaluator::LoadProOnly);
+ if (handler.printedMessages()) {
+ qWarning("Got unexpected message(s)");
+ verified = false;
+ }
+ QStringList missingMsgs = handler.expectedMessages();
+ if (!missingMsgs.isEmpty()) {
+ foreach (const QString &msg, missingMsgs)
+ qWarning("Missing message: %s", qPrintable(msg));
+ verified = false;
+ }
+ if ((ret == QMakeEvaluator::ReturnTrue) != ok) {
+ static const char * const lbl[] = { "failure", "success" };
+ qWarning("Expected %s, got %s", lbl[int(ok)], lbl[1 - int(ok)]);
+ verified = false;
+ }
+ if (!compareState(&visitor, outPro))
+ verified = false;
+ pro->deref();
+ outPro->deref();
+ QVERIFY(verified);
+}
diff --git a/tests/auto/tools/qmakelib/parsertest.cpp b/tests/auto/tools/qmakelib/parsertest.cpp
new file mode 100644
index 0000000000..a7b7431a98
--- /dev/null
+++ b/tests/auto/tools/qmakelib/parsertest.cpp
@@ -0,0 +1,1987 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tst_qmakelib.h"
+
+#include <proitems.h>
+#include <qmakevfs.h>
+#include <qmakeparser.h>
+
+class TokenStream
+{
+public:
+ TokenStream() {}
+ QString toString() const { return ts; }
+
+ TokenStream &operator<<(ushort n) { ts += QChar(n); return *this; }
+ TokenStream &operator<<(uint n) { ts += QChar(n & 0xffff); ts += QChar(n >> 16); return *this; }
+ TokenStream &operator<<(const QStringRef &s) { ts += s; return *this; }
+ TokenStream &operator<<(const ProString &s) { return *this << ushort(s.length()) << s.toQStringRef(); }
+ TokenStream &operator<<(const ProKey &s) { return *this << s.hash() << s.toString(); }
+
+private:
+ QString ts;
+};
+
+#define TS(s) (TokenStream() s).toString()
+#define H(n) ushort(n)
+#define I(n) uint(n)
+#define S(s) ProString(QString::fromWCharArray(s))
+#define HS(s) ProKey(QString::fromWCharArray(s))
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4003) // "not enough actual parameters for macro TS()"
+
+void tst_qmakelib::addParseOperators()
+{
+ QTest::newRow("assign none")
+ << "VAR ="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAssign) << H(0)
+ /* 11 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("append none")
+ << "VAR +="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAppend) << H(0)
+ /* 11 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("unique append none")
+ << "VAR *="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAppendUnique) << H(0)
+ /* 11 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("remove none")
+ << "VAR -="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokRemove) << H(0)
+ /* 11 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("replace empty")
+ << "VAR ~="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokReplace) << H(0)
+ /* 11 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("assignment without variable")
+ << "="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokAssign) << H(0)
+ /* 4 */ << H(TokValueTerminator))
+ << "in:1: Assignment needs exactly one word on the left hand side."
+ << false;
+
+ QTest::newRow("assignment with multiple variables")
+ << "VAR VAR ="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokAssign) << H(0)
+ /* 4 */ << H(TokValueTerminator))
+ << "in:1: Assignment needs exactly one word on the left hand side."
+ << false;
+}
+
+void tst_qmakelib::addParseValues()
+{
+#define ASSIGN_VAR(h) \
+ H(TokLine) << H(1) \
+ << H(TokHashLiteral) << HS(L"VAR") \
+ << H(TokAssign) << H(h)
+
+ QTest::newRow("one literal")
+ << "VAR = val"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val")
+ /* 16 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("one literal (squeezed)")
+ << "VAR=val"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val")
+ /* 16 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("many literals")
+ << "VAR = foo barbaz bak hello"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(4)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+ /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
+ /* 29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
+ /* 36 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("many literals (tab-separated")
+ << "VAR\t=\tfoo\tbarbaz\tbak\thello"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(4)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+ /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
+ /* 29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
+ /* 36 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("one quoted literal")
+ << "VAR = \"val ue\""
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val ue")
+ /* 19 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("quoted literal with missing quote")
+ << "VAR = val \"ue"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAssign) << H(0)
+ /* 11 */ << H(TokValueTerminator))
+ << "in:1: Missing closing \" quote"
+ << false;
+
+ QTest::newRow("many quoted literals")
+ << "VAR = \"foo\" barbaz 'bak hello' \"\""
+ << TS(
+ /* 0 */ << ASSIGN_VAR(3)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+ /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak hello")
+ /* 35 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("many quoted literals (with tabs)")
+ << "VAR\t=\t\"foo\"\tbarbaz\t'bak\thello'"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(3)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
+ /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak\thello")
+ /* 35 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("quoted and unquoted spaces")
+ << " VAR = \"val ue \" "
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val ue ")
+ /* 22 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("funny literals")
+ << "VAR = foo:bar|!baz(blam!, ${foo})"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(2)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo:bar|!baz(blam!,")
+ /* 32 */ << H(TokLiteral | TokNewStr) << S(L"${foo})")
+ /* 41 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("literals with escapes")
+ << "VAR = \\{hi\\} \\[ho\\] \\)uh\\( \"\\\\oh\\$\"\\' \\$\\${FOO}"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(5)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"{hi}")
+ /* 17 */ << H(TokLiteral | TokNewStr) << S(L"[ho]")
+ /* 23 */ << H(TokLiteral | TokNewStr) << S(L")uh(")
+ /* 29 */ << H(TokLiteral | TokNewStr) << S(L"\\oh$'")
+ /* 36 */ << H(TokLiteral | TokNewStr) << S(L"$${FOO}")
+ /* 45 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("magic variables")
+ << "VAR = $$LITERAL_HASH $$LITERAL_DOLLAR $$LITERAL_WHITESPACE $$_FILE_ $$_LINE_"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(5)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"#")
+ /* 14 */ << H(TokLiteral | TokNewStr) << S(L"$")
+ /* 17 */ << H(TokLiteral | TokNewStr) << S(L"\t")
+ /* 20 */ << H(TokLiteral | TokNewStr) << S(L"in")
+ /* 24 */ << H(TokLiteral | TokNewStr) << S(L"1")
+ /* 27 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("continuations and comments")
+ << "VAR = foo \\\n bar\n \n"
+ "GAR = foo \\ # comment\n bar \\\n # comment\n baz \\\n"
+ "\"quoted \\ #comment\n escape\" \\\n right\\\n after \\\n gorilla!\n \n\n"
+ "MOO = \\\n kuh # comment\nLOO =\n\n"
+ "FOO = bar \\\n# comment\n baz \\\n \n# comment\n"
+ "GAZ="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAssign) << H(2)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+ /* 21 */ << H(TokValueTerminator)
+ /* 22 */ << H(TokLine) << H(4)
+ /* 24 */ << H(TokHashLiteral) << HS(L"GAR")
+ /* 31 */ << H(TokAssign) << H(7)
+ /* 33 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 38 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+ /* 43 */ << H(TokLiteral | TokNewStr) << S(L"baz")
+ /* 48 */ << H(TokLiteral | TokNewStr) << S(L"quoted escape")
+ /* 64 */ << H(TokLiteral | TokNewStr) << S(L"right")
+ /* 71 */ << H(TokLiteral | TokNewStr) << S(L"after")
+ /* 78 */ << H(TokLiteral | TokNewStr) << S(L"gorilla!")
+ /* 88 */ << H(TokValueTerminator)
+ /* 89 */ << H(TokLine) << H(15)
+ /* 91 */ << H(TokHashLiteral) << HS(L"MOO")
+ /* 98 */ << H(TokAssign) << H(0)
+ /* 100 */ << H(TokLiteral | TokNewStr) << S(L"kuh")
+ /* 105 */ << H(TokValueTerminator)
+ /* 106 */ << H(TokLine) << H(17)
+ /* 108 */ << H(TokHashLiteral) << HS(L"LOO")
+ /* 115 */ << H(TokAssign) << H(0)
+ /* 117 */ << H(TokValueTerminator)
+ /* 118 */ << H(TokLine) << H(19)
+ /* 120 */ << H(TokHashLiteral) << HS(L"FOO")
+ /* 127 */ << H(TokAssign) << H(2)
+ /* 129 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+ /* 134 */ << H(TokLiteral | TokNewStr) << S(L"baz")
+ /* 139 */ << H(TokValueTerminator)
+ /* 140 */ << H(TokLine) << H(24)
+ /* 142 */ << H(TokHashLiteral) << HS(L"GAZ")
+ /* 149 */ << H(TokAssign) << H(0)
+ /* 151 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("accidental continuation")
+ << "VAR0 = \\\n this \\\n is \\\n ok\n"
+ "VAR1 = \\\n this \\\n is=still \\\n ok\n"
+ "VAR2 = \\\n this \\\n is \\\n"
+ "VAR3 = \\\n not ok\n"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR0")
+ /* 10 */ << H(TokAssign) << H(3)
+ /* 12 */ << H(TokLiteral | TokNewStr) << S(L"this")
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"is")
+ /* 22 */ << H(TokLiteral | TokNewStr) << S(L"ok")
+ /* 26 */ << H(TokValueTerminator)
+ /* 27 */ << H(TokLine) << H(5)
+ /* 29 */ << H(TokHashLiteral) << HS(L"VAR1")
+ /* 37 */ << H(TokAssign) << H(3)
+ /* 39 */ << H(TokLiteral | TokNewStr) << S(L"this")
+ /* 45 */ << H(TokLiteral | TokNewStr) << S(L"is=still")
+ /* 55 */ << H(TokLiteral | TokNewStr) << S(L"ok")
+ /* 59 */ << H(TokValueTerminator)
+ /* 60 */ << H(TokLine) << H(9)
+ /* 62 */ << H(TokHashLiteral) << HS(L"VAR2")
+ /* 70 */ << H(TokAssign) << H(6)
+ /* 72 */ << H(TokLiteral | TokNewStr) << S(L"this")
+ /* 78 */ << H(TokLiteral | TokNewStr) << S(L"is")
+ /* 82 */ << H(TokLiteral | TokNewStr) << S(L"VAR3")
+ /* 88 */ << H(TokLiteral | TokNewStr) << S(L"=")
+ /* 91 */ << H(TokLiteral | TokNewStr) << S(L"not")
+ /* 96 */ << H(TokLiteral | TokNewStr) << S(L"ok")
+ /* 100 */ << H(TokValueTerminator))
+ << "WARNING: in:12: Possible accidental line continuation"
+ << true;
+
+ QTest::newRow("plain variable expansion")
+ << "VAR = $$bar"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("braced variable expansion")
+ << "VAR = $${foo/bar}"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"foo/bar")
+ /* 22 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("bogus variable expansion")
+ << "VAR = $$ "
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"")
+ /* 15 */ << H(TokValueTerminator))
+ << "WARNING: in:1: Missing name in expansion"
+ << true;
+
+ QTest::newRow("bogus braced variable expansion")
+ << "VAR = $${}"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"")
+ /* 15 */ << H(TokValueTerminator))
+ << "WARNING: in:1: Missing name in expansion"
+ << true;
+
+ QTest::newRow("unterminated braced variable expansion")
+ << "VAR = $${FOO"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAssign) << H(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"FOO")
+ /* 18 */ << H(TokValueTerminator))
+ << "in:1: Missing } terminator [found end-of-line]"
+ << false;
+
+ QTest::newRow("invalid identifier in braced variable expansion")
+ << "VAR = $${FOO/BAR+BAZ}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAssign) << H(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"FOO/BAR")
+ /* 22 */ << H(TokLiteral) << S(L"+BAZ")
+ /* 28 */ << H(TokValueTerminator))
+ << "in:1: Missing } terminator [found +]"
+ << false;
+
+ QTest::newRow("property expansion")
+ << "VAR = $$[bar]"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokProperty | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("environment expansion")
+ << "VAR = $$(bar)"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokEnvVar | TokNewStr) << S(L"bar")
+ /* 16 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("plain function call")
+ << "VAR = $$bar()"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokFuncTerminator)
+ /* 19 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("braced function call")
+ << "VAR = $${bar()}"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokFuncTerminator)
+ /* 19 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("function call with one argument")
+ << "VAR = $$bar(blubb)"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
+ /* 25 */ << H(TokFuncTerminator)
+ /* 26 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("function call with multiple arguments")
+ << "VAR = $$bar( blubb blubb, hey ,$$you)"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
+ /* 25 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
+ /* 32 */ << H(TokArgSeparator)
+ /* 33 */ << H(TokLiteral | TokNewStr) << S(L"hey")
+ /* 38 */ << H(TokArgSeparator)
+ /* 39 */ << H(TokVariable | TokNewStr) << HS(L"you")
+ /* 46 */ << H(TokFuncTerminator)
+ /* 47 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("nested function call")
+ << "VAR = $$foo(yo, $$bar(blubb))"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"foo")
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"yo")
+ /* 22 */ << H(TokArgSeparator)
+ /* 23 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+ /* 30 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
+ /* 37 */ << H(TokFuncTerminator)
+ /* 38 */ << H(TokFuncTerminator)
+ /* 39 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ // This is a rather questionable "feature"
+ QTest::newRow("function call with parenthesized argument")
+ << "VAR = $$bar(blubb (yo, man) blabb, nope)"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
+ /* 25 */ << H(TokLiteral | TokNewStr) << S(L"(yo,")
+ /* 31 */ << H(TokLiteral | TokNewStr) << S(L"man)")
+ /* 37 */ << H(TokLiteral | TokNewStr) << S(L"blabb")
+ /* 44 */ << H(TokArgSeparator)
+ /* 45 */ << H(TokLiteral | TokNewStr) << S(L"nope")
+ /* 51 */ << H(TokFuncTerminator)
+ /* 52 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("separate literal and expansion")
+ << "VAR = foo $$bar"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(2)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+ /* 23 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("separate expansion and literal")
+ << "VAR = $$bar foo"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 23 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("joined literal and expansion")
+ << "VAR = foo$$bar"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokVariable) << HS(L"bar")
+ /* 23 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("joined expansion and literal")
+ << "VAR = $${bar}foo"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
+ /* 18 */ << H(TokLiteral) << S(L"foo")
+ /* 23 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("plain variable expansion with funny name and literal")
+ << "VAR = $$az_AZ_09.dot/nix"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot")
+ /* 27 */ << H(TokLiteral) << S(L"/nix")
+ /* 33 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("braced variable expansion with funny name")
+ << "VAR = $${az_AZ_09.dot/nix}"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot/nix")
+ /* 31 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("quoted joined literal and expansion")
+ << "VAR = 'foo$$bar'"
+ << TS(
+ /* 0 */ << ASSIGN_VAR(0)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 16 */ << H(TokVariable | TokQuoted) << HS(L"bar")
+ /* 23 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("assignment with expansion in variable name")
+ << "VAR$$EXTRA ="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokVariable) << HS(L"EXTRA")
+ /* 18 */ << H(TokAssign) << H(0)
+ /* 20 */ << H(TokValueTerminator))
+ << ""
+ << true;
+}
+
+void tst_qmakelib::addParseConditions()
+{
+ QTest::newRow("one test")
+ << "foo"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("wildcard-test")
+ << "foo-*"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo-*")
+ /* 11 */ << H(TokCondition))
+ << ""
+ << true;
+
+ // This is a rather questionable "feature"
+ QTest::newRow("one quoted test")
+ << "\"foo\""
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("two tests")
+ << "foo\nbar"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokLine) << H(2)
+ /* 12 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 19 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("bogus two tests")
+ << "foo bar\nbaz"
+ << TS()
+ << "in:1: Extra characters after test expression."
+ << false;
+
+ QTest::newRow("test-AND-test")
+ << "foo:bar"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokAnd)
+ /* 11 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 18 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("test-OR-test")
+ << " foo | bar "
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokOr)
+ /* 11 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 18 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("NOT-test")
+ << "!foo"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokNot)
+ /* 3 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 10 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("NOT-NOT-test")
+ << "!!foo"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition))
+ << ""
+ << true;
+
+ // This is a rather questionable "feature"
+ QTest::newRow("quoted-NOT-test")
+ << "\"!foo\""
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokNot)
+ /* 3 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 10 */ << H(TokCondition))
+ << ""
+ << true;
+
+ // This is a rather questionable "feature"
+ QTest::newRow("NOT-quoted-test")
+ << "!\"foo\""
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokNot)
+ /* 3 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 10 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("test-AND-NOT-test")
+ << "foo:!bar"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokAnd)
+ /* 11 */ << H(TokNot)
+ /* 12 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 19 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("test-assignment")
+ << "foo\nVAR="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokLine) << H(2)
+ /* 12 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 19 */ << H(TokAssign) << H(0)
+ /* 21 */ << H(TokValueTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-AND-assignment")
+ << "foo: VAR ="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokBranch)
+ /* 11 */ /* then branch */ << I(11)
+ /* 13 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 20 */ << H(TokAssign) << H(0)
+ /* 22 */ << H(TokValueTerminator)
+ /* 23 */ << H(TokTerminator)
+ /* 24 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test-else-test")
+ << "foo\nelse: bar"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokBranch)
+ /* 11 */ /* then branch */ << I(0)
+ /* 13 */ /* else branch */ << I(11)
+ /* 15 */ << H(TokLine) << H(2)
+ /* 17 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 24 */ << H(TokCondition)
+ /* 25 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("function-else-test")
+ << "foo()\nelse: bar"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokFuncTerminator)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(0)
+ /* 14 */ /* else branch */ << I(11)
+ /* 16 */ << H(TokLine) << H(2)
+ /* 18 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 25 */ << H(TokCondition)
+ /* 26 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-AND-test-else-test")
+ << "foo:bar\nelse: baz"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokAnd)
+ /* 11 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 18 */ << H(TokCondition)
+ /* 19 */ << H(TokBranch)
+ /* 20 */ /* then branch */ << I(0)
+ /* 22 */ /* else branch */ << I(11)
+ /* 24 */ << H(TokLine) << H(2)
+ /* 26 */ << H(TokHashLiteral) << HS(L"baz")
+ /* 33 */ << H(TokCondition)
+ /* 34 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-AND-test-else-test-else-test-function")
+ << "foo:bar\nelse: baz\nelse: bak\nbuzz()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokAnd)
+ /* 11 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 18 */ << H(TokCondition)
+ /* 19 */ << H(TokBranch)
+ /* 20 */ /* then branch */ << I(0)
+ /* 22 */ /* else branch */ << I(27)
+ /* 24 */ << H(TokLine) << H(2)
+ /* 26 */ << H(TokHashLiteral) << HS(L"baz")
+ /* 33 */ << H(TokCondition)
+ /* 34 */ << H(TokBranch)
+ /* 35 */ /* then branch */ << I(0)
+ /* 37 */ /* else branch */ << I(11)
+ /* 39 */ << H(TokLine) << H(3)
+ /* 41 */ << H(TokHashLiteral) << HS(L"bak")
+ /* 48 */ << H(TokCondition)
+ /* 49 */ << H(TokTerminator)
+ /* 50 */ << H(TokTerminator)
+ /* 51 */ << H(TokLine) << H(4)
+ /* 53 */ << H(TokHashLiteral) << HS(L"buzz")
+ /* 61 */ << H(TokTestCall)
+ /* 62 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-assignment-else-assignment")
+ << "foo: VAR =\nelse: VAR="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokBranch)
+ /* 11 */ /* then branch */ << I(11)
+ /* 13 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 20 */ << H(TokAssign) << H(0)
+ /* 22 */ << H(TokValueTerminator)
+ /* 23 */ << H(TokTerminator)
+ /* 24 */ /* else branch */ << I(13)
+ /* 26 */ << H(TokLine) << H(2)
+ /* 28 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 35 */ << H(TokAssign) << H(0)
+ /* 37 */ << H(TokValueTerminator)
+ /* 38 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-else-test-assignment")
+ << "foo\nelse: bar: VAR ="
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokBranch)
+ /* 11 */ /* then branch */ << I(0)
+ /* 13 */ /* else branch */ << I(27)
+ /* 15 */ << H(TokLine) << H(2)
+ /* 17 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 24 */ << H(TokCondition)
+ /* 25 */ << H(TokBranch)
+ /* 26 */ /* then branch */ << I(11)
+ /* 28 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 35 */ << H(TokAssign) << H(0)
+ /* 37 */ << H(TokValueTerminator)
+ /* 38 */ << H(TokTerminator)
+ /* 39 */ /* else branch */ << I(0)
+ /* 41 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("one function")
+ << "foo()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("one function (with spaces)")
+ << " foo( ) "
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("unterminated function call")
+ << "foo(\nfoo"
+ << TS()
+ << "in:1: Missing closing parenthesis in function call"
+ << false;
+
+ QTest::newRow("function with arguments")
+ << "foo(blah, hi ho)"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokLiteral | TokNewStr) << S(L"blah")
+ /* 16 */ << H(TokArgSeparator)
+ /* 17 */ << H(TokLiteral | TokNewStr) << S(L"hi")
+ /* 21 */ << H(TokLiteral | TokNewStr) << S(L"ho")
+ /* 25 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("function with empty arguments")
+ << "foo(,)"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokArgSeparator)
+ /* 11 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("function with funny arguments")
+ << "foo(blah\\, \"hi , \\ho\" ,uh\\ ,\\oh ,, )"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokLiteral | TokNewStr) << S(L"blah\\")
+ /* 17 */ << H(TokArgSeparator)
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"hi , \\ho")
+ /* 29 */ << H(TokArgSeparator)
+ /* 30 */ << H(TokLiteral | TokNewStr) << S(L"uh\\")
+ /* 35 */ << H(TokArgSeparator)
+ /* 36 */ << H(TokLiteral | TokNewStr) << S(L"\\oh")
+ /* 41 */ << H(TokArgSeparator)
+ /* 42 */ << H(TokArgSeparator)
+ /* 43 */ << H(TokFuncTerminator))
+ << "WARNING: in:1: Unescaped backslashes are deprecated\n"
+ "WARNING: in:1: Unescaped backslashes are deprecated\n"
+ "WARNING: in:1: Unescaped backslashes are deprecated\n"
+ "WARNING: in:1: Unescaped backslashes are deprecated"
+ << true;
+
+ QTest::newRow("function with nested call")
+ << "foo($$blah(hi ho))"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokFuncName | TokNewStr) << HS(L"blah")
+ /* 18 */ << H(TokLiteral | TokNewStr) << S(L"hi")
+ /* 22 */ << H(TokLiteral | TokNewStr) << S(L"ho")
+ /* 26 */ << H(TokFuncTerminator)
+ /* 27 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("stand-alone parentheses")
+ << "()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestCall)
+ /* 3 */ << H(TokFuncTerminator))
+ << "in:1: Opening parenthesis without prior test name."
+ << false;
+
+ QTest::newRow("bogus test and function")
+ << "foo bar()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestCall)
+ /* 3 */ << H(TokFuncTerminator))
+ << "in:1: Extra characters after test expression."
+ << false;
+
+ // This is a rather questionable "feature"
+ QTest::newRow("two functions")
+ << "foo() bar()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokFuncTerminator)
+ /* 11 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 18 */ << H(TokTestCall)
+ /* 19 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("function-AND-test")
+ << "foo():bar"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokTestCall)
+ /* 10 */ << H(TokFuncTerminator)
+ /* 11 */ << H(TokAnd)
+ /* 12 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 19 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("test-AND-function")
+ << "foo:bar()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokAnd)
+ /* 11 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 18 */ << H(TokTestCall)
+ /* 19 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("NOT-function-AND-test")
+ << "!foo():bar"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokNot)
+ /* 3 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 10 */ << H(TokTestCall)
+ /* 11 */ << H(TokFuncTerminator)
+ /* 12 */ << H(TokAnd)
+ /* 13 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 20 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("test-AND-NOT-function")
+ << "foo:!bar()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"foo")
+ /* 9 */ << H(TokCondition)
+ /* 10 */ << H(TokAnd)
+ /* 11 */ << H(TokNot)
+ /* 12 */ << H(TokHashLiteral) << HS(L"bar")
+ /* 19 */ << H(TokTestCall)
+ /* 20 */ << H(TokFuncTerminator))
+ << ""
+ << true;
+}
+
+void tst_qmakelib::addParseControlStatements()
+{
+ QTest::newRow("for(VAR, LIST) loop")
+ << "for(VAR, LIST)"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"VAR")
+ /* 9 */ /* iterator */ << I(7)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
+ /* 17 */ << H(TokValueTerminator)
+ /* 18 */ /* body */ << I(1)
+ /* 20 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("for(ever) loop")
+ << "for(ever)"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"")
+ /* 6 */ /* iterator */ << I(9)
+ /* 8 */ << H(TokHashLiteral) << HS(L"ever")
+ /* 16 */ << H(TokValueTerminator)
+ /* 17 */ /* body */ << I(1)
+ /* 19 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ // This is a rather questionable "feature"
+ QTest::newRow("for($$blub) loop")
+ << "for($$blub)"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"")
+ /* 6 */ /* iterator */ << I(9)
+ /* 8 */ << H(TokVariable | TokNewStr) << HS(L"blub")
+ /* 16 */ << H(TokValueTerminator)
+ /* 17 */ /* body */ << I(1)
+ /* 19 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-for-test-else-test")
+ << "true:for(VAR, LIST): true\nelse: true"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(31)
+ /* 14 */ << H(TokForLoop) << HS(L"VAR")
+ /* 21 */ /* iterator */ << I(7)
+ /* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
+ /* 29 */ << H(TokValueTerminator)
+ /* 30 */ /* body */ << I(12)
+ /* 32 */ << H(TokLine) << H(1)
+ /* 34 */ << H(TokHashLiteral) << HS(L"true")
+ /* 42 */ << H(TokCondition)
+ /* 43 */ << H(TokTerminator)
+ /* 44 */ << H(TokTerminator)
+ /* 45 */ /* else branch */ << I(12)
+ /* 47 */ << H(TokLine) << H(2)
+ /* 49 */ << H(TokHashLiteral) << HS(L"true")
+ /* 57 */ << H(TokCondition)
+ /* 58 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("next()")
+ << "for(ever): next()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"")
+ /* 6 */ /* iterator */ << I(9)
+ /* 8 */ << H(TokHashLiteral) << HS(L"ever")
+ /* 16 */ << H(TokValueTerminator)
+ /* 17 */ /* body */ << I(4)
+ /* 19 */ << H(TokLine) << H(1)
+ /* 21 */ << H(TokNext)
+ /* 22 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("break()")
+ << "for(ever): break()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"")
+ /* 6 */ /* iterator */ << I(9)
+ /* 8 */ << H(TokHashLiteral) << HS(L"ever")
+ /* 16 */ << H(TokValueTerminator)
+ /* 17 */ /* body */ << I(4)
+ /* 19 */ << H(TokLine) << H(1)
+ /* 21 */ << H(TokBreak)
+ /* 22 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("top-level return()")
+ << "return()"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokReturn))
+ << ""
+ << true;
+
+ QTest::newRow("else")
+ << "else"
+ << TS()
+ << "in:1: Unexpected 'else'."
+ << false;
+
+ QTest::newRow("test-{else}")
+ << "test { else }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(1)
+ /* 14 */ << H(TokTerminator)
+ /* 15 */ /* else branch */ << I(0))
+ << "in:1: Unexpected 'else'."
+ << false;
+
+ QTest::newRow("defineTest-{else}")
+ << "defineTest(fn) { else }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestDef) << HS(L"fn")
+ /* 8 */ /* body */ << I(1)
+ /* 10 */ << H(TokTerminator))
+ << "in:1: Unexpected 'else'."
+ << false;
+
+ QTest::newRow("for-else")
+ << "for(ever) { else }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"")
+ /* 6 */ /* iterator */ << I(9)
+ /* 8 */ << H(TokHashLiteral) << HS(L"ever")
+ /* 16 */ << H(TokValueTerminator)
+ /* 17 */ /* body */ << I(1)
+ /* 19 */ << H(TokTerminator))
+ << "in:1: Unexpected 'else'."
+ << false;
+
+ QTest::newRow("double-test-else")
+ << "foo bar\nelse"
+ << TS(
+ /* 0 */ << H(TokBranch)
+ /* 1 */ /* then branch */ << I(0)
+ /* 3 */ /* else branch */ << I(1) // This seems weird
+ /* 5 */ << H(TokTerminator))
+ << "in:1: Extra characters after test expression."
+ << false;
+
+ QTest::newRow("test-function-else")
+ << "foo bar()\nelse"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestCall) // This seems pointless
+ /* 3 */ << H(TokFuncTerminator)
+ /* 4 */ << H(TokBranch)
+ /* 5 */ /* then branch */ << I(0)
+ /* 7 */ /* else branch */ << I(1) // This seems weird
+ /* 9 */ << H(TokTerminator))
+ << "in:1: Extra characters after test expression."
+ << false;
+}
+
+void tst_qmakelib::addParseBraces()
+{
+ QTest::newRow("{}")
+ << "{ }"
+ << TS()
+ << ""
+ << true;
+
+ QTest::newRow("{}-newlines")
+ << "\n\n{ }\n\n"
+ << TS()
+ << ""
+ << true;
+
+ QTest::newRow("{")
+ << "{"
+ << TS()
+ << "in:2: Missing closing brace(s)."
+ << false;
+
+ QTest::newRow("test {")
+ << "test {"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(1)
+ /* 14 */ << H(TokTerminator)
+ /* 15 */ /* else branch */ << I(0))
+ << "in:2: Missing closing brace(s)."
+ << false;
+
+ QTest::newRow("}")
+ << "}"
+ << TS()
+ << "in:1: Excess closing brace."
+ << false;
+
+ QTest::newRow("{test}")
+ << "{ true }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("{test-newlines}")
+ << "{\ntrue\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(2)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("{assignment-test}-test")
+ << "{ VAR = { foo } bar } true"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAssign) << H(4)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"{")
+ /* 14 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 19 */ << H(TokLiteral | TokNewStr) << S(L"}")
+ /* 22 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+ /* 27 */ << H(TokValueTerminator)
+ /* 28 */ << H(TokHashLiteral) << HS(L"true")
+ /* 36 */ << H(TokCondition))
+ << ""
+ << true;
+
+ QTest::newRow("assignment with excess opening brace")
+ << "VAR = { { foo }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 9 */ << H(TokAssign) << H(4)
+ /* 11 */ << H(TokLiteral | TokNewStr) << S(L"{")
+ /* 14 */ << H(TokLiteral | TokNewStr) << S(L"{")
+ /* 17 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 22 */ << H(TokLiteral | TokNewStr) << S(L"}")
+ /* 25 */ << H(TokValueTerminator))
+ << "WARNING: in:1: Possible braces mismatch"
+ << true;
+
+ QTest::newRow("test-{}")
+ << "true {}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(1)
+ /* 14 */ << H(TokTerminator)
+ /* 15 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test-{newlines}")
+ << "true {\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(1)
+ /* 14 */ << H(TokTerminator)
+ /* 15 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test-{test}")
+ << "true { true }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(10)
+ /* 14 */ << H(TokHashLiteral) << HS(L"true")
+ /* 22 */ << H(TokCondition)
+ /* 23 */ << H(TokTerminator)
+ /* 24 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test:-{test}")
+ << "true: { true }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(10)
+ /* 14 */ << H(TokHashLiteral) << HS(L"true")
+ /* 22 */ << H(TokCondition)
+ /* 23 */ << H(TokTerminator)
+ /* 24 */ /* else branch */ << I(0))
+ << "WARNING: in:1: Excess colon in front of opening brace."
+ << true;
+
+ QTest::newRow("test-{test-newlines}")
+ << "true {\ntrue\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(12)
+ /* 14 */ << H(TokLine) << H(2)
+ /* 16 */ << H(TokHashLiteral) << HS(L"true")
+ /* 24 */ << H(TokCondition)
+ /* 25 */ << H(TokTerminator)
+ /* 26 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test:-{test-newlines}")
+ << "true: {\ntrue\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(12)
+ /* 14 */ << H(TokLine) << H(2)
+ /* 16 */ << H(TokHashLiteral) << HS(L"true")
+ /* 24 */ << H(TokCondition)
+ /* 25 */ << H(TokTerminator)
+ /* 26 */ /* else branch */ << I(0))
+ << "WARNING: in:1: Excess colon in front of opening brace."
+ << true;
+
+ QTest::newRow("test-{assignment}")
+ << "true { VAR = {foo} }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(18)
+ /* 14 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 21 */ << H(TokAssign) << H(0)
+ /* 23 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
+ /* 30 */ << H(TokValueTerminator)
+ /* 31 */ << H(TokTerminator)
+ /* 32 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test-{test-assignment}")
+ << "true { true: VAR = {foo} }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(33)
+ /* 14 */ << H(TokHashLiteral) << HS(L"true")
+ /* 22 */ << H(TokCondition)
+ /* 23 */ << H(TokBranch)
+ /* 24 */ /* then branch */ << I(18)
+ /* 26 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 33 */ << H(TokAssign) << H(0)
+ /* 35 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
+ /* 42 */ << H(TokValueTerminator)
+ /* 43 */ << H(TokTerminator)
+ /* 44 */ /* else branch */ << I(0)
+ /* 46 */ << H(TokTerminator)
+ /* 47 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test-{assignment-newlines}")
+ << "true {\nVAR = {foo}\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(20)
+ /* 14 */ << H(TokLine) << H(2)
+ /* 16 */ << H(TokHashLiteral) << HS(L"VAR")
+ /* 23 */ << H(TokAssign) << H(0)
+ /* 25 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
+ /* 32 */ << H(TokValueTerminator)
+ /* 33 */ << H(TokTerminator)
+ /* 34 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test-{}-else-test-{}")
+ << "true {} else: true {}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(1)
+ /* 14 */ << H(TokTerminator)
+ /* 15 */ /* else branch */ << I(18)
+ /* 17 */ << H(TokLine) << H(1)
+ /* 19 */ << H(TokHashLiteral) << HS(L"true")
+ /* 27 */ << H(TokCondition)
+ /* 28 */ << H(TokBranch)
+ /* 29 */ /* then branch */ << I(1)
+ /* 31 */ << H(TokTerminator)
+ /* 32 */ /* else branch */ << I(0)
+ /* 34 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-{}-else-test-{}-newlines")
+ << "true {\n}\nelse: true {\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(1)
+ /* 14 */ << H(TokTerminator)
+ /* 15 */ /* else branch */ << I(18)
+ /* 17 */ << H(TokLine) << H(3)
+ /* 19 */ << H(TokHashLiteral) << HS(L"true")
+ /* 27 */ << H(TokCondition)
+ /* 28 */ << H(TokBranch)
+ /* 29 */ /* then branch */ << I(1)
+ /* 31 */ << H(TokTerminator)
+ /* 32 */ /* else branch */ << I(0)
+ /* 34 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-{test}-else-test-{}-newlines")
+ << "true {\ntrue\n}\nelse: true {\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(12)
+ /* 14 */ << H(TokLine) << H(2)
+ /* 16 */ << H(TokHashLiteral) << HS(L"true")
+ /* 24 */ << H(TokCondition)
+ /* 25 */ << H(TokTerminator)
+ /* 26 */ /* else branch */ << I(18)
+ /* 28 */ << H(TokLine) << H(4)
+ /* 30 */ << H(TokHashLiteral) << HS(L"true")
+ /* 38 */ << H(TokCondition)
+ /* 39 */ << H(TokBranch)
+ /* 40 */ /* then branch */ << I(1)
+ /* 42 */ << H(TokTerminator)
+ /* 43 */ /* else branch */ << I(0)
+ /* 45 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("for-{next}")
+ << "for(ever) { next() }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"")
+ /* 6 */ /* iterator */ << I(9)
+ /* 8 */ << H(TokHashLiteral) << HS(L"ever")
+ /* 16 */ << H(TokValueTerminator)
+ /* 17 */ /* body */ << I(4)
+ /* 19 */ << H(TokLine) << H(1)
+ /* 21 */ << H(TokNext)
+ /* 22 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("for:-{next}")
+ << "for(ever): { next() }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokForLoop) << HS(L"")
+ /* 6 */ /* iterator */ << I(9)
+ /* 8 */ << H(TokHashLiteral) << HS(L"ever")
+ /* 16 */ << H(TokValueTerminator)
+ /* 17 */ /* body */ << I(4)
+ /* 19 */ << H(TokLine) << H(1)
+ /* 21 */ << H(TokNext)
+ /* 22 */ << H(TokTerminator))
+ << "WARNING: in:1: Excess colon in front of opening brace."
+ << true;
+
+ QTest::newRow("test-for-{test-else-test-newlines}")
+ << "true:for(VAR, LIST) {\ntrue\nelse: true\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(48)
+ /* 14 */ << H(TokForLoop) << HS(L"VAR")
+ /* 21 */ /* iterator */ << I(7)
+ /* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
+ /* 29 */ << H(TokValueTerminator)
+ /* 30 */ /* body */ << I(29)
+ /* 32 */ << H(TokLine) << H(2)
+ /* 34 */ << H(TokHashLiteral) << HS(L"true")
+ /* 42 */ << H(TokCondition)
+ /* 43 */ << H(TokBranch)
+ /* 44 */ /* then branch */ << I(0)
+ /* 46 */ /* else branch */ << I(12)
+ /* 48 */ << H(TokLine) << H(3)
+ /* 50 */ << H(TokHashLiteral) << HS(L"true")
+ /* 58 */ << H(TokCondition)
+ /* 59 */ << H(TokTerminator)
+ /* 60 */ << H(TokTerminator)
+ /* 61 */ << H(TokTerminator)
+ /* 62 */ /* else branch */ << I(0))
+ << ""
+ << true;
+
+ QTest::newRow("test-for-{test-else-test}")
+ << "true:for(VAR, LIST) { true\nelse: true }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"true")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(48)
+ /* 14 */ << H(TokForLoop) << HS(L"VAR")
+ /* 21 */ /* iterator */ << I(7)
+ /* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
+ /* 29 */ << H(TokValueTerminator)
+ /* 30 */ /* body */ << I(29)
+ /* 32 */ << H(TokLine) << H(1)
+ /* 34 */ << H(TokHashLiteral) << HS(L"true")
+ /* 42 */ << H(TokCondition)
+ /* 43 */ << H(TokBranch)
+ /* 44 */ /* then branch */ << I(0)
+ /* 46 */ /* else branch */ << I(12)
+ /* 48 */ << H(TokLine) << H(2)
+ /* 50 */ << H(TokHashLiteral) << HS(L"true")
+ /* 58 */ << H(TokCondition)
+ /* 59 */ << H(TokTerminator)
+ /* 60 */ << H(TokTerminator)
+ /* 61 */ << H(TokTerminator)
+ /* 62 */ /* else branch */ << I(0))
+ << ""
+ << true;
+}
+
+void tst_qmakelib::addParseCustomFunctions()
+{
+ QTest::newRow("defineTest-{newlines}")
+ << "defineTest(test) {\n}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestDef) << HS(L"test")
+ /* 10 */ /* body */ << I(1)
+ /* 12 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("defineTest:-test")
+ << "defineTest(test): test"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestDef) << HS(L"test")
+ /* 10 */ /* body */ << I(12)
+ /* 12 */ << H(TokLine) << H(1)
+ /* 14 */ << H(TokHashLiteral) << HS(L"test")
+ /* 22 */ << H(TokCondition)
+ /* 23 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("defineTest-{test}")
+ << "defineTest(test) { test }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestDef) << HS(L"test")
+ /* 10 */ /* body */ << I(12)
+ /* 12 */ << H(TokLine) << H(1)
+ /* 14 */ << H(TokHashLiteral) << HS(L"test")
+ /* 22 */ << H(TokCondition)
+ /* 23 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("defineTest-{return}")
+ << "defineTest(test) { return() }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokTestDef) << HS(L"test")
+ /* 10 */ /* body */ << I(4)
+ /* 12 */ << H(TokLine) << H(1)
+ /* 14 */ << H(TokReturn)
+ /* 15 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("defineReplace-{return-stuff}")
+ << "defineReplace(stuff) { return(foo bar) }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokReplaceDef) << HS(L"stuff")
+ /* 11 */ /* body */ << I(14)
+ /* 13 */ << H(TokLine) << H(1)
+ /* 15 */ << H(TokLiteral | TokNewStr) << S(L"foo")
+ /* 20 */ << H(TokLiteral | TokNewStr) << S(L"bar")
+ /* 25 */ << H(TokReturn)
+ /* 26 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-AND-defineTest-{}")
+ << "test: defineTest(test) {}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokAnd)
+ /* 12 */ << H(TokTestDef) << HS(L"test")
+ /* 20 */ /* body */ << I(1)
+ /* 22 */ << H(TokTerminator))
+ << ""
+ << true;
+
+ QTest::newRow("test-OR-defineTest-{}")
+ << "test| defineTest(test) {}"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokOr)
+ /* 12 */ << H(TokTestDef) << HS(L"test")
+ /* 20 */ /* body */ << I(1)
+ /* 22 */ << H(TokTerminator))
+ << ""
+ << true;
+}
+
+void tst_qmakelib::addParseAbuse()
+{
+ QTest::newRow("!")
+ << ""
+ << TS()
+ << ""
+ << true;
+
+ QTest::newRow("|")
+ << ""
+ << TS()
+ << ""
+ << true;
+
+ QTest::newRow(":")
+ << ""
+ << TS()
+ << ""
+ << true;
+
+ QTest::newRow("NOT-assignment")
+ << "!VAR ="
+ << TS()
+ << "in:1: Unexpected NOT operator in front of assignment."
+ << false;
+
+ QTest::newRow("NOT-{}")
+ << "!{}"
+ << TS()
+ << "in:1: Unexpected NOT operator in front of opening brace."
+ << false;
+
+ QTest::newRow("NOT-else")
+ << "test\n!else {}"
+ << TS()
+ << "in:2: Unexpected NOT operator in front of else."
+ << false;
+
+ QTest::newRow("NOT-for-{}")
+ << "!for(ever) {}"
+ << TS()
+ << "in:1: Unexpected NOT operator in front of for()."
+ << false;
+
+ QTest::newRow("NOT-defineTest-{}")
+ << "!defineTest(test) {}"
+ << TS()
+ << "in:1: Unexpected NOT operator in front of function definition."
+ << false;
+
+ QTest::newRow("AND-test")
+ << ":test"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition))
+ << "in:1: AND operator without prior condition."
+ << false;
+
+ QTest::newRow("test-AND-else")
+ << "test:else"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition))
+ << "in:1: Unexpected AND operator in front of else."
+ << false;
+
+ QTest::newRow("test-AND-AND-test")
+ << "test::test"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokAnd)
+ /* 12 */ << H(TokHashLiteral) << HS(L"test")
+ /* 20 */ << H(TokCondition))
+ << "WARNING: in:1: Stray AND operator in front of AND operator."
+ << true;
+
+ QTest::newRow("test-AND-OR-test")
+ << "test:|test"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokOr)
+ /* 12 */ << H(TokHashLiteral) << HS(L"test")
+ /* 20 */ << H(TokCondition))
+ << "WARNING: in:1: Stray AND operator in front of OR operator."
+ << true;
+
+ QTest::newRow("test-{AND-test}")
+ << "test { :test }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(10)
+ /* 14 */ << H(TokHashLiteral) << HS(L"test")
+ /* 22 */ << H(TokCondition)
+ /* 23 */ << H(TokTerminator)
+ /* 24 */ /* else branch */ << I(0))
+ << "in:1: AND operator without prior condition."
+ << false;
+
+ QTest::newRow("test-OR-assignment")
+ << "foo| VAR ="
+ << TS()
+ << "in:1: Unexpected OR operator in front of assignment."
+ << false;
+
+ QTest::newRow("test-OR-{}")
+ << "foo|{}"
+ << TS()
+ << "in:1: Unexpected OR operator in front of opening brace."
+ << false;
+
+ QTest::newRow("test-OR-for")
+ << "foo|for(ever) {}"
+ << TS()
+ << "in:1: Unexpected OR operator in front of for()."
+ << false;
+
+ QTest::newRow("OR-test")
+ << "|test"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition))
+ << "in:1: OR operator without prior condition."
+ << false;
+
+ QTest::newRow("test-OR-else")
+ << "test|else"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition))
+ << "in:1: Unexpected OR operator in front of else."
+ << false;
+
+ QTest::newRow("test-OR-OR-test")
+ << "test||test"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokOr)
+ /* 12 */ << H(TokHashLiteral) << HS(L"test")
+ /* 20 */ << H(TokCondition))
+ << "WARNING: in:1: Stray OR operator in front of OR operator."
+ << true;
+
+ QTest::newRow("test-OR-AND-test")
+ << "test|:test"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokAnd)
+ /* 12 */ << H(TokHashLiteral) << HS(L"test")
+ /* 20 */ << H(TokCondition))
+ << "WARNING: in:1: Stray OR operator in front of AND operator."
+ << true;
+
+ QTest::newRow("test-{OR-test}")
+ << "test { |test }"
+ << TS(
+ /* 0 */ << H(TokLine) << H(1)
+ /* 2 */ << H(TokHashLiteral) << HS(L"test")
+ /* 10 */ << H(TokCondition)
+ /* 11 */ << H(TokBranch)
+ /* 12 */ /* then branch */ << I(10)
+ /* 14 */ << H(TokHashLiteral) << HS(L"test")
+ /* 22 */ << H(TokCondition)
+ /* 23 */ << H(TokTerminator)
+ /* 24 */ /* else branch */ << I(0))
+ << "in:1: OR operator without prior condition."
+ << false;
+}
+
+void tst_qmakelib::proParser_data()
+{
+ QTest::addColumn<QString>("in");
+ QTest::addColumn<QString>("out");
+ QTest::addColumn<QString>("msgs");
+ QTest::addColumn<bool>("ok");
+
+ QTest::newRow("empty")
+ << ""
+ << TS()
+ << ""
+ << true;
+
+ QTest::newRow("empty (whitespace)")
+ << " \t \t"
+ << TS()
+ << ""
+ << true;
+
+ addParseOperators(); // Variable operators
+
+ addParseValues();
+
+ addParseConditions(); // "Tests"
+
+ addParseControlStatements();
+
+ addParseBraces();
+
+ addParseCustomFunctions();
+
+ addParseAbuse(); // Mostly operator abuse
+
+ // option() (these produce no tokens)
+
+ QTest::newRow("option(host_build)")
+ << "option(host_build)"
+ << TS()
+ << ""
+ << true;
+
+ QTest::newRow("option()")
+ << "option()"
+ << TS()
+ << "in:1: option() requires one literal argument."
+ << false;
+
+ QTest::newRow("option(host_build magic)")
+ << "option(host_build magic)"
+ << TS()
+ << "in:1: option() requires one literal argument."
+ << false;
+
+ QTest::newRow("option(host_build, magic)")
+ << "option(host_build, magic)"
+ << TS()
+ << "in:1: option() requires one literal argument."
+ << false;
+
+ QTest::newRow("option($$OPTION)")
+ << "option($$OPTION)"
+ << TS()
+ << "in:1: option() requires one literal argument."
+ << false;
+
+ QTest::newRow("{option(host_build)}")
+ << "{option(host_build)}"
+ << TS()
+ << "in:1: option() must appear outside any control structures."
+ << false;
+}
+
+QT_WARNING_POP
+
+void tst_qmakelib::proParser()
+{
+ QFETCH(QString, in);
+ QFETCH(QString, out);
+ QFETCH(QString, msgs);
+ QFETCH(bool, ok);
+
+ bool verified = true;
+ QMakeTestHandler handler;
+ handler.setExpectedMessages(msgs.split('\n', QString::SkipEmptyParts));
+ QMakeVfs vfs;
+ QMakeParser parser(0, &vfs, &handler);
+ ProFile *pro = parser.parsedProBlock(in, "in", 1, QMakeParser::FullGrammar);
+ if (handler.printedMessages()) {
+ qWarning("Got unexpected message(s)");
+ verified = false;
+ }
+ QStringList missingMsgs = handler.expectedMessages();
+ if (!missingMsgs.isEmpty()) {
+ foreach (const QString &msg, missingMsgs)
+ qWarning("Missing message: %s", qPrintable(msg));
+ verified = false;
+ }
+ if (pro->isOk() != ok) {
+ static const char * const lbl[] = { "failure", "success" };
+ qWarning("Expected %s, got %s", lbl[int(ok)], lbl[1 - int(ok)]);
+ verified = false;
+ }
+ if (pro->items() != out && (ok || !out.isEmpty())) {
+ qWarning("Bytecode mismatch.\nActual:%s\nExpected:%s",
+ qPrintable(QMakeParser::formatProBlock(pro->items())),
+ qPrintable(QMakeParser::formatProBlock(out)));
+ verified = false;
+ }
+ pro->deref();
+ QVERIFY(verified);
+}
diff --git a/tests/auto/tools/qmakelib/qmakelib.pro b/tests/auto/tools/qmakelib/qmakelib.pro
index e7807838aa..f1b8dfef3d 100644
--- a/tests/auto/tools/qmakelib/qmakelib.pro
+++ b/tests/auto/tools/qmakelib/qmakelib.pro
@@ -6,11 +6,19 @@ QT = core testlib
INCLUDEPATH += ../../../../qmake/library
VPATH += ../../../../qmake/library
+HEADERS += \
+ tst_qmakelib.h
+
SOURCES += \
tst_qmakelib.cpp \
+ parsertest.cpp \
+ evaltest.cpp \
ioutils.cpp \
proitems.cpp \
qmakevfs.cpp \
- qmakeparser.cpp
+ qmakeparser.cpp \
+ qmakeglobals.cpp \
+ qmakebuiltins.cpp \
+ qmakeevaluator.cpp
-DEFINES += PROPARSER_DEBUG
+DEFINES += PROPARSER_DEBUG PROEVALUATOR_FULL PROEVALUATOR_SETENV
diff --git a/tests/auto/tools/qmakelib/testdata/cat/file1.txt b/tests/auto/tools/qmakelib/testdata/cat/file1.txt
new file mode 100644
index 0000000000..e3e4cd41b6
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/cat/file1.txt
@@ -0,0 +1,2 @@
+"Hello, world."
+foo bar baz
diff --git a/tests/auto/tools/qmakelib/testdata/cat/file2.txt b/tests/auto/tools/qmakelib/testdata/cat/file2.txt
new file mode 100644
index 0000000000..18483311e6
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/cat/file2.txt
@@ -0,0 +1,5 @@
+foo bar baz
+"Hello, ' world." post
+'Hello, " world.' post
+\" \' \\ \a \ nix
+" "
diff --git a/tests/auto/tools/qmakelib/testdata/files/dir/file1.txt b/tests/auto/tools/qmakelib/testdata/files/dir/file1.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/files/dir/file1.txt
diff --git a/tests/auto/tools/qmakelib/testdata/files/dir/file2.txt b/tests/auto/tools/qmakelib/testdata/files/dir/file2.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/files/dir/file2.txt
diff --git a/tests/auto/tools/qmakelib/testdata/files/file1.txt b/tests/auto/tools/qmakelib/testdata/files/file1.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/files/file1.txt
diff --git a/tests/auto/tools/qmakelib/testdata/files/file2.txt b/tests/auto/tools/qmakelib/testdata/files/file2.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/files/file2.txt
diff --git a/tests/auto/tools/qmakelib/testdata/files/other.txt b/tests/auto/tools/qmakelib/testdata/files/other.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/files/other.txt
diff --git a/tests/auto/tools/qmakelib/testdata/fromfile/badfile.prx b/tests/auto/tools/qmakelib/testdata/fromfile/badfile.prx
new file mode 100644
index 0000000000..a916f21587
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/fromfile/badfile.prx
@@ -0,0 +1 @@
+error("fail!")
diff --git a/tests/auto/tools/qmake/testdata/functions/infiletest.pro b/tests/auto/tools/qmakelib/testdata/fromfile/infile.prx
index 821cb5cb2c..821cb5cb2c 100644
--- a/tests/auto/tools/qmake/testdata/functions/infiletest.pro
+++ b/tests/auto/tools/qmakelib/testdata/fromfile/infile.prx
diff --git a/tests/auto/tools/qmakelib/testdata/include/inc.pri b/tests/auto/tools/qmakelib/testdata/include/inc.pri
new file mode 100644
index 0000000000..1f1b3a287f
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/include/inc.pri
@@ -0,0 +1,8 @@
+VAR = val
+.VAR = nope
+
+fake-*: MATCH = 1
+
+defineTest(func) {
+ message("say hi!")
+}
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/fake-g++/qmake.conf b/tests/auto/tools/qmakelib/testdata/mkspecs/fake-g++/qmake.conf
new file mode 100644
index 0000000000..d7a17d2429
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/fake-g++/qmake.conf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_post.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_post.prf
new file mode 100644
index 0000000000..d7a17d2429
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_post.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_pre.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_pre.prf
new file mode 100644
index 0000000000..d7a17d2429
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/default_pre.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_post.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_post.prf
new file mode 100644
index 0000000000..d7a17d2429
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_post.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_pre.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_pre.prf
new file mode 100644
index 0000000000..d7a17d2429
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/spec_pre.prf
@@ -0,0 +1 @@
+# Nothing here
diff --git a/tests/auto/tools/qmakelib/testdata/mkspecs/features/testfeat.prf b/tests/auto/tools/qmakelib/testdata/mkspecs/features/testfeat.prf
new file mode 100644
index 0000000000..57c9a0d783
--- /dev/null
+++ b/tests/auto/tools/qmakelib/testdata/mkspecs/features/testfeat.prf
@@ -0,0 +1 @@
+VAR = foo bar
diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.cpp b/tests/auto/tools/qmakelib/tst_qmakelib.cpp
index 1c6d43338d..3da48815fb 100644
--- a/tests/auto/tools/qmakelib/tst_qmakelib.cpp
+++ b/tests/auto/tools/qmakelib/tst_qmakelib.cpp
@@ -31,37 +31,112 @@
**
****************************************************************************/
-#include <QtTest/QtTest>
+#include "tst_qmakelib.h"
#include <ioutils.h>
-#include <proitems.h>
-#include <qmakevfs.h>
-#include <qmakeparser.h>
-
-#include <QObject>
using namespace QMakeInternal;
-class tst_qmakelib : public QObject
+void tst_qmakelib::initTestCase()
+{
+ m_indir = QFINDTESTDATA("testdata");
+ m_outdir = m_indir + QLatin1String("_build");
+ m_env.insert(QStringLiteral("E1"), QStringLiteral("env var"));
+#ifdef Q_OS_WIN
+ m_env.insert(QStringLiteral("COMSPEC"), qgetenv("COMSPEC"));
+#endif
+ m_prop.insert(ProKey("P1"), ProString("prop val"));
+ m_prop.insert(ProKey("QT_HOST_DATA/get"), ProString(m_indir));
+
+ QVERIFY(!m_indir.isEmpty());
+ QVERIFY(QDir(m_outdir).removeRecursively());
+ QVERIFY(QDir().mkpath(m_outdir));
+}
+
+void tst_qmakelib::cleanupTestCase()
{
- Q_OBJECT
+ QVERIFY(QDir(m_outdir).removeRecursively());
+}
+
+void tst_qmakelib::proString()
+{
+ QString qs1(QStringLiteral("this is a string"));
+
+ ProString s1(qs1);
+ QCOMPARE(s1.toQString(), QStringLiteral("this is a string"));
+
+ ProString s2(qs1, 5, 8);
+ QCOMPARE(s2.toQString(), QStringLiteral("is a str"));
+
+ QCOMPARE(s2.hash(), 0x80000000);
+ qHash(s2);
+ QCOMPARE(s2.hash(), 90404018U);
-public:
- tst_qmakelib() {}
- virtual ~tst_qmakelib() {}
+ QCOMPARE(s2.mid(0, 10).toQString(), QStringLiteral("is a str"));
+ QCOMPARE(s2.mid(1, 5).toQString(), QStringLiteral("s a s"));
+ QCOMPARE(s2.mid(10, 3).toQString(), QStringLiteral(""));
-private slots:
- void quoteArgUnix_data();
- void quoteArgUnix();
- void quoteArgWin_data();
- void quoteArgWin();
- void pathUtils();
+ QString qs2(QStringLiteral(" spacy string "));
+ QCOMPARE(ProString(qs2, 3, 13).trimmed().toQString(), QStringLiteral("spacy string"));
+ QCOMPARE(ProString(qs2, 1, 17).trimmed().toQString(), QStringLiteral("spacy string"));
- void proStringList();
+ QVERIFY(s2.toQStringRef().string()->isSharedWith(qs1));
+ s2.prepend(ProString("there "));
+ QCOMPARE(s2.toQString(), QStringLiteral("there is a str"));
+ QVERIFY(!s2.toQStringRef().string()->isSharedWith(qs1));
- void proParser_data();
- void proParser();
-};
+ ProString s3("this is a longish string with bells and whistles");
+ s3 = s3.mid(18, 17);
+ // Prepend to detached string with lots of spare space in it.
+ s3.prepend(ProString("another "));
+ QCOMPARE(s3.toQString(), QStringLiteral("another string with bells"));
+
+ // Note: The string still has plenty of spare space.
+ s3.append(QLatin1Char('.'));
+ QCOMPARE(s3.toQString(), QStringLiteral("another string with bells."));
+ s3.append(QLatin1String(" eh?"));
+ QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh?"));
+
+ s3.append(ProString(" yeah!"));
+ QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh? yeah!"));
+
+ bool pending = false; // Not in string, but joining => add space
+ s3.append(ProString("..."), &pending);
+ QCOMPARE(s3.toQString(), QStringLiteral("another string with bells. eh? yeah! ..."));
+ QVERIFY(pending);
+
+ ProStringList sl1;
+ sl1 << ProString("") << ProString("foo") << ProString("barbaz");
+ ProString s4a("hallo");
+ s4a.append(sl1);
+ QCOMPARE(s4a.toQString(), QStringLiteral("hallo foo barbaz"));
+ ProString s4b("hallo");
+ pending = false;
+ s4b.append(sl1, &pending);
+ QCOMPARE(s4b.toQString(), QStringLiteral("hallo foo barbaz"));
+ ProString s4c;
+ pending = false;
+ s4c.append(sl1, &pending);
+ QCOMPARE(s4c.toQString(), QStringLiteral(" foo barbaz"));
+ // bizarreness
+ ProString s4d("hallo");
+ pending = false;
+ s4d.append(sl1, &pending, true);
+ QCOMPARE(s4d.toQString(), QStringLiteral("hallo foo barbaz"));
+ ProString s4e;
+ pending = false;
+ s4e.append(sl1, &pending, true);
+ QCOMPARE(s4e.toQString(), QStringLiteral("foo barbaz"));
+
+ ProStringList sl2;
+ sl2 << ProString("foo");
+ ProString s5;
+ s5.append(sl2);
+ QCOMPARE(s5.toQString(), QStringLiteral("foo"));
+ QVERIFY(s5.toQStringRef().string()->isSharedWith(*sl2.first().toQStringRef().string()));
+
+ QCOMPARE(ProString("one") + ProString(" more"), QStringLiteral("one more"));
+}
void tst_qmakelib::proStringList()
{
@@ -171,1940 +246,24 @@ void tst_qmakelib::pathUtils()
QCOMPARE(IoUtils::resolvePath(fnbase, fn1), QStringLiteral("/a/unix/file/path"));
}
-class QMakeHandler : public QMakeParserHandler {
-public:
- QMakeHandler() : QMakeParserHandler(), printed(false) {}
- virtual void message(int type, const QString &msg, const QString &fileName, int lineNo)
- { print(fileName, lineNo, type, msg); }
-
- void setExpectedMessages(const QStringList &msgs) { expected = msgs; }
- QStringList expectedMessages() const { return expected; }
-
- bool printedMessages() const { return printed; }
-
-private:
- void print(const QString &fileName, int lineNo, int type, const QString &msg)
- {
- QString pfx = ((type & QMakeParserHandler::CategoryMask) == QMakeParserHandler::WarningMessage)
- ? QString::fromLatin1("WARNING: ") : QString();
- QString out;
- if (lineNo)
- out = QStringLiteral("%1%2:%3: %4").arg(pfx, fileName, QString::number(lineNo), msg);
- else
- out = QStringLiteral("%1%2").arg(pfx, msg);
- if (!expected.isEmpty() && expected.first() == out) {
- expected.removeAt(0);
- return;
- }
- qWarning("%s", qPrintable(out));
- printed = true;
- }
-
- QStringList expected;
- bool printed;
-};
-
-static QMakeHandler qmakeHandler;
-
-class TokenStream
+void QMakeTestHandler::print(const QString &fileName, int lineNo, int type, const QString &msg)
{
-public:
- TokenStream() {}
- QString toString() const { return ts; }
-
- TokenStream &operator<<(ushort n) { ts += QChar(n); return *this; }
- TokenStream &operator<<(uint n) { ts += QChar(n & 0xffff); ts += QChar(n >> 16); return *this; }
- TokenStream &operator<<(const QStringRef &s) { ts += s; return *this; }
- TokenStream &operator<<(const ProString &s) { return *this << ushort(s.length()) << s.toQStringRef(); }
- TokenStream &operator<<(const ProKey &s) { return *this << s.hash() << s.toString(); }
-
-private:
- QString ts;
-};
-
-#define TS(s) (TokenStream() s).toString()
-#define H(n) ushort(n)
-#define I(n) uint(n)
-#define S(s) ProString(QString::fromWCharArray(s))
-#define HS(s) ProKey(QString::fromWCharArray(s))
-
-void tst_qmakelib::proParser_data()
-{
- QTest::addColumn<QString>("in");
- QTest::addColumn<QString>("out");
- QTest::addColumn<QString>("msgs");
- QTest::addColumn<bool>("ok");
-
- QTest::newRow("empty")
- << ""
- << TS()
- << ""
- << true;
-
- QTest::newRow("empty (whitespace)")
- << " \t \t"
- << TS()
- << ""
- << true;
-
- // Variable operators
-
- QTest::newRow("assign none")
- << "VAR ="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAssign) << H(0)
- /* 11 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("append none")
- << "VAR +="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAppend) << H(0)
- /* 11 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("unique append none")
- << "VAR *="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAppendUnique) << H(0)
- /* 11 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("remove none")
- << "VAR -="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokRemove) << H(0)
- /* 11 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("replace empty")
- << "VAR ~="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokReplace) << H(0)
- /* 11 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("assignment without variable")
- << "="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokAssign) << H(0)
- /* 4 */ << H(TokValueTerminator))
- << "in:1: Assignment needs exactly one word on the left hand side."
- << false;
-
- QTest::newRow("assignment with multiple variables")
- << "VAR VAR ="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokAssign) << H(0)
- /* 4 */ << H(TokValueTerminator))
- << "in:1: Assignment needs exactly one word on the left hand side."
- << false;
-
- // Values
-
-#define ASSIGN_VAR(h) \
- H(TokLine) << H(1) \
- << H(TokHashLiteral) << HS(L"VAR") \
- << H(TokAssign) << H(h)
-
- QTest::newRow("one literal")
- << "VAR = val"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val")
- /* 16 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("one literal (squeezed)")
- << "VAR=val"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val")
- /* 16 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("many literals")
- << "VAR = foo barbaz bak hello"
- << TS(
- /* 0 */ << ASSIGN_VAR(4)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
- /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
- /* 29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
- /* 36 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("many literals (tab-separated")
- << "VAR\t=\tfoo\tbarbaz\tbak\thello"
- << TS(
- /* 0 */ << ASSIGN_VAR(4)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
- /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
- /* 29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
- /* 36 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("one quoted literal")
- << "VAR = \"val ue\""
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val ue")
- /* 19 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("quoted literal with missing quote")
- << "VAR = val \"ue"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAssign) << H(0)
- /* 11 */ << H(TokValueTerminator))
- << "in:1: Missing closing \" quote"
- << false;
-
- QTest::newRow("many quoted literals")
- << "VAR = \"foo\" barbaz 'bak hello' \"\""
- << TS(
- /* 0 */ << ASSIGN_VAR(3)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
- /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak hello")
- /* 35 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("many quoted literals (with tabs)")
- << "VAR\t=\t\"foo\"\tbarbaz\t'bak\thello'"
- << TS(
- /* 0 */ << ASSIGN_VAR(3)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
- /* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak\thello")
- /* 35 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("quoted and unquoted spaces")
- << " VAR = \"val ue \" "
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"val ue ")
- /* 22 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("funny literals")
- << "VAR = foo:bar|!baz(blam!, ${foo})"
- << TS(
- /* 0 */ << ASSIGN_VAR(2)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo:bar|!baz(blam!,")
- /* 32 */ << H(TokLiteral | TokNewStr) << S(L"${foo})")
- /* 41 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("literals with escapes")
- << "VAR = \\{hi\\} \\[ho\\] \\)uh\\( \"\\\\oh\\$\"\\' \\$\\${FOO}"
- << TS(
- /* 0 */ << ASSIGN_VAR(5)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"{hi}")
- /* 17 */ << H(TokLiteral | TokNewStr) << S(L"[ho]")
- /* 23 */ << H(TokLiteral | TokNewStr) << S(L")uh(")
- /* 29 */ << H(TokLiteral | TokNewStr) << S(L"\\oh$'")
- /* 36 */ << H(TokLiteral | TokNewStr) << S(L"$${FOO}")
- /* 45 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("magic variables")
- << "VAR = $$LITERAL_HASH $$LITERAL_DOLLAR $$LITERAL_WHITESPACE $$_FILE_ $$_LINE_"
- << TS(
- /* 0 */ << ASSIGN_VAR(5)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"#")
- /* 14 */ << H(TokLiteral | TokNewStr) << S(L"$")
- /* 17 */ << H(TokLiteral | TokNewStr) << S(L"\t")
- /* 20 */ << H(TokLiteral | TokNewStr) << S(L"in")
- /* 24 */ << H(TokLiteral | TokNewStr) << S(L"1")
- /* 27 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("continuations and comments")
- << "VAR = foo \\\n bar\n \n"
- "GAR = foo \\ # comment\n bar \\\n # comment\n baz \\\n"
- "\"quoted \\ #comment\n escape\" \\\n right\\\n after \\\n gorilla!\n \n\n"
- "MOO = \\\n kuh # comment\nLOO =\n\n"
- "FOO = bar \\\n# comment\n baz \\\n \n# comment\n"
- "GAZ="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAssign) << H(2)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokLiteral | TokNewStr) << S(L"bar")
- /* 21 */ << H(TokValueTerminator)
- /* 22 */ << H(TokLine) << H(4)
- /* 24 */ << H(TokHashLiteral) << HS(L"GAR")
- /* 31 */ << H(TokAssign) << H(7)
- /* 33 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 38 */ << H(TokLiteral | TokNewStr) << S(L"bar")
- /* 43 */ << H(TokLiteral | TokNewStr) << S(L"baz")
- /* 48 */ << H(TokLiteral | TokNewStr) << S(L"quoted escape")
- /* 64 */ << H(TokLiteral | TokNewStr) << S(L"right")
- /* 71 */ << H(TokLiteral | TokNewStr) << S(L"after")
- /* 78 */ << H(TokLiteral | TokNewStr) << S(L"gorilla!")
- /* 88 */ << H(TokValueTerminator)
- /* 89 */ << H(TokLine) << H(15)
- /* 91 */ << H(TokHashLiteral) << HS(L"MOO")
- /* 98 */ << H(TokAssign) << H(0)
- /* 100 */ << H(TokLiteral | TokNewStr) << S(L"kuh")
- /* 105 */ << H(TokValueTerminator)
- /* 106 */ << H(TokLine) << H(17)
- /* 108 */ << H(TokHashLiteral) << HS(L"LOO")
- /* 115 */ << H(TokAssign) << H(0)
- /* 117 */ << H(TokValueTerminator)
- /* 118 */ << H(TokLine) << H(19)
- /* 120 */ << H(TokHashLiteral) << HS(L"FOO")
- /* 127 */ << H(TokAssign) << H(2)
- /* 129 */ << H(TokLiteral | TokNewStr) << S(L"bar")
- /* 134 */ << H(TokLiteral | TokNewStr) << S(L"baz")
- /* 139 */ << H(TokValueTerminator)
- /* 140 */ << H(TokLine) << H(24)
- /* 142 */ << H(TokHashLiteral) << HS(L"GAZ")
- /* 149 */ << H(TokAssign) << H(0)
- /* 151 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("accidental continuation")
- << "VAR0 = \\\n this \\\n is \\\n ok\n"
- "VAR1 = \\\n this \\\n is=still \\\n ok\n"
- "VAR2 = \\\n this \\\n is \\\n"
- "VAR3 = \\\n not ok\n"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR0")
- /* 10 */ << H(TokAssign) << H(3)
- /* 12 */ << H(TokLiteral | TokNewStr) << S(L"this")
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"is")
- /* 22 */ << H(TokLiteral | TokNewStr) << S(L"ok")
- /* 26 */ << H(TokValueTerminator)
- /* 27 */ << H(TokLine) << H(5)
- /* 29 */ << H(TokHashLiteral) << HS(L"VAR1")
- /* 37 */ << H(TokAssign) << H(3)
- /* 39 */ << H(TokLiteral | TokNewStr) << S(L"this")
- /* 45 */ << H(TokLiteral | TokNewStr) << S(L"is=still")
- /* 55 */ << H(TokLiteral | TokNewStr) << S(L"ok")
- /* 59 */ << H(TokValueTerminator)
- /* 60 */ << H(TokLine) << H(9)
- /* 62 */ << H(TokHashLiteral) << HS(L"VAR2")
- /* 70 */ << H(TokAssign) << H(6)
- /* 72 */ << H(TokLiteral | TokNewStr) << S(L"this")
- /* 78 */ << H(TokLiteral | TokNewStr) << S(L"is")
- /* 82 */ << H(TokLiteral | TokNewStr) << S(L"VAR3")
- /* 88 */ << H(TokLiteral | TokNewStr) << S(L"=")
- /* 91 */ << H(TokLiteral | TokNewStr) << S(L"not")
- /* 96 */ << H(TokLiteral | TokNewStr) << S(L"ok")
- /* 100 */ << H(TokValueTerminator))
- << "WARNING: in:12: Possible accidental line continuation"
- << true;
-
- QTest::newRow("plain variable expansion")
- << "VAR = $$bar"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("braced variable expansion")
- << "VAR = $${foo/bar}"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"foo/bar")
- /* 22 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("bogus variable expansion")
- << "VAR = $$ "
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"")
- /* 15 */ << H(TokValueTerminator))
- << "WARNING: in:1: Missing name in expansion"
- << true;
-
- QTest::newRow("bogus braced variable expansion")
- << "VAR = $${}"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"")
- /* 15 */ << H(TokValueTerminator))
- << "WARNING: in:1: Missing name in expansion"
- << true;
-
- QTest::newRow("unterminated braced variable expansion")
- << "VAR = $${FOO"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAssign) << H(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"FOO")
- /* 18 */ << H(TokValueTerminator))
- << "in:1: Missing } terminator [found end-of-line]"
- << false;
-
- QTest::newRow("invalid identifier in braced variable expansion")
- << "VAR = $${FOO/BAR+BAZ}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAssign) << H(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"FOO/BAR")
- /* 22 */ << H(TokLiteral) << S(L"+BAZ")
- /* 28 */ << H(TokValueTerminator))
- << "in:1: Missing } terminator [found +]"
- << false;
-
- QTest::newRow("property expansion")
- << "VAR = $$[bar]"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokProperty | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("environment expansion")
- << "VAR = $$(bar)"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokEnvVar | TokNewStr) << S(L"bar")
- /* 16 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("plain function call")
- << "VAR = $$bar()"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokFuncTerminator)
- /* 19 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("braced function call")
- << "VAR = $${bar()}"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokFuncTerminator)
- /* 19 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("function call with one argument")
- << "VAR = $$bar(blubb)"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
- /* 25 */ << H(TokFuncTerminator)
- /* 26 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("function call with multiple arguments")
- << "VAR = $$bar( blubb blubb, hey ,$$you)"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
- /* 25 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
- /* 32 */ << H(TokArgSeparator)
- /* 33 */ << H(TokLiteral | TokNewStr) << S(L"hey")
- /* 38 */ << H(TokArgSeparator)
- /* 39 */ << H(TokVariable | TokNewStr) << HS(L"you")
- /* 46 */ << H(TokFuncTerminator)
- /* 47 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("nested function call")
- << "VAR = $$foo(yo, $$bar(blubb))"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"foo")
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"yo")
- /* 22 */ << H(TokArgSeparator)
- /* 23 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
- /* 30 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
- /* 37 */ << H(TokFuncTerminator)
- /* 38 */ << H(TokFuncTerminator)
- /* 39 */ << H(TokValueTerminator))
- << ""
- << true;
-
- // This is a rather questionable "feature"
- QTest::newRow("function call with parenthesized argument")
- << "VAR = $$bar(blubb (yo, man) blabb, nope)"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
- /* 25 */ << H(TokLiteral | TokNewStr) << S(L"(yo,")
- /* 31 */ << H(TokLiteral | TokNewStr) << S(L"man)")
- /* 37 */ << H(TokLiteral | TokNewStr) << S(L"blabb")
- /* 44 */ << H(TokArgSeparator)
- /* 45 */ << H(TokLiteral | TokNewStr) << S(L"nope")
- /* 51 */ << H(TokFuncTerminator)
- /* 52 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("separate literal and expansion")
- << "VAR = foo $$bar"
- << TS(
- /* 0 */ << ASSIGN_VAR(2)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokVariable | TokNewStr) << HS(L"bar")
- /* 23 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("separate expansion and literal")
- << "VAR = $$bar foo"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 23 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("joined literal and expansion")
- << "VAR = foo$$bar"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokVariable) << HS(L"bar")
- /* 23 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("joined expansion and literal")
- << "VAR = $${bar}foo"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
- /* 18 */ << H(TokLiteral) << S(L"foo")
- /* 23 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("plain variable expansion with funny name and literal")
- << "VAR = $$az_AZ_09.dot/nix"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot")
- /* 27 */ << H(TokLiteral) << S(L"/nix")
- /* 33 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("braced variable expansion with funny name")
- << "VAR = $${az_AZ_09.dot/nix}"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot/nix")
- /* 31 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("quoted joined literal and expansion")
- << "VAR = 'foo$$bar'"
- << TS(
- /* 0 */ << ASSIGN_VAR(0)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 16 */ << H(TokVariable | TokQuoted) << HS(L"bar")
- /* 23 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("assignment with expansion in variable name")
- << "VAR$$EXTRA ="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokVariable) << HS(L"EXTRA")
- /* 18 */ << H(TokAssign) << H(0)
- /* 20 */ << H(TokValueTerminator))
- << ""
- << true;
-
- // Conditionals ("Tests")
-
- QTest::newRow("one test")
- << "foo"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("wildcard-test")
- << "foo-*"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo-*")
- /* 11 */ << H(TokCondition))
- << ""
- << true;
-
- // This is a rather questionable "feature"
- QTest::newRow("one quoted test")
- << "\"foo\""
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("two tests")
- << "foo\nbar"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokLine) << H(2)
- /* 12 */ << H(TokHashLiteral) << HS(L"bar")
- /* 19 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("bogus two tests")
- << "foo bar\nbaz"
- << TS()
- << "in:1: Extra characters after test expression."
- << false;
-
- QTest::newRow("test-AND-test")
- << "foo:bar"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokAnd)
- /* 11 */ << H(TokHashLiteral) << HS(L"bar")
- /* 18 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("test-OR-test")
- << " foo | bar "
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokOr)
- /* 11 */ << H(TokHashLiteral) << HS(L"bar")
- /* 18 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("NOT-test")
- << "!foo"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokNot)
- /* 3 */ << H(TokHashLiteral) << HS(L"foo")
- /* 10 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("NOT-NOT-test")
- << "!!foo"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition))
- << ""
- << true;
-
- // This is a rather questionable "feature"
- QTest::newRow("quoted-NOT-test")
- << "\"!foo\""
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokNot)
- /* 3 */ << H(TokHashLiteral) << HS(L"foo")
- /* 10 */ << H(TokCondition))
- << ""
- << true;
-
- // This is a rather questionable "feature"
- QTest::newRow("NOT-quoted-test")
- << "!\"foo\""
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokNot)
- /* 3 */ << H(TokHashLiteral) << HS(L"foo")
- /* 10 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("test-AND-NOT-test")
- << "foo:!bar"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokAnd)
- /* 11 */ << H(TokNot)
- /* 12 */ << H(TokHashLiteral) << HS(L"bar")
- /* 19 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("test-assignment")
- << "foo\nVAR="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokLine) << H(2)
- /* 12 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 19 */ << H(TokAssign) << H(0)
- /* 21 */ << H(TokValueTerminator))
- << ""
- << true;
-
- QTest::newRow("test-AND-assignment")
- << "foo: VAR ="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokBranch)
- /* 11 */ /* then branch */ << I(11)
- /* 13 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 20 */ << H(TokAssign) << H(0)
- /* 22 */ << H(TokValueTerminator)
- /* 23 */ << H(TokTerminator)
- /* 24 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test-else-test")
- << "foo\nelse: bar"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokBranch)
- /* 11 */ /* then branch */ << I(0)
- /* 13 */ /* else branch */ << I(11)
- /* 15 */ << H(TokLine) << H(2)
- /* 17 */ << H(TokHashLiteral) << HS(L"bar")
- /* 24 */ << H(TokCondition)
- /* 25 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("function-else-test")
- << "foo()\nelse: bar"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokFuncTerminator)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(0)
- /* 14 */ /* else branch */ << I(11)
- /* 16 */ << H(TokLine) << H(2)
- /* 18 */ << H(TokHashLiteral) << HS(L"bar")
- /* 25 */ << H(TokCondition)
- /* 26 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-AND-test-else-test")
- << "foo:bar\nelse: baz"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokAnd)
- /* 11 */ << H(TokHashLiteral) << HS(L"bar")
- /* 18 */ << H(TokCondition)
- /* 19 */ << H(TokBranch)
- /* 20 */ /* then branch */ << I(0)
- /* 22 */ /* else branch */ << I(11)
- /* 24 */ << H(TokLine) << H(2)
- /* 26 */ << H(TokHashLiteral) << HS(L"baz")
- /* 33 */ << H(TokCondition)
- /* 34 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-AND-test-else-test-else-test-function")
- << "foo:bar\nelse: baz\nelse: bak\nbuzz()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokAnd)
- /* 11 */ << H(TokHashLiteral) << HS(L"bar")
- /* 18 */ << H(TokCondition)
- /* 19 */ << H(TokBranch)
- /* 20 */ /* then branch */ << I(0)
- /* 22 */ /* else branch */ << I(27)
- /* 24 */ << H(TokLine) << H(2)
- /* 26 */ << H(TokHashLiteral) << HS(L"baz")
- /* 33 */ << H(TokCondition)
- /* 34 */ << H(TokBranch)
- /* 35 */ /* then branch */ << I(0)
- /* 37 */ /* else branch */ << I(11)
- /* 39 */ << H(TokLine) << H(3)
- /* 41 */ << H(TokHashLiteral) << HS(L"bak")
- /* 48 */ << H(TokCondition)
- /* 49 */ << H(TokTerminator)
- /* 50 */ << H(TokTerminator)
- /* 51 */ << H(TokLine) << H(4)
- /* 53 */ << H(TokHashLiteral) << HS(L"buzz")
- /* 61 */ << H(TokTestCall)
- /* 62 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("test-assignment-else-assignment")
- << "foo: VAR =\nelse: VAR="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokBranch)
- /* 11 */ /* then branch */ << I(11)
- /* 13 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 20 */ << H(TokAssign) << H(0)
- /* 22 */ << H(TokValueTerminator)
- /* 23 */ << H(TokTerminator)
- /* 24 */ /* else branch */ << I(13)
- /* 26 */ << H(TokLine) << H(2)
- /* 28 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 35 */ << H(TokAssign) << H(0)
- /* 37 */ << H(TokValueTerminator)
- /* 38 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-else-test-assignment")
- << "foo\nelse: bar: VAR ="
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokBranch)
- /* 11 */ /* then branch */ << I(0)
- /* 13 */ /* else branch */ << I(27)
- /* 15 */ << H(TokLine) << H(2)
- /* 17 */ << H(TokHashLiteral) << HS(L"bar")
- /* 24 */ << H(TokCondition)
- /* 25 */ << H(TokBranch)
- /* 26 */ /* then branch */ << I(11)
- /* 28 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 35 */ << H(TokAssign) << H(0)
- /* 37 */ << H(TokValueTerminator)
- /* 38 */ << H(TokTerminator)
- /* 39 */ /* else branch */ << I(0)
- /* 41 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("one function")
- << "foo()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("one function (with spaces)")
- << " foo( ) "
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("unterminated function call")
- << "foo(\nfoo"
- << TS()
- << "in:1: Missing closing parenthesis in function call"
- << false;
-
- QTest::newRow("function with arguments")
- << "foo(blah, hi ho)"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokLiteral | TokNewStr) << S(L"blah")
- /* 16 */ << H(TokArgSeparator)
- /* 17 */ << H(TokLiteral | TokNewStr) << S(L"hi")
- /* 21 */ << H(TokLiteral | TokNewStr) << S(L"ho")
- /* 25 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("function with empty arguments")
- << "foo(,)"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokArgSeparator)
- /* 11 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("function with funny arguments")
- << "foo(blah\\, \"hi , \\ho\" ,uh\\ ,\\oh ,, )"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokLiteral | TokNewStr) << S(L"blah\\")
- /* 17 */ << H(TokArgSeparator)
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"hi , \\ho")
- /* 29 */ << H(TokArgSeparator)
- /* 30 */ << H(TokLiteral | TokNewStr) << S(L"uh\\")
- /* 35 */ << H(TokArgSeparator)
- /* 36 */ << H(TokLiteral | TokNewStr) << S(L"\\oh")
- /* 41 */ << H(TokArgSeparator)
- /* 42 */ << H(TokArgSeparator)
- /* 43 */ << H(TokFuncTerminator))
- << "WARNING: in:1: Unescaped backslashes are deprecated\n"
- "WARNING: in:1: Unescaped backslashes are deprecated\n"
- "WARNING: in:1: Unescaped backslashes are deprecated\n"
- "WARNING: in:1: Unescaped backslashes are deprecated"
- << true;
-
- QTest::newRow("function with nested call")
- << "foo($$blah(hi ho))"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokFuncName | TokNewStr) << HS(L"blah")
- /* 18 */ << H(TokLiteral | TokNewStr) << S(L"hi")
- /* 22 */ << H(TokLiteral | TokNewStr) << S(L"ho")
- /* 26 */ << H(TokFuncTerminator)
- /* 27 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("stand-alone parentheses")
- << "()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokTestCall)
- /* 3 */ << H(TokFuncTerminator))
- << "in:1: Opening parenthesis without prior test name."
- << false;
-
- QTest::newRow("bogus test and function")
- << "foo bar()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokTestCall)
- /* 3 */ << H(TokFuncTerminator))
- << "in:1: Extra characters after test expression."
- << false;
-
- // This is a rather questionable "feature"
- QTest::newRow("two functions")
- << "foo() bar()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokFuncTerminator)
- /* 11 */ << H(TokHashLiteral) << HS(L"bar")
- /* 18 */ << H(TokTestCall)
- /* 19 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("function-AND-test")
- << "foo():bar"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokTestCall)
- /* 10 */ << H(TokFuncTerminator)
- /* 11 */ << H(TokAnd)
- /* 12 */ << H(TokHashLiteral) << HS(L"bar")
- /* 19 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("test-AND-function")
- << "foo:bar()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokAnd)
- /* 11 */ << H(TokHashLiteral) << HS(L"bar")
- /* 18 */ << H(TokTestCall)
- /* 19 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- QTest::newRow("NOT-function-AND-test")
- << "!foo():bar"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokNot)
- /* 3 */ << H(TokHashLiteral) << HS(L"foo")
- /* 10 */ << H(TokTestCall)
- /* 11 */ << H(TokFuncTerminator)
- /* 12 */ << H(TokAnd)
- /* 13 */ << H(TokHashLiteral) << HS(L"bar")
- /* 20 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("test-AND-NOT-function")
- << "foo:!bar()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"foo")
- /* 9 */ << H(TokCondition)
- /* 10 */ << H(TokAnd)
- /* 11 */ << H(TokNot)
- /* 12 */ << H(TokHashLiteral) << HS(L"bar")
- /* 19 */ << H(TokTestCall)
- /* 20 */ << H(TokFuncTerminator))
- << ""
- << true;
-
- // Control statements
-
- QTest::newRow("for(VAR, LIST) loop")
- << "for(VAR, LIST)"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"VAR")
- /* 9 */ /* iterator */ << I(7)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
- /* 17 */ << H(TokValueTerminator)
- /* 18 */ /* body */ << I(1)
- /* 20 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("for(ever) loop")
- << "for(ever)"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"")
- /* 6 */ /* iterator */ << I(9)
- /* 8 */ << H(TokHashLiteral) << HS(L"ever")
- /* 16 */ << H(TokValueTerminator)
- /* 17 */ /* body */ << I(1)
- /* 19 */ << H(TokTerminator))
- << ""
- << true;
-
- // This is a rather questionable "feature"
- QTest::newRow("for($$blub) loop")
- << "for($$blub)"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"")
- /* 6 */ /* iterator */ << I(9)
- /* 8 */ << H(TokVariable | TokNewStr) << HS(L"blub")
- /* 16 */ << H(TokValueTerminator)
- /* 17 */ /* body */ << I(1)
- /* 19 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-for-test-else-test")
- << "true:for(VAR, LIST): true\nelse: true"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(31)
- /* 14 */ << H(TokForLoop) << HS(L"VAR")
- /* 21 */ /* iterator */ << I(7)
- /* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
- /* 29 */ << H(TokValueTerminator)
- /* 30 */ /* body */ << I(12)
- /* 32 */ << H(TokLine) << H(1)
- /* 34 */ << H(TokHashLiteral) << HS(L"true")
- /* 42 */ << H(TokCondition)
- /* 43 */ << H(TokTerminator)
- /* 44 */ << H(TokTerminator)
- /* 45 */ /* else branch */ << I(12)
- /* 47 */ << H(TokLine) << H(2)
- /* 49 */ << H(TokHashLiteral) << HS(L"true")
- /* 57 */ << H(TokCondition)
- /* 58 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("next()")
- << "for(ever): next()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"")
- /* 6 */ /* iterator */ << I(9)
- /* 8 */ << H(TokHashLiteral) << HS(L"ever")
- /* 16 */ << H(TokValueTerminator)
- /* 17 */ /* body */ << I(4)
- /* 19 */ << H(TokLine) << H(1)
- /* 21 */ << H(TokNext)
- /* 22 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("break()")
- << "for(ever): break()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"")
- /* 6 */ /* iterator */ << I(9)
- /* 8 */ << H(TokHashLiteral) << HS(L"ever")
- /* 16 */ << H(TokValueTerminator)
- /* 17 */ /* body */ << I(4)
- /* 19 */ << H(TokLine) << H(1)
- /* 21 */ << H(TokBreak)
- /* 22 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("top-level return()")
- << "return()"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokReturn))
- << ""
- << true;
-
- QTest::newRow("else")
- << "else"
- << TS()
- << "in:1: Unexpected 'else'."
- << false;
-
- QTest::newRow("test-{else}")
- << "test { else }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(1)
- /* 14 */ << H(TokTerminator)
- /* 15 */ /* else branch */ << I(0))
- << "in:1: Unexpected 'else'."
- << false;
-
- QTest::newRow("defineTest-{else}")
- << "defineTest(fn) { else }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokTestDef) << HS(L"fn")
- /* 8 */ /* body */ << I(1)
- /* 10 */ << H(TokTerminator))
- << "in:1: Unexpected 'else'."
- << false;
-
- QTest::newRow("for-else")
- << "for(ever) { else }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"")
- /* 6 */ /* iterator */ << I(9)
- /* 8 */ << H(TokHashLiteral) << HS(L"ever")
- /* 16 */ << H(TokValueTerminator)
- /* 17 */ /* body */ << I(1)
- /* 19 */ << H(TokTerminator))
- << "in:1: Unexpected 'else'."
- << false;
-
- // Braces
-
- QTest::newRow("{}")
- << "{ }"
- << TS()
- << ""
- << true;
-
- QTest::newRow("{}-newlines")
- << "\n\n{ }\n\n"
- << TS()
- << ""
- << true;
-
- QTest::newRow("{")
- << "{"
- << TS()
- << "in:2: Missing closing brace(s)."
- << false;
-
- QTest::newRow("test {")
- << "test {"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(1)
- /* 14 */ << H(TokTerminator)
- /* 15 */ /* else branch */ << I(0))
- << "in:2: Missing closing brace(s)."
- << false;
-
- QTest::newRow("}")
- << "}"
- << TS()
- << "in:1: Excess closing brace."
- << false;
-
- QTest::newRow("{test}")
- << "{ true }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("{test-newlines}")
- << "{\ntrue\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(2)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("{assignment-test}-test")
- << "{ VAR = { foo } bar } true"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAssign) << H(4)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"{")
- /* 14 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 19 */ << H(TokLiteral | TokNewStr) << S(L"}")
- /* 22 */ << H(TokLiteral | TokNewStr) << S(L"bar")
- /* 27 */ << H(TokValueTerminator)
- /* 28 */ << H(TokHashLiteral) << HS(L"true")
- /* 36 */ << H(TokCondition))
- << ""
- << true;
-
- QTest::newRow("assignment with excess opening brace")
- << "VAR = { { foo }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 9 */ << H(TokAssign) << H(4)
- /* 11 */ << H(TokLiteral | TokNewStr) << S(L"{")
- /* 14 */ << H(TokLiteral | TokNewStr) << S(L"{")
- /* 17 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 22 */ << H(TokLiteral | TokNewStr) << S(L"}")
- /* 25 */ << H(TokValueTerminator))
- << "WARNING: in:1: Possible braces mismatch"
- << true;
-
- QTest::newRow("test-{}")
- << "true {}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(1)
- /* 14 */ << H(TokTerminator)
- /* 15 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test-{newlines}")
- << "true {\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(1)
- /* 14 */ << H(TokTerminator)
- /* 15 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test-{test}")
- << "true { true }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(10)
- /* 14 */ << H(TokHashLiteral) << HS(L"true")
- /* 22 */ << H(TokCondition)
- /* 23 */ << H(TokTerminator)
- /* 24 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test:-{test}")
- << "true: { true }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(10)
- /* 14 */ << H(TokHashLiteral) << HS(L"true")
- /* 22 */ << H(TokCondition)
- /* 23 */ << H(TokTerminator)
- /* 24 */ /* else branch */ << I(0))
- << "WARNING: in:1: Excess colon in front of opening brace."
- << true;
-
- QTest::newRow("test-{test-newlines}")
- << "true {\ntrue\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(12)
- /* 14 */ << H(TokLine) << H(2)
- /* 16 */ << H(TokHashLiteral) << HS(L"true")
- /* 24 */ << H(TokCondition)
- /* 25 */ << H(TokTerminator)
- /* 26 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test:-{test-newlines}")
- << "true: {\ntrue\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(12)
- /* 14 */ << H(TokLine) << H(2)
- /* 16 */ << H(TokHashLiteral) << HS(L"true")
- /* 24 */ << H(TokCondition)
- /* 25 */ << H(TokTerminator)
- /* 26 */ /* else branch */ << I(0))
- << "WARNING: in:1: Excess colon in front of opening brace."
- << true;
-
- QTest::newRow("test-{assignment}")
- << "true { VAR = {foo} }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(18)
- /* 14 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 21 */ << H(TokAssign) << H(0)
- /* 23 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
- /* 30 */ << H(TokValueTerminator)
- /* 31 */ << H(TokTerminator)
- /* 32 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test-{test-assignment}")
- << "true { true: VAR = {foo} }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(33)
- /* 14 */ << H(TokHashLiteral) << HS(L"true")
- /* 22 */ << H(TokCondition)
- /* 23 */ << H(TokBranch)
- /* 24 */ /* then branch */ << I(18)
- /* 26 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 33 */ << H(TokAssign) << H(0)
- /* 35 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
- /* 42 */ << H(TokValueTerminator)
- /* 43 */ << H(TokTerminator)
- /* 44 */ /* else branch */ << I(0)
- /* 46 */ << H(TokTerminator)
- /* 47 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test-{assignment-newlines}")
- << "true {\nVAR = {foo}\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(20)
- /* 14 */ << H(TokLine) << H(2)
- /* 16 */ << H(TokHashLiteral) << HS(L"VAR")
- /* 23 */ << H(TokAssign) << H(0)
- /* 25 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
- /* 32 */ << H(TokValueTerminator)
- /* 33 */ << H(TokTerminator)
- /* 34 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test-{}-else-test-{}")
- << "true {} else: true {}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(1)
- /* 14 */ << H(TokTerminator)
- /* 15 */ /* else branch */ << I(18)
- /* 17 */ << H(TokLine) << H(1)
- /* 19 */ << H(TokHashLiteral) << HS(L"true")
- /* 27 */ << H(TokCondition)
- /* 28 */ << H(TokBranch)
- /* 29 */ /* then branch */ << I(1)
- /* 31 */ << H(TokTerminator)
- /* 32 */ /* else branch */ << I(0)
- /* 34 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-{}-else-test-{}-newlines")
- << "true {\n}\nelse: true {\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(1)
- /* 14 */ << H(TokTerminator)
- /* 15 */ /* else branch */ << I(18)
- /* 17 */ << H(TokLine) << H(3)
- /* 19 */ << H(TokHashLiteral) << HS(L"true")
- /* 27 */ << H(TokCondition)
- /* 28 */ << H(TokBranch)
- /* 29 */ /* then branch */ << I(1)
- /* 31 */ << H(TokTerminator)
- /* 32 */ /* else branch */ << I(0)
- /* 34 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-{test}-else-test-{}-newlines")
- << "true {\ntrue\n}\nelse: true {\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(12)
- /* 14 */ << H(TokLine) << H(2)
- /* 16 */ << H(TokHashLiteral) << HS(L"true")
- /* 24 */ << H(TokCondition)
- /* 25 */ << H(TokTerminator)
- /* 26 */ /* else branch */ << I(18)
- /* 28 */ << H(TokLine) << H(4)
- /* 30 */ << H(TokHashLiteral) << HS(L"true")
- /* 38 */ << H(TokCondition)
- /* 39 */ << H(TokBranch)
- /* 40 */ /* then branch */ << I(1)
- /* 42 */ << H(TokTerminator)
- /* 43 */ /* else branch */ << I(0)
- /* 45 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("for-{next}")
- << "for(ever) { next() }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"")
- /* 6 */ /* iterator */ << I(9)
- /* 8 */ << H(TokHashLiteral) << HS(L"ever")
- /* 16 */ << H(TokValueTerminator)
- /* 17 */ /* body */ << I(4)
- /* 19 */ << H(TokLine) << H(1)
- /* 21 */ << H(TokNext)
- /* 22 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("for:-{next}")
- << "for(ever): { next() }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokForLoop) << HS(L"")
- /* 6 */ /* iterator */ << I(9)
- /* 8 */ << H(TokHashLiteral) << HS(L"ever")
- /* 16 */ << H(TokValueTerminator)
- /* 17 */ /* body */ << I(4)
- /* 19 */ << H(TokLine) << H(1)
- /* 21 */ << H(TokNext)
- /* 22 */ << H(TokTerminator))
- << "WARNING: in:1: Excess colon in front of opening brace."
- << true;
-
- QTest::newRow("test-for-{test-else-test-newlines}")
- << "true:for(VAR, LIST) {\ntrue\nelse: true\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(48)
- /* 14 */ << H(TokForLoop) << HS(L"VAR")
- /* 21 */ /* iterator */ << I(7)
- /* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
- /* 29 */ << H(TokValueTerminator)
- /* 30 */ /* body */ << I(29)
- /* 32 */ << H(TokLine) << H(2)
- /* 34 */ << H(TokHashLiteral) << HS(L"true")
- /* 42 */ << H(TokCondition)
- /* 43 */ << H(TokBranch)
- /* 44 */ /* then branch */ << I(0)
- /* 46 */ /* else branch */ << I(12)
- /* 48 */ << H(TokLine) << H(3)
- /* 50 */ << H(TokHashLiteral) << HS(L"true")
- /* 58 */ << H(TokCondition)
- /* 59 */ << H(TokTerminator)
- /* 60 */ << H(TokTerminator)
- /* 61 */ << H(TokTerminator)
- /* 62 */ /* else branch */ << I(0))
- << ""
- << true;
-
- QTest::newRow("test-for-{test-else-test}")
- << "true:for(VAR, LIST) { true\nelse: true }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"true")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(48)
- /* 14 */ << H(TokForLoop) << HS(L"VAR")
- /* 21 */ /* iterator */ << I(7)
- /* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
- /* 29 */ << H(TokValueTerminator)
- /* 30 */ /* body */ << I(29)
- /* 32 */ << H(TokLine) << H(1)
- /* 34 */ << H(TokHashLiteral) << HS(L"true")
- /* 42 */ << H(TokCondition)
- /* 43 */ << H(TokBranch)
- /* 44 */ /* then branch */ << I(0)
- /* 46 */ /* else branch */ << I(12)
- /* 48 */ << H(TokLine) << H(2)
- /* 50 */ << H(TokHashLiteral) << HS(L"true")
- /* 58 */ << H(TokCondition)
- /* 59 */ << H(TokTerminator)
- /* 60 */ << H(TokTerminator)
- /* 61 */ << H(TokTerminator)
- /* 62 */ /* else branch */ << I(0))
- << ""
- << true;
-
- // Custom functions
-
- QTest::newRow("defineTest-{newlines}")
- << "defineTest(test) {\n}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokTestDef) << HS(L"test")
- /* 10 */ /* body */ << I(1)
- /* 12 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("defineTest:-test")
- << "defineTest(test): test"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokTestDef) << HS(L"test")
- /* 10 */ /* body */ << I(12)
- /* 12 */ << H(TokLine) << H(1)
- /* 14 */ << H(TokHashLiteral) << HS(L"test")
- /* 22 */ << H(TokCondition)
- /* 23 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("defineTest-{test}")
- << "defineTest(test) { test }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokTestDef) << HS(L"test")
- /* 10 */ /* body */ << I(12)
- /* 12 */ << H(TokLine) << H(1)
- /* 14 */ << H(TokHashLiteral) << HS(L"test")
- /* 22 */ << H(TokCondition)
- /* 23 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("defineTest-{return}")
- << "defineTest(test) { return() }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokTestDef) << HS(L"test")
- /* 10 */ /* body */ << I(4)
- /* 12 */ << H(TokLine) << H(1)
- /* 14 */ << H(TokReturn)
- /* 15 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("defineReplace-{return-stuff}")
- << "defineReplace(stuff) { return(foo bar) }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokReplaceDef) << HS(L"stuff")
- /* 11 */ /* body */ << I(14)
- /* 13 */ << H(TokLine) << H(1)
- /* 15 */ << H(TokLiteral | TokNewStr) << S(L"foo")
- /* 20 */ << H(TokLiteral | TokNewStr) << S(L"bar")
- /* 25 */ << H(TokReturn)
- /* 26 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-AND-defineTest-{}")
- << "test: defineTest(test) {}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokAnd)
- /* 12 */ << H(TokTestDef) << HS(L"test")
- /* 20 */ /* body */ << I(1)
- /* 22 */ << H(TokTerminator))
- << ""
- << true;
-
- QTest::newRow("test-OR-defineTest-{}")
- << "test| defineTest(test) {}"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokOr)
- /* 12 */ << H(TokTestDef) << HS(L"test")
- /* 20 */ /* body */ << I(1)
- /* 22 */ << H(TokTerminator))
- << ""
- << true;
-
- // Operator abuse
-
- QTest::newRow("!")
- << ""
- << TS()
- << ""
- << true;
-
- QTest::newRow("|")
- << ""
- << TS()
- << ""
- << true;
-
- QTest::newRow(":")
- << ""
- << TS()
- << ""
- << true;
-
- QTest::newRow("NOT-assignment")
- << "!VAR ="
- << TS()
- << "in:1: Unexpected NOT operator in front of assignment."
- << false;
-
- QTest::newRow("NOT-{}")
- << "!{}"
- << TS()
- << "in:1: Unexpected NOT operator in front of opening brace."
- << false;
-
- QTest::newRow("NOT-else")
- << "test\n!else {}"
- << TS()
- << "in:2: Unexpected NOT operator in front of else."
- << false;
-
- QTest::newRow("NOT-for-{}")
- << "!for(ever) {}"
- << TS()
- << "in:1: Unexpected NOT operator in front of for()."
- << false;
-
- QTest::newRow("NOT-defineTest-{}")
- << "!defineTest(test) {}"
- << TS()
- << "in:1: Unexpected NOT operator in front of function definition."
- << false;
-
- QTest::newRow("AND-test")
- << ":test"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition))
- << "in:1: AND operator without prior condition."
- << false;
-
- QTest::newRow("test-AND-else")
- << "test:else"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition))
- << "in:1: Unexpected AND operator in front of else."
- << false;
-
- QTest::newRow("test-AND-AND-test")
- << "test::test"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokAnd)
- /* 12 */ << H(TokHashLiteral) << HS(L"test")
- /* 20 */ << H(TokCondition))
- << "WARNING: in:1: Stray AND operator in front of AND operator."
- << true;
-
- QTest::newRow("test-AND-OR-test")
- << "test:|test"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokOr)
- /* 12 */ << H(TokHashLiteral) << HS(L"test")
- /* 20 */ << H(TokCondition))
- << "WARNING: in:1: Stray AND operator in front of OR operator."
- << true;
-
- QTest::newRow("test-{AND-test}")
- << "test { :test }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(10)
- /* 14 */ << H(TokHashLiteral) << HS(L"test")
- /* 22 */ << H(TokCondition)
- /* 23 */ << H(TokTerminator)
- /* 24 */ /* else branch */ << I(0))
- << "in:1: AND operator without prior condition."
- << false;
-
- QTest::newRow("test-OR-assignment")
- << "foo| VAR ="
- << TS()
- << "in:1: Unexpected OR operator in front of assignment."
- << false;
-
- QTest::newRow("test-OR-{}")
- << "foo|{}"
- << TS()
- << "in:1: Unexpected OR operator in front of opening brace."
- << false;
-
- QTest::newRow("test-OR-for")
- << "foo|for(ever) {}"
- << TS()
- << "in:1: Unexpected OR operator in front of for()."
- << false;
-
- QTest::newRow("OR-test")
- << "|test"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition))
- << "in:1: OR operator without prior condition."
- << false;
-
- QTest::newRow("test-OR-else")
- << "test|else"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition))
- << "in:1: Unexpected OR operator in front of else."
- << false;
-
- QTest::newRow("test-OR-OR-test")
- << "test||test"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokOr)
- /* 12 */ << H(TokHashLiteral) << HS(L"test")
- /* 20 */ << H(TokCondition))
- << "WARNING: in:1: Stray OR operator in front of OR operator."
- << true;
-
- QTest::newRow("test-OR-AND-test")
- << "test|:test"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokAnd)
- /* 12 */ << H(TokHashLiteral) << HS(L"test")
- /* 20 */ << H(TokCondition))
- << "WARNING: in:1: Stray OR operator in front of AND operator."
- << true;
-
- QTest::newRow("test-{OR-test}")
- << "test { |test }"
- << TS(
- /* 0 */ << H(TokLine) << H(1)
- /* 2 */ << H(TokHashLiteral) << HS(L"test")
- /* 10 */ << H(TokCondition)
- /* 11 */ << H(TokBranch)
- /* 12 */ /* then branch */ << I(10)
- /* 14 */ << H(TokHashLiteral) << HS(L"test")
- /* 22 */ << H(TokCondition)
- /* 23 */ << H(TokTerminator)
- /* 24 */ /* else branch */ << I(0))
- << "in:1: OR operator without prior condition."
- << false;
-
- // option() (these produce no tokens)
-
- QTest::newRow("option(host_build)")
- << "option(host_build)"
- << TS()
- << ""
- << true;
-
- QTest::newRow("option()")
- << "option()"
- << TS()
- << "in:1: option() requires one literal argument."
- << false;
-
- QTest::newRow("option(host_build magic)")
- << "option(host_build magic)"
- << TS()
- << "in:1: option() requires one literal argument."
- << false;
-
- QTest::newRow("option(host_build, magic)")
- << "option(host_build, magic)"
- << TS()
- << "in:1: option() requires one literal argument."
- << false;
-
- QTest::newRow("option($$OPTION)")
- << "option($$OPTION)"
- << TS()
- << "in:1: option() requires one literal argument."
- << false;
-
- QTest::newRow("{option(host_build)}")
- << "{option(host_build)}"
- << TS()
- << "in:1: option() must appear outside any control structures."
- << false;
+ QString pfx = ((type & QMakeParserHandler::CategoryMask) == QMakeParserHandler::WarningMessage)
+ ? QString::fromLatin1("WARNING: ") : QString();
+ if (lineNo)
+ doPrint(QStringLiteral("%1%2:%3: %4").arg(pfx, fileName, QString::number(lineNo), msg));
+ else
+ doPrint(QStringLiteral("%1%2").arg(pfx, msg));
}
-void tst_qmakelib::proParser()
+void QMakeTestHandler::doPrint(const QString &msg)
{
- QFETCH(QString, in);
- QFETCH(QString, out);
- QFETCH(QString, msgs);
- QFETCH(bool, ok);
-
- bool verified = true;
- QMakeHandler handler;
- handler.setExpectedMessages(msgs.split('\n', QString::SkipEmptyParts));
- QMakeVfs vfs;
- QMakeParser parser(0, &vfs, &handler);
- ProFile *pro = parser.parsedProBlock(in, "in", 1, QMakeParser::FullGrammar);
- if (handler.printedMessages()) {
- qWarning("Got unexpected message(s)");
- verified = false;
- }
- QStringList missingMsgs = handler.expectedMessages();
- if (!missingMsgs.isEmpty()) {
- foreach (const QString &msg, missingMsgs)
- qWarning("Missing message: %s", qPrintable(msg));
- verified = false;
- }
- if (pro->isOk() != ok) {
- static const char * const lbl[] = { "failure", "success" };
- qWarning("Expected %s, got %s", lbl[int(ok)], lbl[1 - int(ok)]);
- verified = false;
- }
- if (pro->items() != out && (ok || !out.isEmpty())) {
- qWarning("Bytecode mismatch.\nActual:%s\nExpected:%s",
- qPrintable(QMakeParser::formatProBlock(pro->items())),
- qPrintable(QMakeParser::formatProBlock(out)));
- verified = false;
+ if (!expected.isEmpty() && expected.first() == msg) {
+ expected.removeAt(0);
+ } else {
+ qWarning("%s", qPrintable(msg));
+ printed = true;
}
- pro->deref();
- QVERIFY(verified);
}
QTEST_MAIN(tst_qmakelib)
-#include "tst_qmakelib.moc"
diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.h b/tests/auto/tools/qmakelib/tst_qmakelib.h
new file mode 100644
index 0000000000..c4716ca65e
--- /dev/null
+++ b/tests/auto/tools/qmakelib/tst_qmakelib.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmakeevaluator.h>
+
+#include <QObject>
+#include <QProcessEnvironment>
+#include <QtTest/QtTest>
+
+class tst_qmakelib : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_qmakelib() {}
+ virtual ~tst_qmakelib() {}
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void quoteArgUnix_data();
+ void quoteArgUnix();
+ void quoteArgWin_data();
+ void quoteArgWin();
+ void pathUtils();
+
+ void proString();
+ void proStringList();
+
+ void proParser_data();
+ void proParser();
+
+ void proEval_data();
+ void proEval();
+
+private:
+ void addParseOperators();
+ void addParseValues();
+ void addParseConditions();
+ void addParseControlStatements();
+ void addParseBraces();
+ void addParseCustomFunctions();
+ void addParseAbuse();
+
+ void addAssignments();
+ void addExpansions();
+ void addControlStructs();
+ void addReplaceFunctions(const QString &qindir);
+ void addTestFunctions(const QString &qindir);
+
+ QProcessEnvironment m_env;
+ QHash<ProKey, ProString> m_prop;
+ QString m_indir, m_outdir;
+};
+
+class QMakeTestHandler : public QMakeHandler {
+public:
+ QMakeTestHandler() : QMakeHandler(), printed(false) {}
+ virtual void message(int type, const QString &msg, const QString &fileName, int lineNo)
+ { print(fileName, lineNo, type, msg); }
+
+ virtual void fileMessage(const QString &msg)
+ { doPrint(msg); }
+
+ virtual void aboutToEval(ProFile *, ProFile *, EvalFileType) {}
+ virtual void doneWithEval(ProFile *) {}
+
+ void setExpectedMessages(const QStringList &msgs) { expected = msgs; }
+ QStringList expectedMessages() const { return expected; }
+
+ bool printedMessages() const { return printed; }
+
+private:
+ void print(const QString &fileName, int lineNo, int type, const QString &msg);
+ void doPrint(const QString &msg);
+
+ QStringList expected;
+ bool printed;
+};
+
diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
index fecc14f541..e62ce3ceb5 100644
--- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
+++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
@@ -564,6 +564,11 @@ void tst_QDialog::snapToDefaultButton()
topLeftPos = QPoint(topLeftPos.x() + 100, topLeftPos.y() + 100);
QPoint startingPos(topLeftPos.x() + 250, topLeftPos.y() + 250);
QCursor::setPos(startingPos);
+#ifdef Q_OS_OSX
+ // On OS X we use CGEventPost to move the cursor, it needs at least
+ // some time before the event handled and the position really set.
+ QTest::qWait(100);
+#endif
QCOMPARE(QCursor::pos(), startingPos);
QDialog dialog;
QPushButton *button = new QPushButton(&dialog);
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
index da0c5532a5..9b92c34fb5 100644
--- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -179,6 +179,7 @@ private slots:
void task250119_shortcutContext();
void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
+ void QTBUG_45867_send_itemChildAddedChange_to_parent();
};
@@ -3490,5 +3491,36 @@ void tst_QGraphicsWidget::QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems()
//This should not crash
}
+void tst_QGraphicsWidget::QTBUG_45867_send_itemChildAddedChange_to_parent()
+{
+ class GraphicsItem : public QGraphicsItem
+ {
+ public:
+ int m_itemChildAddedChangeNotificationsCount;
+
+ GraphicsItem()
+ : QGraphicsItem(),
+ m_itemChildAddedChangeNotificationsCount(0)
+ {
+ }
+
+ QRectF boundingRect() const Q_DECL_OVERRIDE { return QRectF(); }
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) Q_DECL_OVERRIDE {}
+
+ protected:
+ QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) Q_DECL_OVERRIDE
+ {
+ if (change == QGraphicsItem::ItemChildAddedChange)
+ ++m_itemChildAddedChangeNotificationsCount;
+ return QGraphicsItem::itemChange(change, value);
+ }
+ };
+
+ GraphicsItem item;
+ QGraphicsWidget widget(&item);
+ QCOMPARE(item.m_itemChildAddedChangeNotificationsCount, 1);
+}
+
QTEST_MAIN(tst_QGraphicsWidget)
#include "tst_qgraphicswidget.moc"
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index 22245707cc..9b8b306e00 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -48,6 +48,7 @@
#include <QtWidgets/QScrollBar>
#include <QtWidgets/QDialog>
#include <QtWidgets/QStyledItemDelegate>
+#include <QtWidgets/QStyleFactory>
#if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
# include <windows.h>
@@ -2350,11 +2351,34 @@ void tst_QListView::testViewOptions()
QCOMPARE(options.decorationPosition, QStyleOptionViewItem::Top);
}
+// make sure we have no transient scroll bars
+class TempStyleSetter
+{
+public:
+ TempStyleSetter()
+ : m_oldStyle(qApp->style())
+ {
+ m_oldStyle->setParent(0);
+ QListView tempView;
+ if (QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, tempView.horizontalScrollBar()))
+ QApplication::setStyle(QStyleFactory::create("Fusion"));
+ }
+
+ ~TempStyleSetter()
+ {
+ QApplication::setStyle(m_oldStyle);
+ }
+private:
+ QStyle* m_oldStyle;
+};
+
void tst_QListView::taskQTBUG_39902_mutualScrollBars()
{
QWidget window;
window.resize(400, 300);
QListView *view = new QListView(&window);
+ // make sure we have no transient scroll bars
+ TempStyleSetter styleSetter;
QStandardItemModel model(200, 1);
const QSize itemSize(100, 20);
for (int i = 0; i < model.rowCount(); ++i)
@@ -2372,6 +2396,44 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars()
view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
// this will end up in a stack overflow, if QTBUG-39902 is not fixed
QTest::qWait(100);
+
+ // these tests do not apply with transient scroll bars enabled
+ QVERIFY (!view->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, view->horizontalScrollBar()));
+
+ // make it double as large, no scroll bars should be visible
+ view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2);
+ QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+ QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
+
+ // make it half the size, both scroll bars should be visible
+ view->resize((itemSize.width() + view->frameWidth() * 2) / 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) / 2);
+ QTRY_VERIFY(view->horizontalScrollBar()->isVisible());
+ QTRY_VERIFY(view->verticalScrollBar()->isVisible());
+
+ // make it double as large, no scroll bars should be visible
+ view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2);
+ QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+ QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
+
+ // now, coming from the double size, resize it to the exactly matching size, still no scroll bars should be visible again
+ view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
+ QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+ QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
+
+ // now remove just one single pixel in height -> both scroll bars will show up since they depend on each other
+ view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1);
+ QTRY_VERIFY(view->horizontalScrollBar()->isVisible());
+ QTRY_VERIFY(view->verticalScrollBar()->isVisible());
+
+ // now remove just one single pixel in with -> both scroll bars will show up since they depend on each other
+ view->resize(itemSize.width() + view->frameWidth() * 2 - 1, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
+ QTRY_VERIFY(view->horizontalScrollBar()->isVisible());
+ QTRY_VERIFY(view->verticalScrollBar()->isVisible());
+
+ // finally, coming from a size being to small, resize back to the exactly matching size -> both scroll bars should disappear again
+ view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2);
+ QTRY_VERIFY(!view->horizontalScrollBar()->isVisible());
+ QTRY_VERIFY(!view->verticalScrollBar()->isVisible());
}
void tst_QListView::horizontalScrollingByVerticalWheelEvents()
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 6786ae9aa2..dcbdbe824a 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -605,21 +605,21 @@ void tst_QListWidget::insertItems()
void tst_QListWidget::itemAssignment()
{
QListWidgetItem itemInWidget("inWidget", testWidget);
- itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsTristate);
+ itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsUserTristate);
QListWidgetItem itemOutsideWidget("outsideWidget");
QVERIFY(itemInWidget.listWidget());
QCOMPARE(itemInWidget.text(), QString("inWidget"));
- QVERIFY(itemInWidget.flags() & Qt::ItemIsTristate);
+ QVERIFY(itemInWidget.flags() & Qt::ItemIsUserTristate);
QVERIFY(!itemOutsideWidget.listWidget());
QCOMPARE(itemOutsideWidget.text(), QString("outsideWidget"));
- QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsTristate));
+ QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsUserTristate));
itemOutsideWidget = itemInWidget;
QVERIFY(!itemOutsideWidget.listWidget());
QCOMPARE(itemOutsideWidget.text(), QString("inWidget"));
- QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsTristate);
+ QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsUserTristate);
}
void tst_QListWidget::item_data()
diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
index a4c6e13979..36bc23910c 100644
--- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
@@ -281,21 +281,21 @@ void tst_QTableWidget::itemAssignment()
{
QTableWidgetItem itemInWidget("inWidget");
testWidget->setItem(0, 0, &itemInWidget);
- itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsTristate);
+ itemInWidget.setFlags(itemInWidget.flags() | Qt::ItemIsUserTristate);
QTableWidgetItem itemOutsideWidget("outsideWidget");
QVERIFY(itemInWidget.tableWidget());
QCOMPARE(itemInWidget.text(), QString("inWidget"));
- QVERIFY(itemInWidget.flags() & Qt::ItemIsTristate);
+ QVERIFY(itemInWidget.flags() & Qt::ItemIsUserTristate);
QVERIFY(!itemOutsideWidget.tableWidget());
QCOMPARE(itemOutsideWidget.text(), QString("outsideWidget"));
- QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsTristate));
+ QVERIFY(!(itemOutsideWidget.flags() & Qt::ItemIsUserTristate));
itemOutsideWidget = itemInWidget;
QVERIFY(!itemOutsideWidget.tableWidget());
QCOMPARE(itemOutsideWidget.text(), QString("inWidget"));
- QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsTristate);
+ QVERIFY(itemOutsideWidget.flags() & Qt::ItemIsUserTristate);
}
void tst_QTableWidget::item_data()
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 3ead172d82..1324027af6 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -255,6 +255,7 @@ private slots:
void taskQTBUG_8176_emitOnExpandAll();
void taskQTBUG_34717_collapseAtBottom();
void taskQTBUG_37813_crash();
+ void taskQTBUG_45697_crash();
void testInitialFocus();
};
@@ -4385,5 +4386,82 @@ void tst_QTreeView::taskQTBUG_37813_crash()
#endif // QT_BUILD_INTERNAL
}
+// QTBUG-45697: Using a QTreeView with a multi-column model filtered by QSortFilterProxyModel,
+// when sorting the source model while the widget is not yet visible and showing the widget
+// later on, corruption occurs in QTreeView.
+class Qtbug45697TestWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ static const int columnCount = 3;
+
+ explicit Qtbug45697TestWidget();
+ int timerTick() const { return m_timerTick; }
+
+public slots:
+ void slotTimer();
+
+private:
+ QTreeView *m_treeView;
+ QStandardItemModel *m_model;
+ QSortFilterProxyModel *m_sortFilterProxyModel;
+ int m_timerTick;
+};
+
+Qtbug45697TestWidget::Qtbug45697TestWidget()
+ : m_treeView(new QTreeView(this))
+ , m_model(new QStandardItemModel(0, Qtbug45697TestWidget::columnCount, this))
+ , m_sortFilterProxyModel(new QSortFilterProxyModel(this))
+ , m_timerTick(0)
+ {
+ QVBoxLayout *vBoxLayout = new QVBoxLayout(this);
+ vBoxLayout->addWidget(m_treeView);
+
+ for (char sortChar = 'z'; sortChar >= 'a' ; --sortChar) {
+ QList<QStandardItem *> items;
+ for (int column = 0; column < Qtbug45697TestWidget::columnCount; ++column) {
+ const QString text = QLatin1Char(sortChar) + QLatin1String(" ") + QString::number(column);
+ items.append(new QStandardItem(text));
+ }
+ m_model->appendRow(items);
+ }
+
+ m_sortFilterProxyModel->setSourceModel(m_model);
+ m_treeView->setModel(m_sortFilterProxyModel);
+
+ QHeaderView *headerView = m_treeView->header();
+ for (int s = 1, lastSection = headerView->count() - 1; s < lastSection; ++s )
+ headerView->setSectionResizeMode(s, QHeaderView::ResizeToContents);
+
+ QTimer *timer = new QTimer(this);
+ timer->setInterval(50);
+ connect(timer, &QTimer::timeout, this, &Qtbug45697TestWidget::slotTimer);
+ timer->start();
+}
+
+void Qtbug45697TestWidget::slotTimer()
+{
+ switch (m_timerTick++) {
+ case 0:
+ m_model->sort(0);
+ break;
+ case 1:
+ show();
+ break;
+ default:
+ close();
+ break;
+ }
+}
+
+void tst_QTreeView::taskQTBUG_45697_crash()
+{
+ Qtbug45697TestWidget testWidget;
+ testWidget.setWindowTitle(QTest::currentTestFunction());
+ testWidget.resize(400, 400);
+ testWidget.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(100, 100));
+ QTRY_VERIFY(testWidget.timerTick() >= 2);
+}
+
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index c9a1a64135..c33fd5a951 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -178,6 +178,12 @@ private slots:
void settableStyleHints_data();
void settableStyleHints(); // Needs to run last as it changes style hints.
+
+protected slots:
+ void quitApplication();
+
+private:
+ bool quitApplicationTriggered;
};
class EventSpy : public QObject
@@ -235,6 +241,7 @@ public:
static char *argv0;
tst_QApplication::tst_QApplication()
+ : quitApplicationTriggered(false)
{
#ifdef Q_OS_WINCE
// Clean up environment previously to launching test
@@ -719,11 +726,8 @@ void tst_QApplication::quitOnLastWindowClosed()
{
int argc = 0;
QApplication app(argc, 0);
- QTimer timer;
- timer.setInterval(100);
QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
- QSignalSpy spy2(&timer, SIGNAL(timeout()));
CloseEventTestWindow mainWindow;
@@ -733,14 +737,14 @@ void tst_QApplication::quitOnLastWindowClosed()
mainWindow.show();
QVERIFY(QTest::qWaitForWindowExposed(&mainWindow));
- timer.start();
- QTimer::singleShot(1000, &mainWindow, SLOT(close())); // This should quit the application
- QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
+ QTimer::singleShot(1000, &mainWindow, SLOT(close())); // This should NOT quit the application (see CloseEventTestWindow)
+ quitApplicationTriggered = false;
+ QTimer::singleShot(2000, this, SLOT(quitApplication())); // This actually quits the application.
app.exec();
QCOMPARE(spy.count(), 1);
- QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not caused the quit
+ QVERIFY(quitApplicationTriggered);
}
{
int argc = 0;
@@ -768,24 +772,20 @@ void tst_QApplication::quitOnLastWindowClosed()
QApplication app(argc, 0);
QVERIFY(app.quitOnLastWindowClosed());
- QTimer timer;
- timer.setInterval(100);
- QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
-
QWindow w;
w.show();
QWidget wid;
wid.show();
- timer.start();
QTimer::singleShot(1000, &wid, SLOT(close())); // This should NOT quit the application because the
// QWindow is still there.
- QTimer::singleShot(2000, &app, SLOT(quit())); // This causes the quit.
+ quitApplicationTriggered = false;
+ QTimer::singleShot(2000, this, SLOT(quitApplication())); // This causes the quit.
app.exec();
- QVERIFY(timerSpy.count() > 15); // Should be around 20 if closing did not caused the quit
+ QVERIFY(quitApplicationTriggered); // Should be around 20 if closing did not caused the quit
}
{ // QTBUG-31569: If the last widget with Qt::WA_QuitOnClose set is closed, other
// widgets that don't have the attribute set should be closed automatically.
@@ -2406,6 +2406,12 @@ void tst_QApplication::globalStaticObjectDestruction()
#endif
}
+void tst_QApplication::quitApplication()
+{
+ quitApplicationTriggered = true;
+ qApp->quit();
+}
+
//QTEST_APPLESS_MAIN(tst_QApplication)
int main(int argc, char *argv[])
{
diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
index ebd99be786..0de9e188a0 100644
--- a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
+++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
@@ -34,30 +34,32 @@
#include <QtTest/QtTest>
#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qscreen.h>
class tst_QToolTip : public QObject
{
Q_OBJECT
-public:
- tst_QToolTip() {}
- virtual ~tst_QToolTip() {}
-
-public slots:
- void initTestCase() {}
- void cleanupTestCase() {}
- void init() {}
- void cleanup() {}
-
private slots:
-
- // task-specific tests below me
+ void init();
+ void cleanup();
void task183679_data();
void task183679();
void whatsThis();
void setPalette();
};
+void tst_QToolTip::init()
+{
+ QVERIFY(!QToolTip::isVisible());
+}
+
+void tst_QToolTip::cleanup()
+{
+ QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty());
+}
+
class Widget_task183679 : public QWidget
{
Q_OBJECT
@@ -100,12 +102,14 @@ void tst_QToolTip::task183679()
#endif
Widget_task183679 widget;
+ widget.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(50, 50));
+ widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())
+ + QLatin1Char(' ') + QLatin1String(QTest::currentDataTag()));
widget.show();
QApplication::setActiveWindow(&widget);
QVERIFY(QTest::qWaitForWindowActive(&widget));
widget.showDelayedToolTip(100);
- QTest::qWait(300);
QTRY_VERIFY(QToolTip::isVisible());
QTest::keyPress(&widget, key);
@@ -116,26 +120,31 @@ void tst_QToolTip::task183679()
QTest::qWait(1500);
QCOMPARE(QToolTip::isVisible(), visible);
+ if (visible)
+ QToolTip::hideText();
}
-#include <QWhatsThis>
+static QWidget *findWhatsThat()
+{
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget->inherits("QWhatsThat"))
+ return widget;
+ }
+ return Q_NULLPTR;
+}
void tst_QToolTip::whatsThis()
{
qApp->setStyleSheet( "QWidget { font-size: 72px; }" );
- QWhatsThis::showText(QPoint(0,0), "THis is text");
- QTest::qWait(400);
- QWidget *whatsthis = 0;
- foreach (QWidget *widget, QApplication::topLevelWidgets()) {
- if (widget->inherits("QWhatsThat")) {
- whatsthis = widget;
- break;
- }
- }
- QVERIFY(whatsthis);
+ QWhatsThis::showText(QPoint(0, 0), "This is text");
+
+ QWidget *whatsthis = Q_NULLPTR;
+ QTRY_VERIFY( (whatsthis = findWhatsThat()) );
QVERIFY(whatsthis->isVisible());
- QVERIFY(whatsthis->height() > 100); // Test QTBUG-2416
- qApp->setStyleSheet("");
+ const int whatsThisHeight = whatsthis->height();
+ qApp->setStyleSheet(QString());
+ QWhatsThis::hideText();
+ QVERIFY2(whatsThisHeight > 100, QByteArray::number(whatsThisHeight)); // Test QTBUG-2416
}
@@ -167,6 +176,7 @@ void tst_QToolTip::setPalette()
newPalette.setColor(QPalette::ToolTipText, Qt::blue);
QToolTip::setPalette(newPalette);
QCOMPARE(toolTip->palette(), newPalette);
+ QToolTip::hideText();
}
QTEST_MAIN(tst_QToolTip)
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index ed40f98051..591aa9e40f 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -1,11 +1,16 @@
+# OSX QTBUG-25300 QTBUG-45502
[normalGeometry]
ubuntu-14.04
+osx
[saveRestoreGeometry]
ubuntu-14.04
+osx
[restoreVersion1Geometry]
ubuntu-14.04
+osx
[updateWhileMinimized]
ubuntu-14.04
+osx
[focusProxyAndInputMethods]
ubuntu-14.04
[touchEventSynthesizedMouseEvent]
@@ -14,3 +19,119 @@ ubuntu-14.04
ubuntu-14.04
[largerThanScreen_QTBUG30142]
ubuntu-14.04
+[windowState]
+osx
+[showMaximized]
+osx
+[setGeometry]
+osx
+[stackUnder]
+osx
+[raise]
+osx-10.9
+[widgetAt]
+osx
+[sheetOpacity]
+osx
+[resizeEvent]
+osx
+[setWindowGeometry:100,123 200x200, flags 0]
+osx-10.10
+[windowMoveResize:100,123 200x200, flags 0]
+osx-10.10
+[setWindowGeometry:100,122 200x200, flags 0]
+osx-10.9
+[windowMoveResize:100,122 200x200, flags 0]
+osx-10.9
+[setWindowGeometry:100,100 824x564, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x564, flags 0]
+osx-10.10
+[setWindowGeometry:100,100 824x516, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x516, flags 0]
+osx-10.10
+[setWindowGeometry:100,73 200x0, flags 0]
+osx-10.10
+[windowMoveResize:100,73 200x0, flags 0]
+osx-10.10
+[setWindowGeometry:100,100 824x519, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x519, flags 0]
+osx-10.10
+[setWindowGeometry:100,100 824x518, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x518, flags 0]
+osx-10.10
+[setWindowGeometry:100,72 200x0, flags 0]
+osx-10.9
+[windowMoveResize:100,72 200x0, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x574, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x574, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x578, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x578, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x576, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x576, flags 0]
+osx-10.9
+[setWindowGeometry:100,100 824x521, flags 0]
+osx-10.10
+[windowMoveResize:100,100 824x521, flags 0]
+osx-10.10
+[setWindowGeometry:100,122 952x577, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x577, flags 0]
+osx-10.9
+[setWindowGeometry:100,122 952x580, flags 0]
+osx-10.9
+[windowMoveResize:100,122 952x580, flags 0]
+osx-10.9
+[windowMoveResize:130,72 0x0, flags 0]
+osx-10.9
+[windowMoveResize:130,122 0x200, flags 0]
+osx-10.9
+[childEvents]
+osx
+[renderInvisible]
+osx
+[optimizedResizeMove]
+osx
+[optimizedResize_topLevel]
+osx
+[render_systemClip]
+osx
+[update]
+osx
+[doubleRepaint]
+osx
+[childAt_unifiedToolBar]
+osx
+[showMinimizedKeepsFocus]
+osx-10.10
+[moveWindowInShowEvent:1]
+osx-10.9
+[moveWindowInShowEvent:2]
+osx-10.9
+[taskQTBUG_4055_sendSyntheticEnterLeave]
+osx
+[syntheticEnterLeave]
+osx
+[maskedUpdate]
+osx
+[hideWhenFocusWidgetIsChild]
+osx-10.10
+[hideOpaqueChildWhileHidden]
+osx
+[resizeStaticContentsChildWidget_QTBUG35282]
+osx-10.9
+[lower]
+osx
+[setClearAndResizeMask]
+osx
+[setToolTip]
+osx-10.9
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
index 30e1048247..aae083d45e 100644
--- a/tests/auto/widgets/kernel/qwidget/qwidget.pro
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -21,5 +21,3 @@ x11 {
}
!wince*:win32:!winrt: LIBS += -luser32 -lgdi32
-
-mac:CONFIG+=insignificant_test # QTBUG-25300, QTBUG-23695
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 10c553bd3e..68ccaef43f 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -436,6 +436,7 @@ private slots:
void grabKeyboard();
void touchEventSynthesizedMouseEvent();
+ void touchUpdateOnNewTouch();
void styleSheetPropagation();
@@ -3335,8 +3336,6 @@ void tst_QWidget::widgetAt()
#if defined(Q_OS_WINCE)
QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
#endif
- if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
- QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
QTRY_VERIFY((wr = QApplication::widgetAt(testPos)));
QTRY_COMPARE(wr->objectName(), w1->objectName());
@@ -3355,8 +3354,6 @@ void tst_QWidget::widgetAt()
#if defined(Q_OS_WINCE)
QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
#endif
- if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
- QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
QTRY_VERIFY(QApplication::widgetAt(testPos) == w1.data());
QTRY_VERIFY(QApplication::widgetAt(testPos + QPoint(1, 1)) == w2.data());
}
@@ -9757,6 +9754,9 @@ class TouchMouseWidget : public QWidget {
public:
explicit TouchMouseWidget(QWidget *parent = 0)
: QWidget(parent),
+ m_touchBeginCount(0),
+ m_touchUpdateCount(0),
+ m_touchEndCount(0),
m_touchEventCount(0),
m_acceptTouch(false),
m_mouseEventCount(0),
@@ -9783,6 +9783,12 @@ protected:
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
+ if (e->type() == QEvent::TouchBegin)
+ ++m_touchBeginCount;
+ else if (e->type() == QEvent::TouchUpdate)
+ ++m_touchUpdateCount;
+ else if (e->type() == QEvent::TouchEnd)
+ ++m_touchEndCount;
++m_touchEventCount;
if (m_acceptTouch)
e->accept();
@@ -9807,6 +9813,9 @@ protected:
}
public:
+ int m_touchBeginCount;
+ int m_touchUpdateCount;
+ int m_touchEndCount;
int m_touchEventCount;
bool m_acceptTouch;
int m_mouseEventCount;
@@ -9923,6 +9932,46 @@ void tst_QWidget::touchEventSynthesizedMouseEvent()
}
}
+void tst_QWidget::touchUpdateOnNewTouch()
+{
+ QTouchDevice *device = new QTouchDevice;
+ device->setType(QTouchDevice::TouchScreen);
+ QWindowSystemInterface::registerTouchDevice(device);
+
+ TouchMouseWidget widget;
+ widget.setAcceptTouch(true);
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(new QWidget);
+ widget.setLayout(layout);
+ widget.show();
+
+ QWindow* window = widget.windowHandle();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ QCOMPARE(widget.m_touchBeginCount, 0);
+ QCOMPARE(widget.m_touchUpdateCount, 0);
+ QCOMPARE(widget.m_touchEndCount, 0);
+ QTest::touchEvent(window, device).press(0, QPoint(20, 20), window);
+ QCOMPARE(widget.m_touchBeginCount, 1);
+ QCOMPARE(widget.m_touchUpdateCount, 0);
+ QCOMPARE(widget.m_touchEndCount, 0);
+ QTest::touchEvent(window, device).move(0, QPoint(25, 25), window);
+ QCOMPARE(widget.m_touchBeginCount, 1);
+ QCOMPARE(widget.m_touchUpdateCount, 1);
+ QCOMPARE(widget.m_touchEndCount, 0);
+ QTest::touchEvent(window, device).stationary(0).press(1, QPoint(40, 40), window);
+ QCOMPARE(widget.m_touchBeginCount, 1);
+ QCOMPARE(widget.m_touchUpdateCount, 2);
+ QCOMPARE(widget.m_touchEndCount, 0);
+ QTest::touchEvent(window, device).stationary(1).release(0, QPoint(25, 25), window);
+ QCOMPARE(widget.m_touchBeginCount, 1);
+ QCOMPARE(widget.m_touchUpdateCount, 3);
+ QCOMPARE(widget.m_touchEndCount, 0);
+ QTest::touchEvent(window, device).release(1, QPoint(40, 40), window);
+ QCOMPARE(widget.m_touchBeginCount, 1);
+ QCOMPARE(widget.m_touchUpdateCount, 3);
+ QCOMPARE(widget.m_touchEndCount, 1);
+}
+
void tst_QWidget::styleSheetPropagation()
{
QTableView tw;
diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
index 9c549365ff..38b473e5ae 100644
--- a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
+++ b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp
@@ -90,6 +90,7 @@ private slots:
// void buttons();
void testDelete();
+ void testSignalEmissionAfterDelete_QTBUG_45835();
void testRemove();
void testMultipleAdd();
void testStandardButtonMapping_data();
@@ -111,6 +112,7 @@ private:
tst_QDialogButtonBox::tst_QDialogButtonBox()
{
+ qRegisterMetaType<QAbstractButton *>();
}
tst_QDialogButtonBox::~tst_QDialogButtonBox()
@@ -414,6 +416,70 @@ void tst_QDialogButtonBox::testDelete()
QCOMPARE(buttonBox.buttons().count(), 0);
}
+class ObjectDeleter : public QObject
+{
+ Q_OBJECT
+public slots:
+ void deleteButton(QAbstractButton *button)
+ {
+ delete button;
+ }
+
+ void deleteSender()
+ {
+ delete sender();
+ }
+};
+
+void tst_QDialogButtonBox::testSignalEmissionAfterDelete_QTBUG_45835()
+{
+ {
+ QDialogButtonBox buttonBox;
+ QCOMPARE(buttonBox.buttons().count(), 0);
+
+ QSignalSpy buttonClickedSpy(&buttonBox, &QDialogButtonBox::clicked);
+ QVERIFY(buttonClickedSpy.isValid());
+
+ QSignalSpy buttonBoxAcceptedSpy(&buttonBox, &QDialogButtonBox::accepted);
+ QVERIFY(buttonBoxAcceptedSpy.isValid());
+
+ QPushButton *button = buttonBox.addButton("Test", QDialogButtonBox::AcceptRole);
+ QCOMPARE(buttonBox.buttons().count(), 1);
+
+ ObjectDeleter objectDeleter;
+ connect(&buttonBox, &QDialogButtonBox::clicked, &objectDeleter, &ObjectDeleter::deleteButton);
+
+ button->click();
+
+ QCOMPARE(buttonBox.buttons().count(), 0);
+ QCOMPARE(buttonClickedSpy.count(), 1);
+ QCOMPARE(buttonBoxAcceptedSpy.count(), 1);
+ }
+
+ {
+ QPointer<QDialogButtonBox> buttonBox(new QDialogButtonBox);
+ QCOMPARE(buttonBox->buttons().count(), 0);
+
+ QSignalSpy buttonClickedSpy(buttonBox.data(), &QDialogButtonBox::clicked);
+ QVERIFY(buttonClickedSpy.isValid());
+
+ QSignalSpy buttonBoxAcceptedSpy(buttonBox.data(), &QDialogButtonBox::accepted);
+ QVERIFY(buttonBoxAcceptedSpy.isValid());
+
+ QPushButton *button = buttonBox->addButton("Test", QDialogButtonBox::AcceptRole);
+ QCOMPARE(buttonBox->buttons().count(), 1);
+
+ ObjectDeleter objectDeleter;
+ connect(buttonBox.data(), &QDialogButtonBox::clicked, &objectDeleter, &ObjectDeleter::deleteSender);
+
+ button->click();
+
+ QVERIFY(buttonBox.isNull());
+ QCOMPARE(buttonClickedSpy.count(), 1);
+ QCOMPARE(buttonBoxAcceptedSpy.count(), 0);
+ }
+}
+
void tst_QDialogButtonBox::testMultipleAdd()
{
// Add a button into the thing multiple times.
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index ade9f72543..2bbc2e05b7 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -764,6 +764,8 @@ void tst_QDockWidget::restoreDockWidget()
restoreWindow.show();
QVERIFY(QTest::qWaitForWindowExposed(&restoreWindow));
QTRY_VERIFY(dock->isFloating());
+ if (!QGuiApplication::platformName().compare("xcb", Qt::CaseInsensitive))
+ QSKIP("Skip due to Window manager positioning issues", Abort);
QTRY_COMPARE(dock->pos(), dockPos);
}
}
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 9417541040..adedc601a9 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -304,6 +304,7 @@ private slots:
void undoRedoAndEchoModes();
void clearButton();
+ void clearButtonVisibleAfterSettingText_QTBUG_45518();
void sideWidgets();
void shouldShowPlaceholderText_data();
@@ -4273,6 +4274,50 @@ void tst_QLineEdit::clearButton()
QVERIFY(!clearButton->isEnabled());
}
+void tst_QLineEdit::clearButtonVisibleAfterSettingText_QTBUG_45518()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("This test requires a developer build");
+#else
+ QLineEdit edit;
+ edit.setMinimumWidth(200);
+ centerOnScreen(&edit);
+ QLineEditIconButton *clearButton;
+ clearButton = edit.findChild<QLineEditIconButton *>();
+ QVERIFY(!clearButton);
+
+ edit.setText(QStringLiteral("some text"));
+ edit.show();
+ QVERIFY(QTest::qWaitForWindowActive(&edit));
+
+ QVERIFY(!edit.isClearButtonEnabled());
+
+ clearButton = edit.findChild<QLineEditIconButton *>();
+ QVERIFY(!clearButton);
+
+ edit.setClearButtonEnabled(true);
+ QVERIFY(edit.isClearButtonEnabled());
+
+ clearButton = edit.findChild<QLineEditIconButton *>();
+ QVERIFY(clearButton);
+ QVERIFY(clearButton->isVisible());
+
+ QTRY_VERIFY(clearButton->opacity() > 0);
+ QTRY_COMPARE(clearButton->cursor().shape(), Qt::ArrowCursor);
+
+ QTest::mouseClick(clearButton, Qt::LeftButton, 0, clearButton->rect().center());
+ QTRY_COMPARE(edit.text(), QString());
+
+ QTRY_COMPARE(clearButton->opacity(), qreal(0));
+ QTRY_COMPARE(clearButton->cursor().shape(), clearButton->parentWidget()->cursor().shape());
+
+ edit.setClearButtonEnabled(false);
+ QVERIFY(!edit.isClearButtonEnabled());
+ clearButton = edit.findChild<QLineEditIconButton *>();
+ QVERIFY(!clearButton);
+#endif // QT_BUILD_INTERNAL
+}
+
void tst_QLineEdit::sideWidgets()
{
QWidget testWidget;
diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST
new file mode 100644
index 0000000000..de49d5ff45
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST
@@ -0,0 +1,2 @@
+[task258920_mouseBorder]
+osx
diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
index 53ea4a9148..424ab2ceed 100644
--- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
@@ -2,3 +2,5 @@
ubuntu-14.04
[taskQTBUG4965_escapeEaten]
ubuntu-14.04
+[task256322_highlight]
+osx