From 48c38aae10e5fe9c85e0e045916f6abfed936463 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 15 May 2015 21:05:44 +0200 Subject: [PATCH] move parser test to a separate file for better structure. Change-Id: I16bd1ca245640e92ffe167241a5a565e7a550e1d Reviewed-by: Joerg Bornemann --- tests/auto/tools/qmakelib/parsertest.cpp | 1966 +++++++++++++++++++ tests/auto/tools/qmakelib/qmakelib.pro | 4 + tests/auto/tools/qmakelib/tst_qmakelib.cpp | 2002 +------------------- tests/auto/tools/qmakelib/tst_qmakelib.h | 77 + 4 files changed, 2061 insertions(+), 1988 deletions(-) create mode 100644 tests/auto/tools/qmakelib/parsertest.cpp create mode 100644 tests/auto/tools/qmakelib/tst_qmakelib.h diff --git a/tests/auto/tools/qmakelib/parsertest.cpp b/tests/auto/tools/qmakelib/parsertest.cpp new file mode 100644 index 0000000000..2fe8e90b51 --- /dev/null +++ b/tests/auto/tools/qmakelib/parsertest.cpp @@ -0,0 +1,1966 @@ +/**************************************************************************** +** +** 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 +#include +#include + +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::proParser_data() +{ + QTest::addColumn("in"); + QTest::addColumn("out"); + QTest::addColumn("msgs"); + QTest::addColumn("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; + + 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; + + // 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; +} + +QT_WARNING_POP + +void tst_qmakelib::proParser() +{ + 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; + } + pro->deref(); + QVERIFY(verified); +} diff --git a/tests/auto/tools/qmakelib/qmakelib.pro b/tests/auto/tools/qmakelib/qmakelib.pro index e7807838aa..41aae95068 100644 --- a/tests/auto/tools/qmakelib/qmakelib.pro +++ b/tests/auto/tools/qmakelib/qmakelib.pro @@ -6,8 +6,12 @@ QT = core testlib INCLUDEPATH += ../../../../qmake/library VPATH += ../../../../qmake/library +HEADERS += \ + tst_qmakelib.h + SOURCES += \ tst_qmakelib.cpp \ + parsertest.cpp \ ioutils.cpp \ proitems.cpp \ qmakevfs.cpp \ diff --git a/tests/auto/tools/qmakelib/tst_qmakelib.cpp b/tests/auto/tools/qmakelib/tst_qmakelib.cpp index ab14de0e24..5caa730a19 100644 --- a/tests/auto/tools/qmakelib/tst_qmakelib.cpp +++ b/tests/auto/tools/qmakelib/tst_qmakelib.cpp @@ -31,39 +31,12 @@ ** ****************************************************************************/ -#include +#include "tst_qmakelib.h" #include -#include -#include -#include - -#include using namespace QMakeInternal; -class tst_qmakelib : public QObject -{ - Q_OBJECT - -public: - tst_qmakelib() {} - virtual ~tst_qmakelib() {} - -private slots: - void quoteArgUnix_data(); - void quoteArgUnix(); - void quoteArgWin_data(); - void quoteArgWin(); - void pathUtils(); - - void proString(); - void proStringList(); - - void proParser_data(); - void proParser(); -}; - void tst_qmakelib::proString() { QString qs1(QStringLiteral("this is a string")); @@ -252,1968 +225,21 @@ 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 QMakeHandler::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)) - -QT_WARNING_PUSH -QT_WARNING_DISABLE_MSVC(4003) // "not enough actual parameters for macro TS()" - -void tst_qmakelib::proParser_data() -{ - QTest::addColumn("in"); - QTest::addColumn("out"); - QTest::addColumn("msgs"); - QTest::addColumn("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; - - 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; - - // 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; -} - -QT_WARNING_POP - -void tst_qmakelib::proParser() -{ - 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; + 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; } - 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); + qWarning("%s", qPrintable(out)); + printed = true; } 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..1ae408bfc1 --- /dev/null +++ b/tests/auto/tools/qmakelib/tst_qmakelib.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 + +#include +#include + +class tst_qmakelib : public QObject +{ + Q_OBJECT + +public: + tst_qmakelib() {} + virtual ~tst_qmakelib() {} + +private slots: + void quoteArgUnix_data(); + void quoteArgUnix(); + void quoteArgWin_data(); + void quoteArgWin(); + void pathUtils(); + + void proString(); + void proStringList(); + + void proParser_data(); + void proParser(); +}; + +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); + + QStringList expected; + bool printed; +};