26b1cf2bba
The Qt version was added in 5.14 "for use as eventual replacement for QString::SplitBehavior." Move another step closer to that goal. Change-Id: I3f1b836cfb47bba0fdc27f2c3aa7b0576d123dca Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2059 lines
69 KiB
C++
2059 lines
69 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
|
** 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 https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "tst_qmakelib.h"
|
|
|
|
#include <proitems.h>
|
|
#include <qmakevfs.h>
|
|
#include <qmakeparser.h>
|
|
|
|
class TokenStream
|
|
{
|
|
public:
|
|
TokenStream() {}
|
|
QString toString() const { return ts; }
|
|
|
|
TokenStream &operator<<(ushort n) { ts += QChar(n); return *this; }
|
|
TokenStream &operator<<(uint n) { ts += QChar(n & 0xffff); ts += QChar(n >> 16); return *this; }
|
|
TokenStream &operator<<(const QStringRef &s) { ts += s; return *this; }
|
|
TokenStream &operator<<(const ProString &s) { return *this << ushort(s.length()) << s.toQStringRef(); }
|
|
TokenStream &operator<<(const ProKey &s) { return *this << s.hash() << s.toString(); }
|
|
|
|
private:
|
|
QString ts;
|
|
};
|
|
|
|
#define TS(s) (TokenStream() s).toString()
|
|
#define H(n) ushort(n)
|
|
#define I(n) uint(n)
|
|
#define S(s) ProString(QString::fromWCharArray(s))
|
|
#define HS(s) ProKey(QString::fromWCharArray(s))
|
|
|
|
QT_WARNING_PUSH
|
|
QT_WARNING_DISABLE_MSVC(4003) // "not enough actual parameters for macro TS()"
|
|
|
|
void tst_qmakelib::addParseOperators()
|
|
{
|
|
QTest::newRow("assign none")
|
|
<< "VAR ="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAssign) << H(0)
|
|
/* 11 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("append none")
|
|
<< "VAR +="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAppend) << H(0)
|
|
/* 11 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("unique append none")
|
|
<< "VAR *="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAppendUnique) << H(0)
|
|
/* 11 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("remove none")
|
|
<< "VAR -="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokRemove) << H(0)
|
|
/* 11 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("replace empty")
|
|
<< "VAR ~="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokReplace) << H(0)
|
|
/* 11 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("assignment without variable")
|
|
<< "="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokAssign) << H(0)
|
|
/* 4 */ << H(TokValueTerminator))
|
|
<< "in:1: Assignment needs exactly one word on the left hand side."
|
|
<< false;
|
|
|
|
QTest::newRow("assignment with multiple variables")
|
|
<< "VAR VAR ="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokAssign) << H(0)
|
|
/* 4 */ << H(TokValueTerminator))
|
|
<< "in:1: Assignment needs exactly one word on the left hand side."
|
|
<< false;
|
|
}
|
|
|
|
void tst_qmakelib::addParseValues()
|
|
{
|
|
#define ASSIGN_VAR(h) \
|
|
H(TokLine) << H(1) \
|
|
<< H(TokHashLiteral) << HS(L"VAR") \
|
|
<< H(TokAssign) << H(h)
|
|
|
|
QTest::newRow("one literal")
|
|
<< "VAR = val"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"val")
|
|
/* 16 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("one literal (squeezed)")
|
|
<< "VAR=val"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"val")
|
|
/* 16 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("many literals")
|
|
<< "VAR = foo barbaz bak hello"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(4)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
|
|
/* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
|
|
/* 29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
|
|
/* 36 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("many literals (tab-separated")
|
|
<< "VAR\t=\tfoo\tbarbaz\tbak\thello"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(4)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
|
|
/* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak")
|
|
/* 29 */ << H(TokLiteral | TokNewStr) << S(L"hello")
|
|
/* 36 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("one quoted literal")
|
|
<< "VAR = \"val ue\""
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"val ue")
|
|
/* 19 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("quoted literal with missing quote")
|
|
<< "VAR = val \"ue"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAssign) << H(0)
|
|
/* 11 */ << H(TokValueTerminator))
|
|
<< "in:1: Missing closing \" quote"
|
|
<< false;
|
|
|
|
QTest::newRow("many quoted literals")
|
|
<< "VAR = \"foo\" barbaz 'bak hello' \"\""
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(3)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
|
|
/* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak hello")
|
|
/* 35 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("many quoted literals (with tabs)")
|
|
<< "VAR\t=\t\"foo\"\tbarbaz\t'bak\thello'"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(3)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokLiteral | TokNewStr) << S(L"barbaz")
|
|
/* 24 */ << H(TokLiteral | TokNewStr) << S(L"bak\thello")
|
|
/* 35 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("quoted and unquoted spaces")
|
|
<< " VAR = \"val ue \" "
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"val ue ")
|
|
/* 22 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("funny literals")
|
|
<< "VAR = foo:bar|!baz(blam!, ${foo})"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(2)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo:bar|!baz(blam!,")
|
|
/* 32 */ << H(TokLiteral | TokNewStr) << S(L"${foo})")
|
|
/* 41 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("literals with escapes")
|
|
<< "VAR = \\{hi\\} \\[ho\\] \\)uh\\( \"\\\\oh\\$\"\\' \\$\\${FOO}"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(5)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"{hi}")
|
|
/* 17 */ << H(TokLiteral | TokNewStr) << S(L"[ho]")
|
|
/* 23 */ << H(TokLiteral | TokNewStr) << S(L")uh(")
|
|
/* 29 */ << H(TokLiteral | TokNewStr) << S(L"\\oh$'")
|
|
/* 36 */ << H(TokLiteral | TokNewStr) << S(L"$${FOO}")
|
|
/* 45 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("magic variables")
|
|
<< "VAR = $$LITERAL_HASH $$LITERAL_DOLLAR $$LITERAL_WHITESPACE $$_FILE_ $$_LINE_"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(5)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"#")
|
|
/* 14 */ << H(TokLiteral | TokNewStr) << S(L"$")
|
|
/* 17 */ << H(TokLiteral | TokNewStr) << S(L"\t")
|
|
/* 20 */ << H(TokLiteral | TokNewStr) << S(L"in")
|
|
/* 24 */ << H(TokLiteral | TokNewStr) << S(L"1")
|
|
/* 27 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("continuations and comments")
|
|
<< "VAR = foo \\\n bar\n \n"
|
|
"GAR = foo \\ # comment\n bar \\\n # comment\n baz \\\n"
|
|
"\"quoted \\ #comment\n escape\" \\\n right\\\n after \\\n gorilla!\n \n\n"
|
|
"MOO = \\\n kuh # comment\nLOO =\n\n"
|
|
"FOO = bar \\\n# comment\n baz \\\n \n# comment\n"
|
|
"GAZ="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAssign) << H(2)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokLiteral | TokNewStr) << S(L"bar")
|
|
/* 21 */ << H(TokValueTerminator)
|
|
/* 22 */ << H(TokLine) << H(4)
|
|
/* 24 */ << H(TokHashLiteral) << HS(L"GAR")
|
|
/* 31 */ << H(TokAssign) << H(7)
|
|
/* 33 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 38 */ << H(TokLiteral | TokNewStr) << S(L"bar")
|
|
/* 43 */ << H(TokLiteral | TokNewStr) << S(L"baz")
|
|
/* 48 */ << H(TokLiteral | TokNewStr) << S(L"quoted escape")
|
|
/* 64 */ << H(TokLiteral | TokNewStr) << S(L"right")
|
|
/* 71 */ << H(TokLiteral | TokNewStr) << S(L"after")
|
|
/* 78 */ << H(TokLiteral | TokNewStr) << S(L"gorilla!")
|
|
/* 88 */ << H(TokValueTerminator)
|
|
/* 89 */ << H(TokLine) << H(15)
|
|
/* 91 */ << H(TokHashLiteral) << HS(L"MOO")
|
|
/* 98 */ << H(TokAssign) << H(0)
|
|
/* 100 */ << H(TokLiteral | TokNewStr) << S(L"kuh")
|
|
/* 105 */ << H(TokValueTerminator)
|
|
/* 106 */ << H(TokLine) << H(17)
|
|
/* 108 */ << H(TokHashLiteral) << HS(L"LOO")
|
|
/* 115 */ << H(TokAssign) << H(0)
|
|
/* 117 */ << H(TokValueTerminator)
|
|
/* 118 */ << H(TokLine) << H(19)
|
|
/* 120 */ << H(TokHashLiteral) << HS(L"FOO")
|
|
/* 127 */ << H(TokAssign) << H(2)
|
|
/* 129 */ << H(TokLiteral | TokNewStr) << S(L"bar")
|
|
/* 134 */ << H(TokLiteral | TokNewStr) << S(L"baz")
|
|
/* 139 */ << H(TokValueTerminator)
|
|
/* 140 */ << H(TokLine) << H(24)
|
|
/* 142 */ << H(TokHashLiteral) << HS(L"GAZ")
|
|
/* 149 */ << H(TokAssign) << H(0)
|
|
/* 151 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("accidental continuation")
|
|
<< "VAR0 = \\\n this \\\n is \\\n ok\n"
|
|
"VAR1 = \\\n this \\\n is=still \\\n ok\n"
|
|
"VAR2 = \\\n this \\\n is \\\n"
|
|
"VAR3 = \\\n not ok\n"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR0")
|
|
/* 10 */ << H(TokAssign) << H(3)
|
|
/* 12 */ << H(TokLiteral | TokNewStr) << S(L"this")
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"is")
|
|
/* 22 */ << H(TokLiteral | TokNewStr) << S(L"ok")
|
|
/* 26 */ << H(TokValueTerminator)
|
|
/* 27 */ << H(TokLine) << H(5)
|
|
/* 29 */ << H(TokHashLiteral) << HS(L"VAR1")
|
|
/* 37 */ << H(TokAssign) << H(3)
|
|
/* 39 */ << H(TokLiteral | TokNewStr) << S(L"this")
|
|
/* 45 */ << H(TokLiteral | TokNewStr) << S(L"is=still")
|
|
/* 55 */ << H(TokLiteral | TokNewStr) << S(L"ok")
|
|
/* 59 */ << H(TokValueTerminator)
|
|
/* 60 */ << H(TokLine) << H(9)
|
|
/* 62 */ << H(TokHashLiteral) << HS(L"VAR2")
|
|
/* 70 */ << H(TokAssign) << H(6)
|
|
/* 72 */ << H(TokLiteral | TokNewStr) << S(L"this")
|
|
/* 78 */ << H(TokLiteral | TokNewStr) << S(L"is")
|
|
/* 82 */ << H(TokLiteral | TokNewStr) << S(L"VAR3")
|
|
/* 88 */ << H(TokLiteral | TokNewStr) << S(L"=")
|
|
/* 91 */ << H(TokLiteral | TokNewStr) << S(L"not")
|
|
/* 96 */ << H(TokLiteral | TokNewStr) << S(L"ok")
|
|
/* 100 */ << H(TokValueTerminator))
|
|
<< "WARNING: in:12: Possible accidental line continuation"
|
|
<< true;
|
|
|
|
QTest::newRow("plain variable expansion")
|
|
<< "VAR = $$bar"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("braced variable expansion")
|
|
<< "VAR = $${foo/bar}"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"foo/bar")
|
|
/* 22 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("bogus variable expansion")
|
|
<< "VAR = $$ "
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"")
|
|
/* 15 */ << H(TokValueTerminator))
|
|
<< "WARNING: in:1: Missing name in expansion"
|
|
<< true;
|
|
|
|
QTest::newRow("bogus braced variable expansion")
|
|
<< "VAR = $${}"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"")
|
|
/* 15 */ << H(TokValueTerminator))
|
|
<< "WARNING: in:1: Missing name in expansion"
|
|
<< true;
|
|
|
|
QTest::newRow("unterminated braced variable expansion")
|
|
<< "VAR = $${FOO"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAssign) << H(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"FOO")
|
|
/* 18 */ << H(TokValueTerminator))
|
|
<< "in:1: Missing } terminator [found end-of-line]"
|
|
<< false;
|
|
|
|
QTest::newRow("invalid identifier in braced variable expansion")
|
|
<< "VAR = $${FOO/BAR+BAZ}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAssign) << H(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"FOO/BAR")
|
|
/* 22 */ << H(TokLiteral) << S(L"+BAZ")
|
|
/* 28 */ << H(TokValueTerminator))
|
|
<< "in:1: Missing } terminator [found +]"
|
|
<< false;
|
|
|
|
QTest::newRow("property expansion")
|
|
<< "VAR = $$[bar]"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokProperty | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("environment expansion")
|
|
<< "VAR = $$(bar)"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokEnvVar | TokNewStr) << S(L"bar")
|
|
/* 16 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("plain function call")
|
|
<< "VAR = $$bar()"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokFuncTerminator)
|
|
/* 19 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("braced function call")
|
|
<< "VAR = $${bar()}"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokFuncTerminator)
|
|
/* 19 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("function call with one argument")
|
|
<< "VAR = $$bar(blubb)"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
|
|
/* 25 */ << H(TokFuncTerminator)
|
|
/* 26 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("function call with multiple arguments")
|
|
<< "VAR = $$bar( blubb blubb, hey ,$$you)"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
|
|
/* 25 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
|
|
/* 32 */ << H(TokArgSeparator)
|
|
/* 33 */ << H(TokLiteral | TokNewStr) << S(L"hey")
|
|
/* 38 */ << H(TokArgSeparator)
|
|
/* 39 */ << H(TokVariable | TokNewStr) << HS(L"you")
|
|
/* 46 */ << H(TokFuncTerminator)
|
|
/* 47 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("nested function call")
|
|
<< "VAR = $$foo(yo, $$bar(blubb))"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokFuncName | TokNewStr) << HS(L"foo")
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"yo")
|
|
/* 22 */ << H(TokArgSeparator)
|
|
/* 23 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
|
|
/* 30 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
|
|
/* 37 */ << H(TokFuncTerminator)
|
|
/* 38 */ << H(TokFuncTerminator)
|
|
/* 39 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
// This is a rather questionable "feature"
|
|
QTest::newRow("function call with parenthesized argument")
|
|
<< "VAR = $$bar(blubb (yo, man) blabb, nope)"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokFuncName | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"blubb")
|
|
/* 25 */ << H(TokLiteral | TokNewStr) << S(L"(yo,")
|
|
/* 31 */ << H(TokLiteral | TokNewStr) << S(L"man)")
|
|
/* 37 */ << H(TokLiteral | TokNewStr) << S(L"blabb")
|
|
/* 44 */ << H(TokArgSeparator)
|
|
/* 45 */ << H(TokLiteral | TokNewStr) << S(L"nope")
|
|
/* 51 */ << H(TokFuncTerminator)
|
|
/* 52 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("separate literal and expansion")
|
|
<< "VAR = foo $$bar"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(2)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokVariable | TokNewStr) << HS(L"bar")
|
|
/* 23 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("separate expansion and literal")
|
|
<< "VAR = $$bar foo"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 23 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("joined literal and expansion")
|
|
<< "VAR = foo$$bar"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokVariable) << HS(L"bar")
|
|
/* 23 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("joined expansion and literal")
|
|
<< "VAR = $${bar}foo"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"bar")
|
|
/* 18 */ << H(TokLiteral) << S(L"foo")
|
|
/* 23 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("plain variable expansion with funny name and literal")
|
|
<< "VAR = $$az_AZ_09.dot/nix"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot")
|
|
/* 27 */ << H(TokLiteral) << S(L"/nix")
|
|
/* 33 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("braced variable expansion with funny name")
|
|
<< "VAR = $${az_AZ_09.dot/nix}"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokVariable | TokNewStr) << HS(L"az_AZ_09.dot/nix")
|
|
/* 31 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("quoted joined literal and expansion")
|
|
<< "VAR = 'foo$$bar'"
|
|
<< TS(
|
|
/* 0 */ << ASSIGN_VAR(0)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 16 */ << H(TokVariable | TokQuoted) << HS(L"bar")
|
|
/* 23 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("assignment with expansion in variable name")
|
|
<< "VAR$$EXTRA ="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokVariable) << HS(L"EXTRA")
|
|
/* 18 */ << H(TokAssign) << H(0)
|
|
/* 20 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
}
|
|
|
|
void tst_qmakelib::addParseConditions()
|
|
{
|
|
QTest::newRow("one test")
|
|
<< "foo"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("wildcard-test")
|
|
<< "foo-*"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo-*")
|
|
/* 11 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
// This is a rather questionable "feature"
|
|
QTest::newRow("one quoted test")
|
|
<< "\"foo\""
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("two tests")
|
|
<< "foo\nbar"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokLine) << H(2)
|
|
/* 12 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 19 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("bogus two tests")
|
|
<< "foo bar\nbaz"
|
|
<< TS()
|
|
<< "in:1: Extra characters after test expression."
|
|
<< false;
|
|
|
|
QTest::newRow("test-AND-test")
|
|
<< "foo:bar"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokAnd)
|
|
/* 11 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 18 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-OR-test")
|
|
<< " foo | bar "
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokOr)
|
|
/* 11 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 18 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("NOT-test")
|
|
<< "!foo"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokNot)
|
|
/* 3 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 10 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("NOT-NOT-test")
|
|
<< "!!foo"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
// This is a rather questionable "feature"
|
|
QTest::newRow("quoted-NOT-test")
|
|
<< "\"!foo\""
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokNot)
|
|
/* 3 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 10 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
// This is a rather questionable "feature"
|
|
QTest::newRow("NOT-quoted-test")
|
|
<< "!\"foo\""
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokNot)
|
|
/* 3 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 10 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-NOT-test")
|
|
<< "foo:!bar"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokAnd)
|
|
/* 11 */ << H(TokNot)
|
|
/* 12 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 19 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-assignment")
|
|
<< "foo\nVAR="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokLine) << H(2)
|
|
/* 12 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 19 */ << H(TokAssign) << H(0)
|
|
/* 21 */ << H(TokValueTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-assignment")
|
|
<< "foo: VAR ="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokBranch)
|
|
/* 11 */ /* then branch */ << I(11)
|
|
/* 13 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 20 */ << H(TokAssign) << H(0)
|
|
/* 22 */ << H(TokValueTerminator)
|
|
/* 23 */ << H(TokTerminator)
|
|
/* 24 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-else-test")
|
|
<< "foo\nelse: bar"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokBranch)
|
|
/* 11 */ /* then branch */ << I(0)
|
|
/* 13 */ /* else branch */ << I(11)
|
|
/* 15 */ << H(TokLine) << H(2)
|
|
/* 17 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 24 */ << H(TokCondition)
|
|
/* 25 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("function-else-test")
|
|
<< "foo()\nelse: bar"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokFuncTerminator)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(0)
|
|
/* 14 */ /* else branch */ << I(11)
|
|
/* 16 */ << H(TokLine) << H(2)
|
|
/* 18 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 25 */ << H(TokCondition)
|
|
/* 26 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-test-else-test")
|
|
<< "foo:bar\nelse: baz"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokAnd)
|
|
/* 11 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 18 */ << H(TokCondition)
|
|
/* 19 */ << H(TokBranch)
|
|
/* 20 */ /* then branch */ << I(0)
|
|
/* 22 */ /* else branch */ << I(11)
|
|
/* 24 */ << H(TokLine) << H(2)
|
|
/* 26 */ << H(TokHashLiteral) << HS(L"baz")
|
|
/* 33 */ << H(TokCondition)
|
|
/* 34 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-test-else-test-else-test-function")
|
|
<< "foo:bar\nelse: baz\nelse: bak\nbuzz()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokAnd)
|
|
/* 11 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 18 */ << H(TokCondition)
|
|
/* 19 */ << H(TokBranch)
|
|
/* 20 */ /* then branch */ << I(0)
|
|
/* 22 */ /* else branch */ << I(27)
|
|
/* 24 */ << H(TokLine) << H(2)
|
|
/* 26 */ << H(TokHashLiteral) << HS(L"baz")
|
|
/* 33 */ << H(TokCondition)
|
|
/* 34 */ << H(TokBranch)
|
|
/* 35 */ /* then branch */ << I(0)
|
|
/* 37 */ /* else branch */ << I(11)
|
|
/* 39 */ << H(TokLine) << H(3)
|
|
/* 41 */ << H(TokHashLiteral) << HS(L"bak")
|
|
/* 48 */ << H(TokCondition)
|
|
/* 49 */ << H(TokTerminator)
|
|
/* 50 */ << H(TokTerminator)
|
|
/* 51 */ << H(TokLine) << H(4)
|
|
/* 53 */ << H(TokHashLiteral) << HS(L"buzz")
|
|
/* 61 */ << H(TokTestCall)
|
|
/* 62 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-assignment-else-assignment")
|
|
<< "foo: VAR =\nelse: VAR="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokBranch)
|
|
/* 11 */ /* then branch */ << I(11)
|
|
/* 13 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 20 */ << H(TokAssign) << H(0)
|
|
/* 22 */ << H(TokValueTerminator)
|
|
/* 23 */ << H(TokTerminator)
|
|
/* 24 */ /* else branch */ << I(13)
|
|
/* 26 */ << H(TokLine) << H(2)
|
|
/* 28 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 35 */ << H(TokAssign) << H(0)
|
|
/* 37 */ << H(TokValueTerminator)
|
|
/* 38 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-else-test-assignment")
|
|
<< "foo\nelse: bar: VAR ="
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokBranch)
|
|
/* 11 */ /* then branch */ << I(0)
|
|
/* 13 */ /* else branch */ << I(27)
|
|
/* 15 */ << H(TokLine) << H(2)
|
|
/* 17 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 24 */ << H(TokCondition)
|
|
/* 25 */ << H(TokBranch)
|
|
/* 26 */ /* then branch */ << I(11)
|
|
/* 28 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 35 */ << H(TokAssign) << H(0)
|
|
/* 37 */ << H(TokValueTerminator)
|
|
/* 38 */ << H(TokTerminator)
|
|
/* 39 */ /* else branch */ << I(0)
|
|
/* 41 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("one function")
|
|
<< "foo()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("one function (with spaces)")
|
|
<< " foo( ) "
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("unterminated function call")
|
|
<< "foo(\nfoo"
|
|
<< TS()
|
|
<< "in:1: Missing closing parenthesis in function call"
|
|
<< false;
|
|
|
|
QTest::newRow("function with arguments")
|
|
<< "foo(blah, hi ho)"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokLiteral | TokNewStr) << S(L"blah")
|
|
/* 16 */ << H(TokArgSeparator)
|
|
/* 17 */ << H(TokLiteral | TokNewStr) << S(L"hi")
|
|
/* 21 */ << H(TokLiteral | TokNewStr) << S(L"ho")
|
|
/* 25 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("function with empty arguments")
|
|
<< "foo(,)"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokArgSeparator)
|
|
/* 11 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("function with funny arguments")
|
|
<< "foo(blah\\, \"hi , \\ho\" ,uh\\ ,\\oh ,, )"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokLiteral | TokNewStr) << S(L"blah\\")
|
|
/* 17 */ << H(TokArgSeparator)
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"hi , \\ho")
|
|
/* 29 */ << H(TokArgSeparator)
|
|
/* 30 */ << H(TokLiteral | TokNewStr) << S(L"uh\\")
|
|
/* 35 */ << H(TokArgSeparator)
|
|
/* 36 */ << H(TokLiteral | TokNewStr) << S(L"\\oh")
|
|
/* 41 */ << H(TokArgSeparator)
|
|
/* 42 */ << H(TokArgSeparator)
|
|
/* 43 */ << H(TokFuncTerminator))
|
|
<< "WARNING: in:1: Unescaped backslashes are deprecated\n"
|
|
"WARNING: in:1: Unescaped backslashes are deprecated\n"
|
|
"WARNING: in:1: Unescaped backslashes are deprecated\n"
|
|
"WARNING: in:1: Unescaped backslashes are deprecated"
|
|
<< true;
|
|
|
|
QTest::newRow("function with nested call")
|
|
<< "foo($$blah(hi ho))"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokFuncName | TokNewStr) << HS(L"blah")
|
|
/* 18 */ << H(TokLiteral | TokNewStr) << S(L"hi")
|
|
/* 22 */ << H(TokLiteral | TokNewStr) << S(L"ho")
|
|
/* 26 */ << H(TokFuncTerminator)
|
|
/* 27 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("stand-alone parentheses")
|
|
<< "()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestCall)
|
|
/* 3 */ << H(TokFuncTerminator))
|
|
<< "in:1: Opening parenthesis without prior test name."
|
|
<< false;
|
|
|
|
QTest::newRow("bogus test and function")
|
|
<< "foo bar()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestCall)
|
|
/* 3 */ << H(TokFuncTerminator))
|
|
<< "in:1: Extra characters after test expression."
|
|
<< false;
|
|
|
|
// This is a rather questionable "feature"
|
|
QTest::newRow("two functions")
|
|
<< "foo() bar()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokFuncTerminator)
|
|
/* 11 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 18 */ << H(TokTestCall)
|
|
/* 19 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("function-AND-test")
|
|
<< "foo():bar"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokTestCall)
|
|
/* 10 */ << H(TokFuncTerminator)
|
|
/* 11 */ << H(TokAnd)
|
|
/* 12 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 19 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-function")
|
|
<< "foo:bar()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokAnd)
|
|
/* 11 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 18 */ << H(TokTestCall)
|
|
/* 19 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("NOT-function-AND-test")
|
|
<< "!foo():bar"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokNot)
|
|
/* 3 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 10 */ << H(TokTestCall)
|
|
/* 11 */ << H(TokFuncTerminator)
|
|
/* 12 */ << H(TokAnd)
|
|
/* 13 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 20 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-NOT-function")
|
|
<< "foo:!bar()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"foo")
|
|
/* 9 */ << H(TokCondition)
|
|
/* 10 */ << H(TokAnd)
|
|
/* 11 */ << H(TokNot)
|
|
/* 12 */ << H(TokHashLiteral) << HS(L"bar")
|
|
/* 19 */ << H(TokTestCall)
|
|
/* 20 */ << H(TokFuncTerminator))
|
|
<< ""
|
|
<< true;
|
|
}
|
|
|
|
void tst_qmakelib::addParseControlStatements()
|
|
{
|
|
QTest::newRow("for(VAR, LIST) loop")
|
|
<< "for(VAR, LIST)"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"VAR")
|
|
/* 9 */ /* iterator */ << I(7)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
|
|
/* 17 */ << H(TokValueTerminator)
|
|
/* 18 */ /* body */ << I(1)
|
|
/* 20 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("for(ever) loop")
|
|
<< "for(ever)"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"")
|
|
/* 6 */ /* iterator */ << I(9)
|
|
/* 8 */ << H(TokHashLiteral) << HS(L"ever")
|
|
/* 16 */ << H(TokValueTerminator)
|
|
/* 17 */ /* body */ << I(1)
|
|
/* 19 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
// This is a rather questionable "feature"
|
|
QTest::newRow("for($$blub) loop")
|
|
<< "for($$blub)"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"")
|
|
/* 6 */ /* iterator */ << I(9)
|
|
/* 8 */ << H(TokVariable | TokNewStr) << HS(L"blub")
|
|
/* 16 */ << H(TokValueTerminator)
|
|
/* 17 */ /* body */ << I(1)
|
|
/* 19 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-for-test-else-test")
|
|
<< "true:for(VAR, LIST): true\nelse: true"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(31)
|
|
/* 14 */ << H(TokForLoop) << HS(L"VAR")
|
|
/* 21 */ /* iterator */ << I(7)
|
|
/* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
|
|
/* 29 */ << H(TokValueTerminator)
|
|
/* 30 */ /* body */ << I(12)
|
|
/* 32 */ << H(TokLine) << H(1)
|
|
/* 34 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 42 */ << H(TokCondition)
|
|
/* 43 */ << H(TokTerminator)
|
|
/* 44 */ << H(TokTerminator)
|
|
/* 45 */ /* else branch */ << I(12)
|
|
/* 47 */ << H(TokLine) << H(2)
|
|
/* 49 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 57 */ << H(TokCondition)
|
|
/* 58 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("next()")
|
|
<< "for(ever): next()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"")
|
|
/* 6 */ /* iterator */ << I(9)
|
|
/* 8 */ << H(TokHashLiteral) << HS(L"ever")
|
|
/* 16 */ << H(TokValueTerminator)
|
|
/* 17 */ /* body */ << I(4)
|
|
/* 19 */ << H(TokLine) << H(1)
|
|
/* 21 */ << H(TokNext)
|
|
/* 22 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("break()")
|
|
<< "for(ever): break()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"")
|
|
/* 6 */ /* iterator */ << I(9)
|
|
/* 8 */ << H(TokHashLiteral) << HS(L"ever")
|
|
/* 16 */ << H(TokValueTerminator)
|
|
/* 17 */ /* body */ << I(4)
|
|
/* 19 */ << H(TokLine) << H(1)
|
|
/* 21 */ << H(TokBreak)
|
|
/* 22 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("top-level return()")
|
|
<< "return()"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokReturn))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("else")
|
|
<< "else"
|
|
<< TS()
|
|
<< "in:1: Unexpected 'else'."
|
|
<< false;
|
|
|
|
QTest::newRow("test-{else}")
|
|
<< "test { else }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(1)
|
|
/* 14 */ << H(TokTerminator)
|
|
/* 15 */ /* else branch */ << I(0))
|
|
<< "in:1: Unexpected 'else'."
|
|
<< false;
|
|
|
|
QTest::newRow("defineTest-{else}")
|
|
<< "defineTest(fn) { else }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"fn")
|
|
/* 8 */ /* body */ << I(1)
|
|
/* 10 */ << H(TokTerminator))
|
|
<< "in:1: Unexpected 'else'."
|
|
<< false;
|
|
|
|
QTest::newRow("for-else")
|
|
<< "for(ever) { else }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"")
|
|
/* 6 */ /* iterator */ << I(9)
|
|
/* 8 */ << H(TokHashLiteral) << HS(L"ever")
|
|
/* 16 */ << H(TokValueTerminator)
|
|
/* 17 */ /* body */ << I(1)
|
|
/* 19 */ << H(TokTerminator))
|
|
<< "in:1: Unexpected 'else'."
|
|
<< false;
|
|
|
|
QTest::newRow("double-test-else")
|
|
<< "foo bar\nelse"
|
|
<< TS(
|
|
/* 0 */ << H(TokBranch)
|
|
/* 1 */ /* then branch */ << I(0)
|
|
/* 3 */ /* else branch */ << I(1) // This seems weird
|
|
/* 5 */ << H(TokTerminator))
|
|
<< "in:1: Extra characters after test expression."
|
|
<< false;
|
|
|
|
QTest::newRow("test-function-else")
|
|
<< "foo bar()\nelse"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestCall) // This seems pointless
|
|
/* 3 */ << H(TokFuncTerminator)
|
|
/* 4 */ << H(TokBranch)
|
|
/* 5 */ /* then branch */ << I(0)
|
|
/* 7 */ /* else branch */ << I(1) // This seems weird
|
|
/* 9 */ << H(TokTerminator))
|
|
<< "in:1: Extra characters after test expression."
|
|
<< false;
|
|
}
|
|
|
|
void tst_qmakelib::addParseBraces()
|
|
{
|
|
QTest::newRow("{}")
|
|
<< "{ }"
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("{}-newlines")
|
|
<< "\n\n{ }\n\n"
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("{")
|
|
<< "{"
|
|
<< TS()
|
|
<< "in:2: Missing closing brace(s)."
|
|
<< false;
|
|
|
|
QTest::newRow("test {")
|
|
<< "test {"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(1)
|
|
/* 14 */ << H(TokTerminator)
|
|
/* 15 */ /* else branch */ << I(0))
|
|
<< "in:2: Missing closing brace(s)."
|
|
<< false;
|
|
|
|
QTest::newRow("}")
|
|
<< "}"
|
|
<< TS()
|
|
<< "in:1: Excess closing brace."
|
|
<< false;
|
|
|
|
QTest::newRow("{test}")
|
|
<< "{ true }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("{test-newlines}")
|
|
<< "{\ntrue\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(2)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("{assignment-test}-test")
|
|
<< "{ VAR = { foo } bar } true"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAssign) << H(4)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"{")
|
|
/* 14 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 19 */ << H(TokLiteral | TokNewStr) << S(L"}")
|
|
/* 22 */ << H(TokLiteral | TokNewStr) << S(L"bar")
|
|
/* 27 */ << H(TokValueTerminator)
|
|
/* 28 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 36 */ << H(TokCondition))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("assignment with excess opening brace")
|
|
<< "VAR = { { foo }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 9 */ << H(TokAssign) << H(4)
|
|
/* 11 */ << H(TokLiteral | TokNewStr) << S(L"{")
|
|
/* 14 */ << H(TokLiteral | TokNewStr) << S(L"{")
|
|
/* 17 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 22 */ << H(TokLiteral | TokNewStr) << S(L"}")
|
|
/* 25 */ << H(TokValueTerminator))
|
|
<< "WARNING: in:1: Possible braces mismatch"
|
|
<< true;
|
|
|
|
QTest::newRow("test-{}")
|
|
<< "true {}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(1)
|
|
/* 14 */ << H(TokTerminator)
|
|
/* 15 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-{newlines}")
|
|
<< "true {\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(1)
|
|
/* 14 */ << H(TokTerminator)
|
|
/* 15 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-{test}")
|
|
<< "true { true }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(10)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 22 */ << H(TokCondition)
|
|
/* 23 */ << H(TokTerminator)
|
|
/* 24 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test:-{test}")
|
|
<< "true: { true }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(10)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 22 */ << H(TokCondition)
|
|
/* 23 */ << H(TokTerminator)
|
|
/* 24 */ /* else branch */ << I(0))
|
|
<< "WARNING: in:1: Excess colon in front of opening brace."
|
|
<< true;
|
|
|
|
QTest::newRow("test-{test-newlines}")
|
|
<< "true {\ntrue\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(12)
|
|
/* 14 */ << H(TokLine) << H(2)
|
|
/* 16 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 24 */ << H(TokCondition)
|
|
/* 25 */ << H(TokTerminator)
|
|
/* 26 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test:-{test-newlines}")
|
|
<< "true: {\ntrue\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(12)
|
|
/* 14 */ << H(TokLine) << H(2)
|
|
/* 16 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 24 */ << H(TokCondition)
|
|
/* 25 */ << H(TokTerminator)
|
|
/* 26 */ /* else branch */ << I(0))
|
|
<< "WARNING: in:1: Excess colon in front of opening brace."
|
|
<< true;
|
|
|
|
QTest::newRow("test-{assignment}")
|
|
<< "true { VAR = {foo} }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(18)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 21 */ << H(TokAssign) << H(0)
|
|
/* 23 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
|
|
/* 30 */ << H(TokValueTerminator)
|
|
/* 31 */ << H(TokTerminator)
|
|
/* 32 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-{test-assignment}")
|
|
<< "true { true: VAR = {foo} }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(33)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 22 */ << H(TokCondition)
|
|
/* 23 */ << H(TokBranch)
|
|
/* 24 */ /* then branch */ << I(18)
|
|
/* 26 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 33 */ << H(TokAssign) << H(0)
|
|
/* 35 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
|
|
/* 42 */ << H(TokValueTerminator)
|
|
/* 43 */ << H(TokTerminator)
|
|
/* 44 */ /* else branch */ << I(0)
|
|
/* 46 */ << H(TokTerminator)
|
|
/* 47 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-{assignment-newlines}")
|
|
<< "true {\nVAR = {foo}\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(20)
|
|
/* 14 */ << H(TokLine) << H(2)
|
|
/* 16 */ << H(TokHashLiteral) << HS(L"VAR")
|
|
/* 23 */ << H(TokAssign) << H(0)
|
|
/* 25 */ << H(TokLiteral | TokNewStr) << S(L"{foo}")
|
|
/* 32 */ << H(TokValueTerminator)
|
|
/* 33 */ << H(TokTerminator)
|
|
/* 34 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-{}-else-test-{}")
|
|
<< "true {} else: true {}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(1)
|
|
/* 14 */ << H(TokTerminator)
|
|
/* 15 */ /* else branch */ << I(18)
|
|
/* 17 */ << H(TokLine) << H(1)
|
|
/* 19 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 27 */ << H(TokCondition)
|
|
/* 28 */ << H(TokBranch)
|
|
/* 29 */ /* then branch */ << I(1)
|
|
/* 31 */ << H(TokTerminator)
|
|
/* 32 */ /* else branch */ << I(0)
|
|
/* 34 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-{}-else-test-{}-newlines")
|
|
<< "true {\n}\nelse: true {\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(1)
|
|
/* 14 */ << H(TokTerminator)
|
|
/* 15 */ /* else branch */ << I(18)
|
|
/* 17 */ << H(TokLine) << H(3)
|
|
/* 19 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 27 */ << H(TokCondition)
|
|
/* 28 */ << H(TokBranch)
|
|
/* 29 */ /* then branch */ << I(1)
|
|
/* 31 */ << H(TokTerminator)
|
|
/* 32 */ /* else branch */ << I(0)
|
|
/* 34 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-{test}-else-test-{}-newlines")
|
|
<< "true {\ntrue\n}\nelse: true {\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(12)
|
|
/* 14 */ << H(TokLine) << H(2)
|
|
/* 16 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 24 */ << H(TokCondition)
|
|
/* 25 */ << H(TokTerminator)
|
|
/* 26 */ /* else branch */ << I(18)
|
|
/* 28 */ << H(TokLine) << H(4)
|
|
/* 30 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 38 */ << H(TokCondition)
|
|
/* 39 */ << H(TokBranch)
|
|
/* 40 */ /* then branch */ << I(1)
|
|
/* 42 */ << H(TokTerminator)
|
|
/* 43 */ /* else branch */ << I(0)
|
|
/* 45 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("for-{next}")
|
|
<< "for(ever) { next() }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"")
|
|
/* 6 */ /* iterator */ << I(9)
|
|
/* 8 */ << H(TokHashLiteral) << HS(L"ever")
|
|
/* 16 */ << H(TokValueTerminator)
|
|
/* 17 */ /* body */ << I(4)
|
|
/* 19 */ << H(TokLine) << H(1)
|
|
/* 21 */ << H(TokNext)
|
|
/* 22 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("for:-{next}")
|
|
<< "for(ever): { next() }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokForLoop) << HS(L"")
|
|
/* 6 */ /* iterator */ << I(9)
|
|
/* 8 */ << H(TokHashLiteral) << HS(L"ever")
|
|
/* 16 */ << H(TokValueTerminator)
|
|
/* 17 */ /* body */ << I(4)
|
|
/* 19 */ << H(TokLine) << H(1)
|
|
/* 21 */ << H(TokNext)
|
|
/* 22 */ << H(TokTerminator))
|
|
<< "WARNING: in:1: Excess colon in front of opening brace."
|
|
<< true;
|
|
|
|
QTest::newRow("test-for-{test-else-test-newlines}")
|
|
<< "true:for(VAR, LIST) {\ntrue\nelse: true\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(48)
|
|
/* 14 */ << H(TokForLoop) << HS(L"VAR")
|
|
/* 21 */ /* iterator */ << I(7)
|
|
/* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
|
|
/* 29 */ << H(TokValueTerminator)
|
|
/* 30 */ /* body */ << I(29)
|
|
/* 32 */ << H(TokLine) << H(2)
|
|
/* 34 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 42 */ << H(TokCondition)
|
|
/* 43 */ << H(TokBranch)
|
|
/* 44 */ /* then branch */ << I(0)
|
|
/* 46 */ /* else branch */ << I(12)
|
|
/* 48 */ << H(TokLine) << H(3)
|
|
/* 50 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 58 */ << H(TokCondition)
|
|
/* 59 */ << H(TokTerminator)
|
|
/* 60 */ << H(TokTerminator)
|
|
/* 61 */ << H(TokTerminator)
|
|
/* 62 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-for-{test-else-test}")
|
|
<< "true:for(VAR, LIST) { true\nelse: true }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokBranch)
|
|
/* 12 */ /* then branch */ << I(48)
|
|
/* 14 */ << H(TokForLoop) << HS(L"VAR")
|
|
/* 21 */ /* iterator */ << I(7)
|
|
/* 23 */ << H(TokLiteral | TokNewStr) << S(L"LIST")
|
|
/* 29 */ << H(TokValueTerminator)
|
|
/* 30 */ /* body */ << I(29)
|
|
/* 32 */ << H(TokLine) << H(1)
|
|
/* 34 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 42 */ << H(TokCondition)
|
|
/* 43 */ << H(TokBranch)
|
|
/* 44 */ /* then branch */ << I(0)
|
|
/* 46 */ /* else branch */ << I(12)
|
|
/* 48 */ << H(TokLine) << H(2)
|
|
/* 50 */ << H(TokHashLiteral) << HS(L"true")
|
|
/* 58 */ << H(TokCondition)
|
|
/* 59 */ << H(TokTerminator)
|
|
/* 60 */ << H(TokTerminator)
|
|
/* 61 */ << H(TokTerminator)
|
|
/* 62 */ /* else branch */ << I(0))
|
|
<< ""
|
|
<< true;
|
|
}
|
|
|
|
void tst_qmakelib::addParseCustomFunctions()
|
|
{
|
|
QTest::newRow("defineTest-{newlines}")
|
|
<< "defineTest(test) {\n}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"test")
|
|
/* 10 */ /* body */ << I(1)
|
|
/* 12 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("defineTest:-test")
|
|
<< "defineTest(test): test"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"test")
|
|
/* 10 */ /* body */ << I(12)
|
|
/* 12 */ << H(TokLine) << H(1)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 22 */ << H(TokCondition)
|
|
/* 23 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("defineTest-{test}")
|
|
<< "defineTest(test) { test }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"test")
|
|
/* 10 */ /* body */ << I(12)
|
|
/* 12 */ << H(TokLine) << H(1)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 22 */ << H(TokCondition)
|
|
/* 23 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("defineTest-{return}")
|
|
<< "defineTest(test) { return() }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"test")
|
|
/* 10 */ /* body */ << I(4)
|
|
/* 12 */ << H(TokLine) << H(1)
|
|
/* 14 */ << H(TokReturn)
|
|
/* 15 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("defineReplace-{return-stuff}")
|
|
<< "defineReplace(stuff) { return(foo bar) }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokReplaceDef) << HS(L"stuff")
|
|
/* 11 */ /* body */ << I(14)
|
|
/* 13 */ << H(TokLine) << H(1)
|
|
/* 15 */ << H(TokLiteral | TokNewStr) << S(L"foo")
|
|
/* 20 */ << H(TokLiteral | TokNewStr) << S(L"bar")
|
|
/* 25 */ << H(TokReturn)
|
|
/* 26 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-defineTest-{}")
|
|
<< "test: defineTest(test) {}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokAnd)
|
|
/* 12 */ << H(TokTestDef) << HS(L"test")
|
|
/* 20 */ /* body */ << I(1)
|
|
/* 22 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-OR-defineTest-{}")
|
|
<< "test| defineTest(test) {}"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 10 */ << H(TokCondition)
|
|
/* 11 */ << H(TokOr)
|
|
/* 12 */ << H(TokTestDef) << HS(L"test")
|
|
/* 20 */ /* body */ << I(1)
|
|
/* 22 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("bypassNesting()-{return}")
|
|
<< "defineTest(test) { bypassNesting() { return(true) } }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"test")
|
|
/* 10 */ /* body */ << I(16)
|
|
/* 12 */ << H(TokLine) << H(1)
|
|
/* 14 */ << H(TokBypassNesting)
|
|
/* 15 */ /* block */ << I(10)
|
|
/* 17 */ << H(TokLine) << H(1)
|
|
/* 19 */ << H(TokLiteral | TokNewStr) << S(L"true")
|
|
/* 25 */ << H(TokReturn)
|
|
/* 26 */ << H(TokTerminator)
|
|
/* 27 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-AND-bypassNesting()-{}")
|
|
<< "defineTest(test) { test: bypassNesting() {} }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"test")
|
|
/* 10 */ /* body */ << I(17)
|
|
/* 12 */ << H(TokLine) << H(1)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 22 */ << H(TokCondition)
|
|
/* 23 */ << H(TokAnd)
|
|
/* 24 */ << H(TokBypassNesting)
|
|
/* 25 */ /* block */ << I(1)
|
|
/* 27 */ << H(TokTerminator)
|
|
/* 28 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("test-OR-bypassNesting()-{}")
|
|
<< "defineTest(test) { test| bypassNesting() {} }"
|
|
<< TS(
|
|
/* 0 */ << H(TokLine) << H(1)
|
|
/* 2 */ << H(TokTestDef) << HS(L"test")
|
|
/* 10 */ /* body */ << I(17)
|
|
/* 12 */ << H(TokLine) << H(1)
|
|
/* 14 */ << H(TokHashLiteral) << HS(L"test")
|
|
/* 22 */ << H(TokCondition)
|
|
/* 23 */ << H(TokOr)
|
|
/* 24 */ << H(TokBypassNesting)
|
|
/* 25 */ /* block */ << I(1)
|
|
/* 27 */ << H(TokTerminator)
|
|
/* 28 */ << H(TokTerminator))
|
|
<< ""
|
|
<< true;
|
|
}
|
|
|
|
void tst_qmakelib::addParseAbuse()
|
|
{
|
|
QTest::newRow("!")
|
|
<< ""
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("|")
|
|
<< ""
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow(":")
|
|
<< ""
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("NOT-assignment")
|
|
<< "!VAR ="
|
|
<< TS()
|
|
<< "in:1: Unexpected NOT operator in front of assignment."
|
|
<< false;
|
|
|
|
QTest::newRow("NOT-{}")
|
|
<< "!{}"
|
|
<< TS()
|
|
<< "in:1: Unexpected NOT operator in front of opening brace."
|
|
<< false;
|
|
|
|
QTest::newRow("NOT-else")
|
|
<< "test\n!else {}"
|
|
<< TS()
|
|
<< "in:2: Unexpected NOT operator in front of else."
|
|
<< false;
|
|
|
|
QTest::newRow("NOT-for-{}")
|
|
<< "!for(ever) {}"
|
|
<< TS()
|
|
<< "in:1: Unexpected NOT operator in front of for()."
|
|
<< false;
|
|
|
|
QTest::newRow("NOT-defineTest-{}")
|
|
<< "!defineTest(test) {}"
|
|
<< TS()
|
|
<< "in:1: Unexpected NOT operator in front of function definition."
|
|
<< false;
|
|
|
|
QTest::newRow("outer-bypassNesting()-{}")
|
|
<< "bypassNesting() {}"
|
|
<< TS()
|
|
<< "in:1: Unexpected bypassNesting()."
|
|
<< false;
|
|
|
|
QTest::newRow("bypassNesting(arg)-{}")
|
|
<< "defineTest(test) { bypassNesting(arg) {} }"
|
|
<< TS()
|
|
<< "in:1: bypassNesting() requires zero arguments."
|
|
<< false;
|
|
|
|
QTest::newRow("NOT-bypassNesting()-{}")
|
|
<< "defineTest(test) { !bypassNesting() {} }"
|
|
<< TS()
|
|
<< "in:1: Unexpected NOT operator in front of bypassNesting()."
|
|
<< 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;
|
|
|
|
// Token buffer overflow. Verify with Valgrind or asan.
|
|
QTest::newRow("QTCREATORBUG-16508")
|
|
<< "a{b{c{d{"
|
|
<< TS()
|
|
<< "in:2: Missing closing brace(s)."
|
|
<< false;
|
|
}
|
|
|
|
void tst_qmakelib::proParser_data()
|
|
{
|
|
QTest::addColumn<QString>("in");
|
|
QTest::addColumn<QString>("out");
|
|
QTest::addColumn<QString>("msgs");
|
|
QTest::addColumn<bool>("ok");
|
|
|
|
QTest::newRow("empty")
|
|
<< ""
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("empty (whitespace)")
|
|
<< " \t \t"
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
addParseOperators(); // Variable operators
|
|
|
|
addParseValues();
|
|
|
|
addParseConditions(); // "Tests"
|
|
|
|
addParseControlStatements();
|
|
|
|
addParseBraces();
|
|
|
|
addParseCustomFunctions();
|
|
|
|
addParseAbuse(); // Mostly operator abuse
|
|
|
|
// option() (these produce no tokens)
|
|
|
|
QTest::newRow("option(host_build)")
|
|
<< "option(host_build)"
|
|
<< TS()
|
|
<< ""
|
|
<< true;
|
|
|
|
QTest::newRow("option()")
|
|
<< "option()"
|
|
<< TS()
|
|
<< "in:1: option() requires one literal argument."
|
|
<< false;
|
|
|
|
QTest::newRow("option(host_build magic)")
|
|
<< "option(host_build magic)"
|
|
<< TS()
|
|
<< "in:1: option() requires one literal argument."
|
|
<< false;
|
|
|
|
QTest::newRow("option(host_build, magic)")
|
|
<< "option(host_build, magic)"
|
|
<< TS()
|
|
<< "in:1: option() requires one literal argument."
|
|
<< false;
|
|
|
|
QTest::newRow("option($$OPTION)")
|
|
<< "option($$OPTION)"
|
|
<< TS()
|
|
<< "in:1: option() requires one literal argument."
|
|
<< false;
|
|
|
|
QTest::newRow("{option(host_build)}")
|
|
<< "{option(host_build)}"
|
|
<< TS()
|
|
<< "in:1: option() must appear outside any control structures."
|
|
<< false;
|
|
}
|
|
|
|
QT_WARNING_POP
|
|
|
|
void tst_qmakelib::proParser()
|
|
{
|
|
QFETCH(QString, in);
|
|
QFETCH(QString, out);
|
|
QFETCH(QString, msgs);
|
|
QFETCH(bool, ok);
|
|
|
|
bool verified = true;
|
|
QMakeTestHandler handler;
|
|
handler.setExpectedMessages(msgs.split('\n', Qt::SkipEmptyParts));
|
|
QMakeVfs vfs;
|
|
QMakeParser parser(0, &vfs, &handler);
|
|
ProFile *pro = parser.parsedProBlock(QStringRef(&in), 0, "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);
|
|
}
|