diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /tests/auto/qregexp | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'tests/auto/qregexp')
-rw-r--r-- | tests/auto/qregexp/.gitignore | 1 | ||||
-rw-r--r-- | tests/auto/qregexp/qregexp.pro | 8 | ||||
-rw-r--r-- | tests/auto/qregexp/tst_qregexp.cpp | 1282 |
3 files changed, 1291 insertions, 0 deletions
diff --git a/tests/auto/qregexp/.gitignore b/tests/auto/qregexp/.gitignore new file mode 100644 index 0000000..e6e629e --- /dev/null +++ b/tests/auto/qregexp/.gitignore @@ -0,0 +1 @@ +tst_qregexp diff --git a/tests/auto/qregexp/qregexp.pro b/tests/auto/qregexp/qregexp.pro new file mode 100644 index 0000000..0712496 --- /dev/null +++ b/tests/auto/qregexp/qregexp.pro @@ -0,0 +1,8 @@ +load(qttest_p4) + +QT = core + +SOURCES += tst_qregexp.cpp +QT -= gui + + diff --git a/tests/auto/qregexp/tst_qregexp.cpp b/tests/auto/qregexp/tst_qregexp.cpp new file mode 100644 index 0000000..2968a8e --- /dev/null +++ b/tests/auto/qregexp/tst_qregexp.cpp @@ -0,0 +1,1282 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <qregexp.h> + +const int N = 1; + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QRegExp : public QObject +{ + Q_OBJECT + +public: + tst_QRegExp(); + virtual ~tst_QRegExp(); + + +public slots: + void init(); + void cleanup(); +private slots: + void getSetCheck(); + void indexIn_data(); + void indexIn_addMoreRows(const QByteArray &stri); + void indexIn(); + void lastIndexIn_data(); + void lastIndexIn(); + void matchedLength(); + void wildcard_data(); + void wildcard(); + void caretAnchoredOptimization(); + void isEmpty(); + void prepareEngineOptimization(); + void operator_eq(); + + /* + void isValid(); + void pattern(); + void setPattern(); + void caseSensitive(); + void setCaseSensitive(); + void minimal(); + void setMinimal(); +*/ + void exactMatch(); + void capturedTexts(); +/* + void cap(); + void pos(); + void errorString(); + void escape(); +*/ + void staticRegExp(); + void rainersSlowRegExpCopyBug(); + void nonExistingBackReferenceBug(); + + void reentrancy(); + void threadsafeEngineCache(); +}; + +// Testing get/set functions +void tst_QRegExp::getSetCheck() +{ + QRegExp obj1; + // PatternSyntax QRegExp::patternSyntax() + // void QRegExp::setPatternSyntax(PatternSyntax) + obj1.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::RegExp)); + QCOMPARE(QRegExp::PatternSyntax(QRegExp::RegExp), obj1.patternSyntax()); + obj1.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::Wildcard)); + QCOMPARE(QRegExp::PatternSyntax(QRegExp::Wildcard), obj1.patternSyntax()); + obj1.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::FixedString)); + QCOMPARE(QRegExp::PatternSyntax(QRegExp::FixedString), obj1.patternSyntax()); +} + +extern const char email[]; + +tst_QRegExp::tst_QRegExp() +{ +} + +tst_QRegExp::~tst_QRegExp() +{ +} + +void tst_QRegExp::lastIndexIn_data() +{ + indexIn_data(); +} + +void tst_QRegExp::indexIn_data() +{ + QTest::addColumn<QString>("regexpStr"); + QTest::addColumn<QString>("target"); + QTest::addColumn<int>("pos"); + QTest::addColumn<int>("len"); + QTest::addColumn<QStringList>("caps"); + + for (int i = 0; i < N; ++i) { + QByteArray stri; + if (i > 0) + stri.setNum(i); + + // anchors + QTest::newRow( stri + "anc00" ) << QString("a(?=)z") << QString("az") << 0 << 2 << QStringList(); + QTest::newRow( stri + "anc01" ) << QString("a(?!)z") << QString("az") << -1 << -1 << QStringList(); + QTest::newRow( stri + "anc02" ) << QString("a(?:(?=)|(?=))z") << QString("az") << 0 << 2 + << QStringList(); + QTest::newRow( stri + "anc03" ) << QString("a(?:(?=)|(?!))z") << QString("az") << 0 << 2 + << QStringList(); + QTest::newRow( stri + "anc04" ) << QString("a(?:(?!)|(?=))z") << QString("az") << 0 << 2 + << QStringList(); + QTest::newRow( stri + "anc05" ) << QString("a(?:(?!)|(?!))z") << QString("az") << -1 << -1 + << QStringList(); + QTest::newRow( stri + "anc06" ) << QString("a(?:(?=)|b)z") << QString("az") << 0 << 2 + << QStringList(); + QTest::newRow( stri + "anc07" ) << QString("a(?:(?=)|b)z") << QString("abz") << 0 << 3 + << QStringList(); + QTest::newRow( stri + "anc08" ) << QString("a(?:(?!)|b)z") << QString("az") << -1 << -1 + << QStringList(); + QTest::newRow( stri + "anc09" ) << QString("a(?:(?!)|b)z") << QString("abz") << 0 << 3 + << QStringList(); +#if 0 + QTest::newRow( stri + "anc10" ) << QString("a?(?=^b$)") << QString("ab") << 0 << 1 + << QStringList(); + QTest::newRow( stri + "anc11" ) << QString("a?(?=^b$)") << QString("b") << 0 << 0 + << QStringList(); +#endif + + // back-references + QTest::newRow( stri + "bref00" ) << QString("(a*)(\\1)") << QString("aaaaa") << 0 << 4 + << QStringList( QStringList() << "aa" << "aa" ); + QTest::newRow( stri + "bref01" ) << QString("<(\\w*)>.+</\\1>") << QString("<b>blabla</b>bla</>") + << 0 << 13 << QStringList( QStringList() << "b" ); + QTest::newRow( stri + "bref02" ) << QString("<(\\w*)>.+</\\1>") << QString("<>blabla</b>bla</>") + << 0 << 18 << QStringList( QStringList() << "" ); + QTest::newRow( stri + "bref03" ) << QString("((a*\\2)\\2)") << QString("aaaa") << 0 << 4 + << QStringList( QStringList() << QString("aaaa") << "aa" ); + QTest::newRow( stri + "bref04" ) << QString("^(aa+)\\1+$") << QString("aaaaaa") << 0 << 6 + << QStringList( QStringList() << QString("aa") ); + QTest::newRow( stri + "bref05" ) << QString("^(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)" + "\\14\\13\\12\\11\\10\\9\\8\\7\\6\\5\\4\\3\\2\\1") + << QString("12345678910111213141413121110987654321") << 0 << 38 + << QStringList( QStringList() << "1" << "2" << "3" << "4" << "5" << "6" + << "7" << "8" << "9" << "10" << "11" + << "12" << "13" << "14"); + + // captures + QTest::newRow( stri + "cap00" ) << QString("(a*)") << QString("") << 0 << 0 + << QStringList( QStringList() << QString("") ); + QTest::newRow( stri + "cap01" ) << QString("(a*)") << QString("aaa") << 0 << 3 + << QStringList( QStringList() << "aaa" ); + QTest::newRow( stri + "cap02" ) << QString("(a*)") << QString("baaa") << 0 << 0 + << QStringList( QStringList() << QString("") ); + QTest::newRow( stri + "cap03" ) << QString("(a*)(a*)") << QString("aaa") << 0 << 3 + << QStringList( QStringList() << QString("aaa") << QString("") ); + QTest::newRow( stri + "cap04" ) << QString("(a*)(b*)") << QString("aaabbb") << 0 << 6 + << QStringList( QStringList() << QString("aaa") << QString("bbb") ); + QTest::newRow( stri + "cap06" ) << QString("(a*)a*") << QString("aaa") << 0 << 3 + << QStringList( QStringList() << QString("aaa") ); + QTest::newRow( stri + "cap07" ) << QString("((a*a*)*)") << QString("aaa") << 0 << 3 + << QStringList( QStringList() << "aaa" << QString("aaa") ); + QTest::newRow( stri + "cap08" ) << QString("(((a)*(b)*)*)") << QString("ababa") << 0 << 5 + << QStringList( QStringList() << QString("ababa") << QString("a") << QString("a") + << "" ); + QTest::newRow( stri + "cap09" ) << QString("(((a)*(b)*)c)*") << QString("") << 0 << 0 + << QStringList( QStringList() << QString("") << QString("") << QString("") << QString("") ); + QTest::newRow( stri + "cap10" ) << QString("(((a)*(b)*)c)*") << QString("abc") << 0 << 3 + << QStringList( QStringList() << "abc" << "ab" << "a" + << "b" ); + QTest::newRow( stri + "cap11" ) << QString("(((a)*(b)*)c)*") << QString("abcc") << 0 << 4 + << QStringList( QStringList() << "c" << "" << "" << "" ); + QTest::newRow( stri + "cap12" ) << QString("(((a)*(b)*)c)*") << QString("abcac") << 0 << 5 + << QStringList( QStringList() << "ac" << "a" << "a" << "" ); + QTest::newRow( stri + "cap13" ) << QString("(to|top)?(o|polo)?(gical|o?logical)") + << QString("topological") << 0 << 11 + << QStringList( QStringList() << "top" << "o" + << "logical" ); + QTest::newRow( stri + "cap14" ) << QString("(a)+") << QString("aaaa") << 0 << 4 + << QStringList( QStringList() << "a" ); + + // concatenation + QTest::newRow( stri + "cat00" ) << QString("") << QString("") << 0 << 0 << QStringList(); + QTest::newRow( stri + "cat01" ) << QString("") << QString("a") << 0 << 0 << QStringList(); + QTest::newRow( stri + "cat02" ) << QString("a") << QString("") << -1 << -1 << QStringList(); + QTest::newRow( stri + "cat03" ) << QString("a") << QString("a") << 0 << 1 << QStringList(); + QTest::newRow( stri + "cat04" ) << QString("a") << QString("b") << -1 << -1 << QStringList(); + QTest::newRow( stri + "cat05" ) << QString("b") << QString("a") << -1 << -1 << QStringList(); + QTest::newRow( stri + "cat06" ) << QString("ab") << QString("ab") << 0 << 2 << QStringList(); + QTest::newRow( stri + "cat07" ) << QString("ab") << QString("ba") << -1 << -1 << QStringList(); + QTest::newRow( stri + "cat08" ) << QString("abab") << QString("abbaababab") << 4 << 4 + << QStringList(); + + indexIn_addMoreRows(stri); + } +} + + + +void tst_QRegExp::indexIn_addMoreRows(const QByteArray &stri) +{ + + // from Perl Cookbook + QTest::newRow( stri + "cook00" ) << QString("^(m*)(d?c{0,3}|c[dm])(1?x{0,3}|x[lc])(v?i{0" + ",3}|i[vx])$") + << QString("mmxl") << 0 << 4 + << QStringList( QStringList() << "mm" << "" << "xl" + << "" ); + QTest::newRow( stri + "cook01" ) << QString("(\\S+)(\\s+)(\\S+)") << QString(" a b") << 1 << 5 + << QStringList( QStringList() << "a" << " " << "b" ); + QTest::newRow( stri + "cook02" ) << QString("(\\w+)\\s*=\\s*(.*)\\s*$") << QString(" PATH=. ") << 1 + << 7 << QStringList( QStringList() << "PATH" << ". " ); + QTest::newRow( stri + "cook03" ) << QString(".{80,}") + << QString("0000000011111111222222223333333344444444555" + "5555566666666777777778888888899999999000000" + "00aaaaaaaa") + << 0 << 96 << QStringList(); + QTest::newRow( stri + "cook04" ) << QString("(\\d+)/(\\d+)/(\\d+) (\\d+):(\\d+):(\\d+)") + << QString("1978/05/24 07:30:00") << 0 << 19 + << QStringList( QStringList() << "1978" << "05" << "24" + << "07" << "30" << "00" ); + QTest::newRow( stri + "cook05" ) << QString("/usr/bin") << QString("/usr/local/bin:/usr/bin") + << 15 << 8 << QStringList(); + QTest::newRow( stri + "cook06" ) << QString("%([0-9A-Fa-f]{2})") << QString("http://%7f") << 7 << 3 + << QStringList( QStringList() << "7f" ); + QTest::newRow( stri + "cook07" ) << QString("/\\*.*\\*/") << QString("i++; /* increment i */") << 5 + << 17 << QStringList(); + QTest::newRow( stri + "cook08" ) << QString("^\\s+") << QString(" aaa ") << 0 << 3 + << QStringList(); + QTest::newRow( stri + "cook09" ) << QString("\\s+$") << QString(" aaa ") << 6 << 3 + << QStringList(); + QTest::newRow( stri + "cook10" ) << QString("^.*::") << QString("Box::cat") << 0 << 5 + << QStringList(); + QTest::newRow( stri + "cook11" ) << QString("^([01]?\\d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\" + "d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-" + "4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-4]\\d|25[" + "0-5])$") + << QString("255.00.40.30") << 0 << 12 + << QStringList( QStringList() << "255" << "00" << "40" + << "30" ); + QTest::newRow( stri + "cook12" ) << QString("^.*/") << QString(" /usr/local/bin/moc") << 0 << 16 + << QStringList(); + QTest::newRow( stri + "cook13" ) << QString(":co#(\\d+):") << QString("bla:co#55:") << 3 << 7 + << QStringList( QStringList() << "55" ); + QTest::newRow( stri + "cook14" ) << QString("linux") << QString("alphalinuxinunix") << 5 << 5 + << QStringList(); + QTest::newRow( stri + "cook15" ) << QString("(\\d+\\.?\\d*|\\.\\d+)") << QString("0.0.5") << 0 << 3 + << QStringList( QStringList() << "0.0" ); + + // mathematical trivia + QTest::newRow( stri + "math00" ) << QString("^(a\\1*)$") << QString("a") << 0 << 1 + << QStringList( QStringList() << "a" ); + QTest::newRow( stri + "math01" ) << QString("^(a\\1*)$") << QString("aa") << 0 << 2 + << QStringList( QStringList() << "aa" ); + QTest::newRow( stri + "math02" ) << QString("^(a\\1*)$") << QString("aaa") << -1 << -1 + << QStringList( QStringList() << QString() ); + QTest::newRow( stri + "math03" ) << QString("^(a\\1*)$") << QString("aaaa") << 0 << 4 + << QStringList( QStringList() << "aaaa" ); + QTest::newRow( stri + "math04" ) << QString("^(a\\1*)$") << QString("aaaaa") << -1 << -1 + << QStringList( QStringList() << QString() ); + QTest::newRow( stri + "math05" ) << QString("^(a\\1*)$") << QString("aaaaaa") << -1 << -1 + << QStringList( QStringList() << QString() ); + QTest::newRow( stri + "math06" ) << QString("^(a\\1*)$") << QString("aaaaaaa") << -1 << -1 + << QStringList( QStringList() << QString() ); + QTest::newRow( stri + "math07" ) << QString("^(a\\1*)$") << QString("aaaaaaaa") << 0 << 8 + << QStringList( QStringList() << "aaaaaaaa" ); + QTest::newRow( stri + "math08" ) << QString("^(a\\1*)$") << QString("aaaaaaaaa") << -1 << -1 + << QStringList( QStringList() << QString() ); + QTest::newRow( stri + "math09" ) << QString("^a(?:a(\\1a))*$") << QString("a") << 0 << 1 + << QStringList( QStringList() << "" ); + QTest::newRow( stri + "math10" ) << QString("^a(?:a(\\1a))*$") << QString("aaa") << 0 << 3 + << QStringList( QStringList() << "a" ); + + QTest::newRow( stri + "math13" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|(" + "?=a$)))*a$") + << QString("aaa") << 0 << 3 + << QStringList( QStringList() << "a" << "a" << "" ); + QTest::newRow( stri + "math14" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|(" + "?=a$)))*a$") + << QString("aaaaa") << 0 << 5 + << QStringList( QStringList() << "a" << "a" << "aa" ); + QTest::newRow( stri + "math17" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") + << QString("aaa") << 0 << 3 + << QStringList( QStringList() << "" << "" << "" << "aaa" + << "a" << "aa" ); + QTest::newRow( stri + "math18" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") + << QString("aaaaa") << 0 << 5 + << QStringList( QStringList() << "aaaaa" << "a" << "aaa" + << "" << "" << "" ); + QTest::newRow( stri + "math19" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") + << QString("aaaaaaaa") << 0 << 8 + << QStringList( QStringList() << "" << "" << "" + << "aaaaaaaa" << "a" + << "aa" ); + QTest::newRow( stri + "math20" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") + << QString("aaaaaaaaa") << -1 << -1 + << QStringList( QStringList() << QString() + << QString() + << QString() + << QString() + << QString() + << QString() ); + QTest::newRow( stri + "math21" ) << QString("^(aa+)\\1+$") << QString("aaaaaaaaaaaa") << 0 << 12 + << QStringList( QStringList() << "aa" ); + + static const char * const squareRegExp[] = { + "^a(?:(\\1aa)a)*$", + "^(\\2(\\1a))+$", +#if 0 + "^(?:(\\B\\1aa|^a))+$", +#endif + "^((\\2a)*)\\1\\2a$", + 0 + }; + + int ii = 0; + + while ( squareRegExp[ii] != 0 ) { + for ( int j = 0; j < 100; j++ ) { + QString name; + name.sprintf( "square%.1d%.2d", ii, j ); + + QString target = ""; + target.fill( 'a', j ); + + int pos = -1; + int len = -1; + + for ( int k = 1; k * k <= j; k++ ) { + if ( k * k == j ) { + pos = 0; + len = j; + break; + } + } + + QTest::newRow( name.toLatin1() ) << QString( squareRegExp[ii] ) << target + << pos << len << QStringList( "IGNORE ME" ); + } + ii++; + } + + // miscellaneous + QTest::newRow( stri + "misc00" ) << QString(email) + << QString("troll1@trolltech.com") << 0 << 20 + << QStringList(); + QTest::newRow( stri + "misc01" ) << QString("[0-9]*\\.[0-9]+") << QString("pi = 3.14") << 5 << 4 + << QStringList(); + + // or operator + QTest::newRow( stri + "or00" ) << QString("(?:|b)") << QString("xxx") << 0 << 0 << QStringList(); + QTest::newRow( stri + "or01" ) << QString("(?:|b)") << QString("b") << 0 << 1 << QStringList(); + QTest::newRow( stri + "or02" ) << QString("(?:b|)") << QString("") << 0 << 0 << QStringList(); + QTest::newRow( stri + "or03" ) << QString("(?:b|)") << QString("b") << 0 << 1 << QStringList(); + QTest::newRow( stri + "or04" ) << QString("(?:||b||)") << QString("") << 0 << 0 << QStringList(); + QTest::newRow( stri + "or05" ) << QString("(?:||b||)") << QString("b") << 0 << 1 << QStringList(); + QTest::newRow( stri + "or06" ) << QString("(?:a|b)") << QString("") << -1 << -1 << QStringList(); + QTest::newRow( stri + "or07" ) << QString("(?:a|b)") << QString("cc") << -1 << -1 << QStringList(); + QTest::newRow( stri + "or08" ) << QString("(?:a|b)") << QString("abc") << 0 << 1 << QStringList(); + QTest::newRow( stri + "or09" ) << QString("(?:a|b)") << QString("cba") << 1 << 1 << QStringList(); + QTest::newRow( stri + "or10" ) << QString("(?:ab|ba)") << QString("aba") << 0 << 2 + << QStringList(); + QTest::newRow( stri + "or11" ) << QString("(?:ab|ba)") << QString("bab") << 0 << 2 + << QStringList(); + QTest::newRow( stri + "or12" ) << QString("(?:ab|ba)") << QString("caba") << 1 << 2 + << QStringList(); + QTest::newRow( stri + "or13" ) << QString("(?:ab|ba)") << QString("cbab") << 1 << 2 + << QStringList(); + + // quantifiers + QTest::newRow( stri + "qua00" ) << QString("((([a-j])){0,0})") << QString("") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua01" ) << QString("((([a-j])){0,0})") << QString("a") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua02" ) << QString("((([a-j])){0,0})") << QString("xyz") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua03" ) << QString("((([a-j]))?)") << QString("") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua04" ) << QString("((([a-j]))?)") << QString("a") << 0 << 1 + << QStringList( QStringList() << "a" << "a" << "a" ); + QTest::newRow( stri + "qua05" ) << QString("((([a-j]))?)") << QString("x") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua06" ) << QString("((([a-j]))?)") << QString("ab") << 0 << 1 + << QStringList( QStringList() << "a" << "a" << "a" ); + QTest::newRow( stri + "qua07" ) << QString("((([a-j]))?)") << QString("xa") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua08" ) << QString("((([a-j])){0,3})") << QString("") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua09" ) << QString("((([a-j])){0,3})") << QString("a") << 0 << 1 + << QStringList( QStringList() << "a" << "a" << "a" ); + QTest::newRow( stri + "qua10" ) << QString("((([a-j])){0,3})") << QString("abcd") << 0 << 3 + << QStringList( QStringList() << "abc" << "c" << "c" ); + QTest::newRow( stri + "qua11" ) << QString("((([a-j])){0,3})") << QString("abcde") << 0 << 3 + << QStringList( QStringList() << "abc" << "c" << "c" ); + QTest::newRow( stri + "qua12" ) << QString("((([a-j])){2,4})") << QString("a") << -1 << -1 + << QStringList( QStringList() << QString() + << QString() + << QString() ); + QTest::newRow( stri + "qua13" ) << QString("((([a-j])){2,4})") << QString("ab") << 0 << 2 + << QStringList( QStringList() << "ab" << "b" << "b" ); + QTest::newRow( stri + "qua14" ) << QString("((([a-j])){2,4})") << QString("abcd") << 0 << 4 + << QStringList( QStringList() << "abcd" << "d" << "d" ); + QTest::newRow( stri + "qua15" ) << QString("((([a-j])){2,4})") << QString("abcdef") << 0 << 4 + << QStringList( QStringList() << "abcd" << "d" << "d" ); + QTest::newRow( stri + "qua16" ) << QString("((([a-j])){2,4})") << QString("xaybcd") << 3 << 3 + << QStringList( QStringList() << "bcd" << "d" << "d" ); + QTest::newRow( stri + "qua17" ) << QString("((([a-j])){0,})") << QString("abcdefgh") << 0 << 8 + << QStringList( QStringList() << "abcdefgh" << "h" << "h" ); + QTest::newRow( stri + "qua18" ) << QString("((([a-j])){,0})") << QString("abcdefgh") << 0 << 0 + << QStringList( QStringList() << "" << "" << "" ); + QTest::newRow( stri + "qua19" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("123332333") << 0 + << 9 + << QStringList( QStringList() << "123332333" << "2333" + << "3" ); + QTest::newRow( stri + "qua20" ) << QString("(1(2(3){3,4}){2,3}){1,2}") + << QString("12333323333233331233332333323333") << 0 << 32 + << QStringList( QStringList() << "1233332333323333" + << "23333" << "3" ); + QTest::newRow( stri + "qua21" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("") << -1 << -1 + << QStringList( QStringList() << QString() + << QString() + << QString() ); + QTest::newRow( stri + "qua22" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333") << -1 + << -1 + << QStringList( QStringList() << QString() + << QString() + << QString() ); + QTest::newRow( stri + "qua23" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333233") << -1 + << -1 + << QStringList( QStringList() << QString() + << QString() + << QString() ); + QTest::newRow( stri + "qua24" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("122333") << -1 + << -1 + << QStringList( QStringList() << QString() + << QString() + << QString() ); + + // star operator + QTest::newRow( stri + "star00" ) << QString("(?:)*") << QString("") << 0 << 0 << QStringList(); + QTest::newRow( stri + "star01" ) << QString("(?:)*") << QString("abc") << 0 << 0 << QStringList(); + QTest::newRow( stri + "star02" ) << QString("(?:a)*") << QString("") << 0 << 0 << QStringList(); + QTest::newRow( stri + "star03" ) << QString("(?:a)*") << QString("a") << 0 << 1 << QStringList(); + QTest::newRow( stri + "star04" ) << QString("(?:a)*") << QString("aaa") << 0 << 3 << QStringList(); + QTest::newRow( stri + "star05" ) << QString("(?:a)*") << QString("bbbbaaa") << 0 << 0 + << QStringList(); + QTest::newRow( stri + "star06" ) << QString("(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 0 + << QStringList(); + QTest::newRow( stri + "star07" ) << QString("(?:b)*(?:a)*") << QString("") << 0 << 0 + << QStringList(); + QTest::newRow( stri + "star08" ) << QString("(?:b)*(?:a)*") << QString("a") << 0 << 1 + << QStringList(); + QTest::newRow( stri + "star09" ) << QString("(?:b)*(?:a)*") << QString("aaa") << 0 << 3 + << QStringList(); + QTest::newRow( stri + "star10" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaa") << 0 << 7 + << QStringList(); + QTest::newRow( stri + "star11" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 7 + << QStringList(); + QTest::newRow( stri + "star12" ) << QString("(?:a|b)*") << QString("c") << 0 << 0 << QStringList(); + QTest::newRow( stri + "star13" ) << QString("(?:a|b)*") << QString("abac") << 0 << 3 + << QStringList(); + QTest::newRow( stri + "star14" ) << QString("(?:a|b|)*") << QString("c") << 0 << 0 + << QStringList(); + QTest::newRow( stri + "star15" ) << QString("(?:a|b|)*") << QString("abac") << 0 << 3 + << QStringList(); + QTest::newRow( stri + "star16" ) << QString("(?:ab|ba|b)*") << QString("abbbababbbaaab") << 0 << 11 + << QStringList(); +} + + +void tst_QRegExp::init() +{ +} + +void tst_QRegExp::cleanup() +{ +} + +/* +void tst_QRegExp::isEmpty() +{ +} + +void tst_QRegExp::isValid() +{ +} + +void tst_QRegExp::pattern() +{ +} + +void tst_QRegExp::setPattern() +{ +} + +void tst_QRegExp::caseSensitive() +{ +} + +void tst_QRegExp::setCaseSensitive() +{ +} + +void tst_QRegExp::minimal() +{ +} + +void tst_QRegExp::setMinimal() +{ +} +*/ + +void tst_QRegExp::exactMatch() +{ +#if QT_VERSION >= 0x030100 + QRegExp rx_d( "\\d" ); + QRegExp rx_s( "\\s" ); + QRegExp rx_w( "\\w" ); + QRegExp rx_D( "\\D" ); + QRegExp rx_S( "\\S" ); + QRegExp rx_W( "\\W" ); + + for ( int i = 0; i < 65536; i++ ) { + QChar ch( i ); + bool is_d = ( ch.category() == QChar::Number_DecimalDigit ); + bool is_s = ch.isSpace(); + bool is_w = ( ch.isLetterOrNumber() +#if QT_VERSION >= 0x040200 + || ch.isMark() +#endif + || ch == '_' ); + + QVERIFY( rx_d.exactMatch(QString(ch)) == is_d ); + QVERIFY( rx_s.exactMatch(QString(ch)) == is_s ); + QVERIFY( rx_w.exactMatch(QString(ch)) == is_w ); + QVERIFY( rx_D.exactMatch(QString(ch)) != is_d ); + QVERIFY( rx_S.exactMatch(QString(ch)) != is_s ); + QVERIFY( rx_W.exactMatch(QString(ch)) != is_w ); + } +#endif +} + +void tst_QRegExp::capturedTexts() +{ + QRegExp rx1("a*(a*)", Qt::CaseSensitive, QRegExp::RegExp); + rx1.exactMatch("aaa"); + QCOMPARE(rx1.matchedLength(), 3); + QCOMPARE(rx1.cap(0), QString("aaa")); + QCOMPARE(rx1.cap(1), QString("aaa")); + +#if QT_VERSION >= 0x040200 + QRegExp rx2("a*(a*)", Qt::CaseSensitive, QRegExp::RegExp2); + rx2.exactMatch("aaa"); + QCOMPARE(rx2.matchedLength(), 3); + QCOMPARE(rx2.cap(0), QString("aaa")); + QCOMPARE(rx2.cap(1), QString("")); +#endif + + QRegExp rx3("(?:a|aa)(a*)", Qt::CaseSensitive, QRegExp::RegExp); + rx3.exactMatch("aaa"); + QCOMPARE(rx3.matchedLength(), 3); + QCOMPARE(rx3.cap(0), QString("aaa")); + QCOMPARE(rx3.cap(1), QString("aa")); + +#if QT_VERSION >= 0x040200 + QRegExp rx4("(?:a|aa)(a*)", Qt::CaseSensitive, QRegExp::RegExp2); + rx4.exactMatch("aaa"); + QCOMPARE(rx4.matchedLength(), 3); + QCOMPARE(rx4.cap(0), QString("aaa")); + QCOMPARE(rx4.cap(1), QString("a")); +#endif + + QRegExp rx5("(a)*(a*)", Qt::CaseSensitive, QRegExp::RegExp); + rx5.exactMatch("aaa"); + QCOMPARE(rx5.matchedLength(), 3); + QCOMPARE(rx5.cap(0), QString("aaa")); + QCOMPARE(rx5.cap(1), QString("a")); + QCOMPARE(rx5.cap(2), QString("aa")); + +#if QT_VERSION >= 0x040200 + QRegExp rx6("(a)*(a*)", Qt::CaseSensitive, QRegExp::RegExp2); + rx6.exactMatch("aaa"); + QCOMPARE(rx6.matchedLength(), 3); + QCOMPARE(rx6.cap(0), QString("aaa")); + QCOMPARE(rx6.cap(1), QString("a")); + QCOMPARE(rx6.cap(2), QString("")); +#endif + + QRegExp rx7("([A-Za-z_])([A-Za-z_0-9]*)"); + rx7.setCaseSensitivity(Qt::CaseSensitive); + rx7.setPatternSyntax(QRegExp::RegExp); + QCOMPARE(rx7.numCaptures(), 2); + + int pos = rx7.indexIn("(10 + delta4) * 32"); + QCOMPARE(pos, 6); + QCOMPARE(rx7.matchedLength(), 6); + QCOMPARE(rx7.cap(0), QString("delta4")); + QCOMPARE(rx7.cap(1), QString("d")); + QCOMPARE(rx7.cap(2), QString("elta4")); +} + +/* +void tst_QRegExp::cap() +{ +} + +void tst_QRegExp::pos() +{ +} + +void tst_QRegExp::errorString() +{ +} + +void tst_QRegExp::escape() +{ +} +*/ + +void tst_QRegExp::indexIn() +{ + QFETCH( QString, regexpStr ); + QFETCH( QString, target ); + QFETCH( int, pos ); + QFETCH( int, len ); + QFETCH( QStringList, caps ); + + caps.prepend( "dummy cap(0)" ); + + { + QRegExp rx( regexpStr ); + QVERIFY( rx.isValid() ); + + int mypos = rx.indexIn( target ); + int mylen = rx.matchedLength(); + QStringList mycaps = rx.capturedTexts(); + + QCOMPARE( mypos, pos ); + QCOMPARE( mylen, len ); + if ( caps.size() > 1 && caps[1] != "IGNORE ME" ) { + QCOMPARE( mycaps.count(), caps.count() ); + for ( int i = 1; i < (int) mycaps.count(); i++ ) + QCOMPARE( mycaps[i], caps[i] ); + } + } + +#if QT_VERSION >= 0x040200 + // same as above, but with RegExp2 + { + QRegExp rx( regexpStr, Qt::CaseSensitive, QRegExp::RegExp2 ); + QVERIFY( rx.isValid() ); + + int mypos = rx.indexIn( target ); + int mylen = rx.matchedLength(); + QStringList mycaps = rx.capturedTexts(); + + QCOMPARE( mypos, pos ); + QCOMPARE( mylen, len ); + if ( caps.size() > 1 && caps[1] != "IGNORE ME" ) { + QCOMPARE( mycaps.count(), caps.count() ); + for ( int i = 1; i < (int) mycaps.count(); i++ ) + QCOMPARE( mycaps[i], caps[i] ); + } + } +#endif +} + +void tst_QRegExp::lastIndexIn() +{ + QFETCH( QString, regexpStr ); + QFETCH( QString, target ); + QFETCH( int, pos ); + QFETCH( int, len ); + QFETCH( QStringList, caps ); + + caps.prepend( "dummy" ); + + /* + The test data was really designed for indexIn(), not + lastIndexIn(), but it turns out that we can reuse much of that + for lastIndexIn(). + */ + + { + QRegExp rx( regexpStr ); + QVERIFY( rx.isValid() ); + + int mypos = rx.lastIndexIn( target, target.length() ); + int mylen = rx.matchedLength(); + QStringList mycaps = rx.capturedTexts(); + + if ( mypos <= pos || pos == -1 ) { + QCOMPARE( mypos, pos ); + QCOMPARE( mylen, len ); + + if (caps.size() > 1 && caps[1] != "IGNORE ME") { + QCOMPARE( mycaps.count(), caps.count() ); + for ( int i = 1; i < (int) mycaps.count(); i++ ) + QCOMPARE( mycaps[i], caps[i] ); + } + } + } + +#if QT_VERSION >= 0x040200 + { + QRegExp rx( regexpStr, Qt::CaseSensitive, QRegExp::RegExp2 ); + QVERIFY( rx.isValid() ); + + int mypos = rx.lastIndexIn( target, target.length() ); + int mylen = rx.matchedLength(); + QStringList mycaps = rx.capturedTexts(); + + if ( mypos <= pos || pos == -1 ) { + QCOMPARE( mypos, pos ); + QCOMPARE( mylen, len ); + + if (caps.size() > 1 && caps[1] != "IGNORE ME") { + QCOMPARE( mycaps.count(), caps.count() ); + for ( int i = 1; i < (int) mycaps.count(); i++ ) + QCOMPARE( mycaps[i], caps[i] ); + } + } + } +#endif +} + +void tst_QRegExp::matchedLength() +{ + QRegExp r1( "a+" ); + r1.exactMatch( "aaaba" ); + QCOMPARE( r1.matchedLength(), 3 ); +} + +const char email[] = + "^[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff" + "]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\x" + "ff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:" + "(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@" + ",;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"" + "]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?" + ":\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x" + "80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*" + ")*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*" + "(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\" + "\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015(" + ")]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>" + "@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[" + "\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\" + "x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\\\x" + "80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\" + "015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\" + "\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*@[\\040\\t]*(?:\\([^\\\\\\x" + "80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\" + "015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\" + "\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[" + "\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037" + "\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff" + "])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80" + "-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x" + "80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]" + "*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x" + "80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\" + "\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040" + "\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\" + "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xf" + "f\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-" + "\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015" + "()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x8" + "0-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*|(?:[^(\\040)<>@,;:\".\\\\\\[\\" + "]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x" + "80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^\\\\" + "\\x80-\\xff\\n\\015\"]*)*\")[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\" + "010\\012-\\037]*(?:(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x8" + "0-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\" + "x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)|\"[^\\\\" + "\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015" + "\"]*)*\")[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037]*)*<" + "[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]" + "|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xf" + "f\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:@" + "[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]" + "|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xf" + "f\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[" + "^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:" + "\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015" + "\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n" + "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:" + "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff" + "\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff" + "\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(" + "?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\x" + "ff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-" + "\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xf" + "f])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\" + "040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\" + "([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\" + "n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*(?:,[" + "\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|" + "\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff" + "\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*@[\\0" + "40\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\(" + "[^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n" + "\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\" + "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\" + "\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]" + "]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()" + "]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\" + "x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015" + "()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015" + "()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^" + "\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\0" + "15()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x8" + "0-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?" + ":[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(" + "?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\" + "x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]" + "*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*)*:[\\040\\t]*" + "(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\" + "\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015(" + ")]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)?(?:[^(\\040)" + "<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\" + "[\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^" + "\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\" + "\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\" + "n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\" + "\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\" + "\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff" + "\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^" + "\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\" + "\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\0" + "37\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^" + "\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n" + "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:" + "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff" + "\\n\\015()]*)*\\)[\\040\\t]*)*)*@[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n" + "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:" + "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff" + "\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\0" + "37\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])" + "|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040" + "\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^" + "\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\" + "015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\0" + "40\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\(" + "[^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n" + "\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\" + "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\" + "\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]" + "]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()" + "]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\" + "x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015" + "()]*)*\\)[\\040\\t]*)*)*>)$"; + +void tst_QRegExp::wildcard_data() +{ + QTest::addColumn<QString>("rxp"); + QTest::addColumn<QString>("string"); + QTest::addColumn<int>("foundIndex"); + + QTest::newRow( "data0" ) << QString("*.html") << QString("test.html") << 0; + QTest::newRow( "data1" ) << QString("*.html") << QString("test.htm") << -1; + QTest::newRow( "data2" ) << QString("bar*") << QString("foobarbaz") << 3; + QTest::newRow( "data3" ) << QString("*") << QString("Trolltech") << 0; + QTest::newRow( "data4" ) << QString(".html") << QString("test.html") << 4; + QTest::newRow( "data5" ) << QString(".h") << QString("test.cpp") << -1; + QTest::newRow( "data6" ) << QString(".???l") << QString("test.html") << 4; + QTest::newRow( "data7" ) << QString("?") << QString("test.html") << 0; + QTest::newRow( "data8" ) << QString("?m") << QString("test.html") << 6; + QTest::newRow( "data9" ) << QString(".h[a-z]ml") << QString("test.html") << 4; + QTest::newRow( "data10" ) << QString(".h[A-Z]ml") << QString("test.html") << -1; + QTest::newRow( "data11" ) << QString(".h[A-Z]ml") << QString("test.hTml") << 4; +} + +void tst_QRegExp::wildcard() +{ + QFETCH( QString, rxp ); + QFETCH( QString, string ); + QFETCH( int, foundIndex ); + + QRegExp r( rxp ); + r.setPatternSyntax(QRegExp::Wildcard); + QCOMPARE( r.indexIn( string ), foundIndex ); +} + +void tst_QRegExp::caretAnchoredOptimization() +{ + QString s = "---babnana----"; + s.replace( QRegExp("^-*|(-*)$"), "" ); + QVERIFY(s == "babnana"); + + s = "---babnana----"; + s.replace( QRegExp("^-*|(-{0,})$"), "" ); + QVERIFY(s == "babnana"); + + s = "---babnana----"; + s.replace( QRegExp("^-*|(-{1,})$"), "" ); + QVERIFY(s == "babnana"); + + s = "---babnana----"; + s.replace( QRegExp("^-*|(-+)$"), "" ); + QVERIFY(s == "babnana"); +} + +void tst_QRegExp::isEmpty() +{ + QRegExp rx1; + QVERIFY(rx1.isEmpty()); + + QRegExp rx2 = rx1; + QVERIFY(rx2.isEmpty()); + + rx2.setPattern(""); + QVERIFY(rx2.isEmpty()); + + rx2.setPattern("foo"); + QVERIFY(!rx2.isEmpty()); + + rx2.setPattern(")("); + QVERIFY(!rx2.isEmpty()); + + rx2.setPattern(""); + QVERIFY(rx2.isEmpty()); + + rx2.setPatternSyntax(QRegExp::Wildcard); + rx2.setPattern(""); + QVERIFY(rx2.isEmpty()); +} + +static QRegExp re("foo.*bar"); + +void tst_QRegExp::staticRegExp() +{ + QVERIFY(re.exactMatch("fooHARRYbar")); + // the actual test is that a static regexp should not crash +} + +void tst_QRegExp::rainersSlowRegExpCopyBug() +{ + // this test should take an extreme amount of time if QRegExp is broken + QRegExp original(email); +#if defined(Q_OS_WINCE) + for (int i = 0; i < 100; ++i) { +#else + for (int i = 0; i < 100000; ++i) { +#endif + QRegExp copy = original; + (void)copy.exactMatch("~"); + QRegExp copy2 = original; + } +} + +void tst_QRegExp::nonExistingBackReferenceBug() +{ + { + QRegExp rx("<\\5>"); + QVERIFY(rx.isValid()); + QCOMPARE(rx.indexIn("<>"), 0); + QCOMPARE(rx.capturedTexts(), QStringList("<>")); + } + + { + QRegExp rx("<\\1>"); + QVERIFY(rx.isValid()); + QCOMPARE(rx.indexIn("<>"), 0); + QCOMPARE(rx.capturedTexts(), QStringList("<>")); + } + + { + QRegExp rx("(?:<\\1>)\\1\\5\\4"); + QVERIFY(rx.isValid()); + QCOMPARE(rx.indexIn("<>"), 0); + QCOMPARE(rx.capturedTexts(), QStringList("<>")); + } +} + +class Thread : public QThread +{ +public: + Thread(const QRegExp &rx) : rx(rx) {} + + void run(); + + QRegExp rx; +}; + +void Thread::run() +{ + QString str = "abc"; + for (int i = 0; i < 10; ++i) + str += str; + str += "abbbdekcz"; + int x; + +#if defined(Q_OS_WINCE) + for (int j = 0; j < 100; ++j) { +#else + for (int j = 0; j < 10000; ++j) { +#endif + x = rx.indexIn(str); + } + QCOMPARE(x, 3072); +} + +void tst_QRegExp::reentrancy() +{ + QRegExp rx("(ab{2,}d?e?f?[g-z]?)c"); + Thread *threads[10]; + + for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) { + threads[i] = new Thread(rx); + threads[i]->start(); + } + + for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) + threads[i]->wait(); + + for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) + delete threads[i]; +} + +class Thread2 : public QThread +{ +public: + void run(); +}; + +void Thread2::run() +{ + QRegExp rx("(ab{2,}d?e?f?[g-z]?)c"); + QString str = "abc"; + for (int i = 0; i < 10; ++i) + str += str; + str += "abbbdekcz"; + int x; + +#if defined(Q_OS_WINCE) + for (int j = 0; j < 100; ++j) { +#else + for (int j = 0; j < 10000; ++j) { +#endif + x = rx.indexIn(str); + } + QCOMPARE(x, 3072); +} + +// Test that multiple threads can construct equal QRegExps. +// (In the current QRegExp design each engine instatance will share +// the same cache key, so the threads will race for the cache entry +// in the global cache.) +void tst_QRegExp::threadsafeEngineCache() +{ + Thread2 *threads[10]; + + for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) { + threads[i] = new Thread2(); + threads[i]->start(); + } + + for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) + threads[i]->wait(); + + for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) + delete threads[i]; +} + + +void tst_QRegExp::prepareEngineOptimization() +{ + QRegExp rx0("(f?)(?:(o?)(o?))?"); + + QRegExp rx1(rx0); + + QCOMPARE(rx1.capturedTexts(), QStringList() << "" << "" << "" << ""); + QCOMPARE(rx1.matchedLength(), -1); + QCOMPARE(rx1.matchedLength(), -1); + QCOMPARE(rx1.numCaptures(), 3); + + QCOMPARE(rx1.exactMatch("foo"), true); + QCOMPARE(rx1.matchedLength(), 3); + QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o"); + QCOMPARE(rx1.numCaptures(), 3); + QCOMPARE(rx1.matchedLength(), 3); + QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o"); + QCOMPARE(rx1.pos(3), 2); + + QCOMPARE(rx1.exactMatch("foo"), true); + QCOMPARE(rx1.numCaptures(), 3); + QCOMPARE(rx1.matchedLength(), 3); + QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o"); + QCOMPARE(rx1.pos(3), 2); + + QRegExp rx2 = rx1; + + QCOMPARE(rx1.numCaptures(), 3); + QCOMPARE(rx1.matchedLength(), 3); + QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o"); + QCOMPARE(rx1.pos(3), 2); + + QCOMPARE(rx2.numCaptures(), 3); + QCOMPARE(rx2.matchedLength(), 3); + QCOMPARE(rx2.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o"); + QCOMPARE(rx2.pos(3), 2); + + QCOMPARE(rx1.exactMatch("fo"), true); + QCOMPARE(rx1.numCaptures(), 3); + QCOMPARE(rx1.matchedLength(), 2); + QCOMPARE(rx1.capturedTexts(), QStringList() << "fo" << "f" << "o" << ""); + QCOMPARE(rx1.pos(2), 1); +#if 0 + QCOMPARE(rx1.pos(3), -1); // ### +#endif + + QRegExp rx3; + QVERIFY(rx3.isValid()); + + QRegExp rx4("foo", Qt::CaseInsensitive, QRegExp::RegExp); + QVERIFY(rx4.isValid()); + +#if QT_VERSION >= 0x040200 + QRegExp rx5("foo", Qt::CaseInsensitive, QRegExp::RegExp2); + QVERIFY(rx5.isValid()); +#endif + + QRegExp rx6("foo", Qt::CaseInsensitive, QRegExp::FixedString); + QVERIFY(rx6.isValid()); + + QRegExp rx7("foo", Qt::CaseInsensitive, QRegExp::Wildcard); + QVERIFY(rx7.isValid()); + + QRegExp rx8("][", Qt::CaseInsensitive, QRegExp::RegExp); + QVERIFY(!rx8.isValid()); + +#if QT_VERSION >= 0x040200 + QRegExp rx9("][", Qt::CaseInsensitive, QRegExp::RegExp2); + QVERIFY(!rx9.isValid()); +#endif + + QRegExp rx10("][", Qt::CaseInsensitive, QRegExp::Wildcard); + QVERIFY(!rx10.isValid()); + + QRegExp rx11("][", Qt::CaseInsensitive, QRegExp::FixedString); + QVERIFY(rx11.isValid()); + QVERIFY(rx11.exactMatch("][")); + QCOMPARE(rx11.matchedLength(), 2); + + rx11.setPatternSyntax(QRegExp::Wildcard); + QVERIFY(!rx11.isValid()); + QCOMPARE(rx11.numCaptures(), 0); + QCOMPARE(rx11.matchedLength(), -1); + + rx11.setPatternSyntax(QRegExp::RegExp); + QVERIFY(!rx11.isValid()); + QCOMPARE(rx11.numCaptures(), 0); + QCOMPARE(rx11.matchedLength(), -1); + + rx11.setPattern("(foo)"); + QVERIFY(rx11.isValid()); + QCOMPARE(rx11.numCaptures(), 1); + QCOMPARE(rx11.matchedLength(), -1); + + QCOMPARE(rx11.indexIn("ofoo"), 1); + QCOMPARE(rx11.numCaptures(), 1); + QCOMPARE(rx11.matchedLength(), 3); + + rx11.setPatternSyntax(QRegExp::RegExp); + QCOMPARE(rx11.numCaptures(), 1); + QCOMPARE(rx11.matchedLength(), 3); + + /* + This behavior isn't entirely consistent with setPatter(), + setPatternSyntax(), and setCaseSensitivity(), but I'm testing + it here to ensure that it doesn't change subtly in future + releases. + */ + rx11.setMinimal(true); + QCOMPARE(rx11.matchedLength(), 3); + rx11.setMinimal(false); + QCOMPARE(rx11.matchedLength(), 3); + + rx11.setPatternSyntax(QRegExp::Wildcard); + QCOMPARE(rx11.numCaptures(), 0); + QCOMPARE(rx11.matchedLength(), -1); + + rx11.setPatternSyntax(QRegExp::RegExp); + QCOMPARE(rx11.numCaptures(), 1); + QCOMPARE(rx11.matchedLength(), -1); +} + +void tst_QRegExp::operator_eq() +{ + const int I = 2; + const int J = 4; + const int K = 2; + const int ELL = 2; + QRegExp rxtable[I * J * K * ELL]; + int n; + + n = 0; + for (int i = 0; i < I; ++i) { + for (int j = 0; j < J; ++j) { + for (int k = 0; k < K; ++k) { + for (int ell = 0; ell < ELL; ++ell) { + Qt::CaseSensitivity cs = i == 0 ? Qt::CaseSensitive : Qt::CaseInsensitive; + QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(j); + bool minimal = k == 0; + + if (ell == 0) { + QRegExp rx("foo", cs, syntax); + rx.setMinimal(minimal); + rxtable[n++] = rx; + } else { + QRegExp rx; + rx.setPattern("bar"); + rx.setMinimal(true); + rx.exactMatch("bar"); + rx.setCaseSensitivity(cs); + rx.setMinimal(minimal); + rx.setPattern("foo"); + rx.setPatternSyntax(syntax); + rx.exactMatch("foo"); + rxtable[n++] = rx; + } + } + } + } + } + + for (int i = 0; i < I * J * K * ELL; ++i) { + for (int j = 0; j < I * J * K * ELL; ++j) { + QCOMPARE(rxtable[i] == rxtable[j], i / ELL == j / ELL); + QCOMPARE(rxtable[i] != rxtable[j], i / ELL != j / ELL); + } + } +} + +QTEST_APPLESS_MAIN(tst_QRegExp) +#include "tst_qregexp.moc" |