QRegExp: fix crash
[profile/ivi/qtbase.git] / tests / auto / corelib / tools / qregexp / tst_qregexp.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/QtTest>
43 #include <qregexp.h>
44
45 const int N = 1;
46
47 class tst_QRegExp : public QObject
48 {
49     Q_OBJECT
50 private slots:
51     void getSetCheck();
52     void indexIn_data();
53     void indexIn_addMoreRows(const QByteArray &stri);
54     void indexIn();
55     void lastIndexIn_data();
56     void lastIndexIn();
57     void matchedLength();
58     void wildcard_data();
59     void wildcard();
60     void testEscapingWildcard_data();
61     void testEscapingWildcard();
62     void testInvalidWildcard_data();
63     void testInvalidWildcard();
64     void caretAnchoredOptimization();
65     void isEmpty();
66     void prepareEngineOptimization();
67     void swap();
68     void operator_eq();
69
70     void exactMatch();
71     void capturedTexts();
72     void staticRegExp();
73     void rainersSlowRegExpCopyBug();
74     void nonExistingBackReferenceBug();
75
76     void reentrancy();
77     void threadsafeEngineCache();
78
79     void posAndCapConsistency_data();
80     void posAndCapConsistency();
81     void interval();
82     void validityCheck_data();
83     void validityCheck();
84 };
85
86 // Testing get/set functions
87 void tst_QRegExp::getSetCheck()
88 {
89     QRegExp obj1;
90     // PatternSyntax QRegExp::patternSyntax()
91     // void QRegExp::setPatternSyntax(PatternSyntax)
92     obj1.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::RegExp));
93     QCOMPARE(QRegExp::PatternSyntax(QRegExp::RegExp), obj1.patternSyntax());
94     obj1.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::Wildcard));
95     QCOMPARE(QRegExp::PatternSyntax(QRegExp::Wildcard), obj1.patternSyntax());
96     obj1.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::FixedString));
97     QCOMPARE(QRegExp::PatternSyntax(QRegExp::FixedString), obj1.patternSyntax());
98 }
99
100 extern const char email[];
101
102 void tst_QRegExp::lastIndexIn_data()
103 {
104     indexIn_data();
105 }
106
107 void tst_QRegExp::indexIn_data()
108 {
109     QTest::addColumn<QString>("regexpStr");
110     QTest::addColumn<QString>("target");
111     QTest::addColumn<int>("pos");
112     QTest::addColumn<int>("len");
113     QTest::addColumn<QStringList>("caps");
114
115     for (int i = 0; i < N; ++i) {
116         QByteArray stri;
117         if (i > 0)
118             stri.setNum(i);
119
120         // anchors
121         QTest::newRow( stri + "anc00" ) << QString("a(?=)z") << QString("az") << 0 << 2 << QStringList();
122         QTest::newRow( stri + "anc01" ) << QString("a(?!)z") << QString("az") << -1 << -1 << QStringList();
123         QTest::newRow( stri + "anc02" ) << QString("a(?:(?=)|(?=))z") << QString("az") << 0 << 2
124                                << QStringList();
125         QTest::newRow( stri + "anc03" ) << QString("a(?:(?=)|(?!))z") << QString("az") << 0 << 2
126                                << QStringList();
127         QTest::newRow( stri + "anc04" ) << QString("a(?:(?!)|(?=))z") << QString("az") << 0 << 2
128                                << QStringList();
129         QTest::newRow( stri + "anc05" ) << QString("a(?:(?!)|(?!))z") << QString("az") << -1 << -1
130                                << QStringList();
131         QTest::newRow( stri + "anc06" ) << QString("a(?:(?=)|b)z") << QString("az") << 0 << 2
132                                << QStringList();
133         QTest::newRow( stri + "anc07" ) << QString("a(?:(?=)|b)z") << QString("abz") << 0 << 3
134                                << QStringList();
135         QTest::newRow( stri + "anc08" ) << QString("a(?:(?!)|b)z") << QString("az") << -1 << -1
136                                << QStringList();
137         QTest::newRow( stri + "anc09" ) << QString("a(?:(?!)|b)z") << QString("abz") << 0 << 3
138                                << QStringList();
139 #if 0
140         QTest::newRow( stri + "anc10" ) << QString("a?(?=^b$)") << QString("ab") << 0 << 1
141                                << QStringList();
142         QTest::newRow( stri + "anc11" ) << QString("a?(?=^b$)") << QString("b") << 0 << 0
143                                << QStringList();
144 #endif
145
146         // back-references
147         QTest::newRow( stri + "bref00" ) << QString("(a*)(\\1)") << QString("aaaaa") << 0 << 4
148                                << QStringList( QStringList() << "aa" << "aa" );
149         QTest::newRow( stri + "bref01" ) << QString("<(\\w*)>.+</\\1>") << QString("<b>blabla</b>bla</>")
150                                << 0 << 13 << QStringList( QStringList() << "b" );
151         QTest::newRow( stri + "bref02" ) << QString("<(\\w*)>.+</\\1>") << QString("<>blabla</b>bla</>")
152                                << 0 << 18 << QStringList( QStringList() << "" );
153         QTest::newRow( stri + "bref03" ) << QString("((a*\\2)\\2)") << QString("aaaa") << 0 << 4
154                                << QStringList( QStringList() << QString("aaaa") << "aa" );
155         QTest::newRow( stri + "bref04" ) << QString("^(aa+)\\1+$") << QString("aaaaaa") << 0 << 6
156                                << QStringList( QStringList() << QString("aa") );
157         QTest::newRow( stri + "bref05" ) << QString("^(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)"
158                                           "\\14\\13\\12\\11\\10\\9\\8\\7\\6\\5\\4\\3\\2\\1")
159                                << QString("12345678910111213141413121110987654321") << 0 << 38
160                                << QStringList( QStringList() << "1" << "2" << "3" << "4" << "5" << "6"
161                                                              << "7" << "8" << "9" << "10" << "11"
162                                                              << "12" << "13" << "14");
163
164         // captures
165         QTest::newRow( stri + "cap00" ) << QString("(a*)") << QString("") << 0 << 0
166                                << QStringList( QStringList() << QString("") );
167         QTest::newRow( stri + "cap01" ) << QString("(a*)") << QString("aaa") << 0 << 3
168                                << QStringList( QStringList() << "aaa" );
169         QTest::newRow( stri + "cap02" ) << QString("(a*)") << QString("baaa") << 0 << 0
170                                << QStringList( QStringList() << QString("") );
171         QTest::newRow( stri + "cap03" ) << QString("(a*)(a*)") << QString("aaa") << 0 << 3
172                                << QStringList( QStringList() << QString("aaa") << QString("") );
173         QTest::newRow( stri + "cap04" ) << QString("(a*)(b*)") << QString("aaabbb") << 0 << 6
174                                << QStringList( QStringList() << QString("aaa") << QString("bbb") );
175         QTest::newRow( stri + "cap06" ) << QString("(a*)a*") << QString("aaa") << 0 << 3
176                                << QStringList( QStringList() << QString("aaa") );
177         QTest::newRow( stri + "cap07" ) << QString("((a*a*)*)") << QString("aaa") << 0 << 3
178                                << QStringList( QStringList() << "aaa" << QString("aaa") );
179         QTest::newRow( stri + "cap08" ) << QString("(((a)*(b)*)*)") << QString("ababa") << 0 << 5
180                                << QStringList( QStringList() << QString("ababa") << QString("a") << QString("a")
181                                << "" );
182         QTest::newRow( stri + "cap09" ) << QString("(((a)*(b)*)c)*") << QString("") << 0 << 0
183                                << QStringList( QStringList() << QString("") << QString("") << QString("") << QString("") );
184         QTest::newRow( stri + "cap10" ) << QString("(((a)*(b)*)c)*") << QString("abc") << 0 << 3
185                                << QStringList( QStringList() << "abc" << "ab" << "a"
186                                << "b" );
187         QTest::newRow( stri + "cap11" ) << QString("(((a)*(b)*)c)*") << QString("abcc") << 0 << 4
188                                << QStringList( QStringList() << "c" << "" << "" << "" );
189         QTest::newRow( stri + "cap12" ) << QString("(((a)*(b)*)c)*") << QString("abcac") << 0 << 5
190                                << QStringList( QStringList() << "ac" << "a" << "a" << "" );
191         QTest::newRow( stri + "cap13" ) << QString("(to|top)?(o|polo)?(gical|o?logical)")
192                                << QString("topological") << 0 << 11
193                                << QStringList( QStringList() << "top" << "o"
194                                                   << "logical" );
195         QTest::newRow( stri + "cap14" ) << QString("(a)+") << QString("aaaa") << 0 << 4
196                                << QStringList( QStringList() << "a" );
197
198         // concatenation
199         QTest::newRow( stri + "cat00" ) << QString("") << QString("") << 0 << 0 << QStringList();
200         QTest::newRow( stri + "cat01" ) << QString("") << QString("a") << 0 << 0 << QStringList();
201         QTest::newRow( stri + "cat02" ) << QString("a") << QString("") << -1 << -1 << QStringList();
202         QTest::newRow( stri + "cat03" ) << QString("a") << QString("a") << 0 << 1 << QStringList();
203         QTest::newRow( stri + "cat04" ) << QString("a") << QString("b") << -1 << -1 << QStringList();
204         QTest::newRow( stri + "cat05" ) << QString("b") << QString("a") << -1 << -1 << QStringList();
205         QTest::newRow( stri + "cat06" ) << QString("ab") << QString("ab") << 0 << 2 << QStringList();
206         QTest::newRow( stri + "cat07" ) << QString("ab") << QString("ba") << -1 << -1 << QStringList();
207         QTest::newRow( stri + "cat08" ) << QString("abab") << QString("abbaababab") << 4 << 4 << QStringList();
208
209         indexIn_addMoreRows(stri);
210     }
211 }
212
213 void tst_QRegExp::indexIn_addMoreRows(const QByteArray &stri)
214 {
215         // from Perl Cookbook
216         QTest::newRow( stri + "cook00" ) << QString("^(m*)(d?c{0,3}|c[dm])(1?x{0,3}|x[lc])(v?i{0,3}|i[vx])$")
217                                 << QString("mmxl") << 0 << 4
218                                 << QStringList( QStringList() << "mm" << "" << "xl"
219                                 << "" );
220         QTest::newRow( stri + "cook01" ) << QString("(\\S+)(\\s+)(\\S+)") << QString(" a   b") << 1 << 5
221                                 << QStringList( QStringList() << "a" << "   " << "b" );
222         QTest::newRow( stri + "cook02" ) << QString("(\\w+)\\s*=\\s*(.*)\\s*$") << QString(" PATH=. ") << 1
223                                 << 7 << QStringList( QStringList() << "PATH" << ". " );
224         QTest::newRow( stri + "cook03" ) << QString(".{80,}")
225                                 << QString("0000000011111111222222223333333344444444555"
226                                    "5555566666666777777778888888899999999000000"
227                                    "00aaaaaaaa")
228                                 << 0 << 96 << QStringList();
229         QTest::newRow( stri + "cook04" ) << QString("(\\d+)/(\\d+)/(\\d+) (\\d+):(\\d+):(\\d+)")
230                                 << QString("1978/05/24 07:30:00") << 0 << 19
231                                 << QStringList( QStringList() << "1978" << "05" << "24"
232                                 << "07" << "30" << "00" );
233         QTest::newRow( stri + "cook05" ) << QString("/usr/bin") << QString("/usr/local/bin:/usr/bin")
234                                 << 15 << 8 << QStringList();
235         QTest::newRow( stri + "cook06" ) << QString("%([0-9A-Fa-f]{2})") << QString("http://%7f") << 7 << 3
236                                 << QStringList( QStringList() << "7f" );
237         QTest::newRow( stri + "cook07" ) << QString("/\\*.*\\*/") << QString("i++; /* increment i */") << 5
238                                 << 17 << QStringList();
239         QTest::newRow( stri + "cook08" ) << QString("^\\s+") << QString("   aaa   ") <<  0 << 3
240                                 << QStringList();
241         QTest::newRow( stri + "cook09" ) << QString("\\s+$") << QString("   aaa   ") <<  6 << 3
242                                 << QStringList();
243         QTest::newRow( stri + "cook10" ) << QString("^.*::") << QString("Box::cat") << 0 << 5
244                                 << QStringList();
245         QTest::newRow( stri + "cook11" ) << QString("^([01]?\\d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\"
246                                    "d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-"
247                                    "4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-4]\\d|25["
248                                    "0-5])$")
249                                 << QString("255.00.40.30") << 0 << 12
250                                 << QStringList( QStringList() << "255" << "00" << "40"
251                                 << "30" );
252         QTest::newRow( stri + "cook12" ) << QString("^.*/") << QString(" /usr/local/bin/moc") << 0 << 16
253                                 << QStringList();
254         QTest::newRow( stri + "cook13" ) << QString(":co#(\\d+):") << QString("bla:co#55:") << 3 << 7
255                                 << QStringList( QStringList() << "55" );
256         QTest::newRow( stri + "cook14" ) << QString("linux") << QString("alphalinuxinunix") << 5 << 5
257                                 << QStringList();
258         QTest::newRow( stri + "cook15" ) << QString("(\\d+\\.?\\d*|\\.\\d+)") << QString("0.0.5") << 0 << 3
259                                 << QStringList( QStringList() << "0.0" );
260
261         // mathematical trivia
262         QTest::newRow( stri + "math00" ) << QString("^(a\\1*)$") << QString("a") << 0 << 1
263                                 << QStringList( QStringList() << "a" );
264         QTest::newRow( stri + "math01" ) << QString("^(a\\1*)$") << QString("aa") << 0 << 2
265                                 << QStringList( QStringList() << "aa" );
266         QTest::newRow( stri + "math02" ) << QString("^(a\\1*)$") << QString("aaa") << -1 << -1
267                                 << QStringList( QStringList() << QString() );
268         QTest::newRow( stri + "math03" ) << QString("^(a\\1*)$") << QString("aaaa") << 0 << 4
269                                 << QStringList( QStringList() << "aaaa" );
270         QTest::newRow( stri + "math04" ) << QString("^(a\\1*)$") << QString("aaaaa") << -1 << -1
271                                 << QStringList( QStringList() << QString() );
272         QTest::newRow( stri + "math05" ) << QString("^(a\\1*)$") << QString("aaaaaa") << -1 << -1
273                                 << QStringList( QStringList() << QString() );
274         QTest::newRow( stri + "math06" ) << QString("^(a\\1*)$") << QString("aaaaaaa") << -1 << -1
275                                 << QStringList( QStringList() << QString() );
276         QTest::newRow( stri + "math07" ) << QString("^(a\\1*)$") << QString("aaaaaaaa") << 0 << 8
277                                 << QStringList( QStringList() << "aaaaaaaa" );
278         QTest::newRow( stri + "math08" ) << QString("^(a\\1*)$") << QString("aaaaaaaaa") << -1 << -1
279                                 << QStringList( QStringList() << QString() );
280         QTest::newRow( stri + "math09" ) << QString("^a(?:a(\\1a))*$") << QString("a") << 0 << 1
281                                 << QStringList( QStringList() << "" );
282         QTest::newRow( stri + "math10" ) << QString("^a(?:a(\\1a))*$") << QString("aaa") << 0 << 3
283                                 << QStringList( QStringList() << "a" );
284
285         QTest::newRow( stri + "math13" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|("
286                                    "?=a$)))*a$")
287                                 << QString("aaa") << 0 << 3
288                                 << QStringList( QStringList() << "a" << "a" << "" );
289         QTest::newRow( stri + "math14" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|("
290                                    "?=a$)))*a$")
291                                 << QString("aaaaa") << 0 << 5
292                                 << QStringList( QStringList() << "a" << "a" << "aa" );
293         QTest::newRow( stri + "math17" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
294                                    ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
295                                 << QString("aaa") << 0 << 3
296                                 << QStringList( QStringList() << "" << "" << "" << "aaa" << "a" << "aa" );
297         QTest::newRow( stri + "math18" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
298                                    ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
299                                 << QString("aaaaa") << 0 << 5
300                                 << QStringList( QStringList() << "aaaaa" << "a" << "aaa" << "" << "" << "" );
301         QTest::newRow( stri + "math19" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
302                                    ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
303                                 << QString("aaaaaaaa") << 0 << 8
304                                 << QStringList( QStringList() << "" << "" << "" << "aaaaaaaa" << "a" << "aa" );
305         QTest::newRow( stri + "math20" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
306                                    ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
307                                 << QString("aaaaaaaaa") << -1 << -1
308                                 << QStringList( QStringList() << QString()
309                                    << QString()
310                                    << QString()
311                                    << QString()
312                                    << QString()
313                                    << QString() );
314         QTest::newRow( stri + "math21" ) << QString("^(aa+)\\1+$") << QString("aaaaaaaaaaaa") << 0 << 12
315                                 << QStringList( QStringList() << "aa" );
316
317         static const char * const squareRegExp[] = {
318             "^a(?:(\\1aa)a)*$",
319             "^(\\2(\\1a))+$",
320             "^((\\2a)*)\\1\\2a$",
321             0
322                 };
323
324         int ii = 0;
325
326         while ( squareRegExp[ii] != 0 ) {
327             for ( int j = 0; j < 100; j++ ) {
328                 QString name;
329                 name.sprintf( "square%.1d%.2d", ii, j );
330
331                 QString target = "";
332                 target.fill( 'a', j );
333
334                 int pos = -1;
335                 int len = -1;
336
337                 for ( int k = 1; k * k <= j; k++ ) {
338                     if ( k * k == j ) {
339                         pos = 0;
340                         len = j;
341                         break;
342                     }
343                 }
344
345                 QTest::newRow( name.toLatin1() ) << QString( squareRegExp[ii] ) << target
346                                 << pos << len << QStringList( "IGNORE ME" );
347             }
348             ii++;
349         }
350
351         // miscellaneous
352         QTest::newRow( stri + "misc00" ) << QString(email)
353                                 << QString("email123@example.com") << 0 << 20
354                                 << QStringList();
355         QTest::newRow( stri + "misc01" ) << QString("[0-9]*\\.[0-9]+") << QString("pi = 3.14") << 5 << 4
356                                 << QStringList();
357
358         // or operator
359         QTest::newRow( stri + "or00" ) << QString("(?:|b)") << QString("xxx") << 0 << 0 << QStringList();
360         QTest::newRow( stri + "or01" ) << QString("(?:|b)") << QString("b") << 0 << 1 << QStringList();
361         QTest::newRow( stri + "or02" ) << QString("(?:b|)") << QString("") << 0 << 0 << QStringList();
362         QTest::newRow( stri + "or03" ) << QString("(?:b|)") << QString("b") << 0 << 1 << QStringList();
363         QTest::newRow( stri + "or04" ) << QString("(?:||b||)") << QString("") << 0 << 0 << QStringList();
364         QTest::newRow( stri + "or05" ) << QString("(?:||b||)") << QString("b") << 0 << 1 << QStringList();
365         QTest::newRow( stri + "or06" ) << QString("(?:a|b)") << QString("") << -1 << -1 << QStringList();
366         QTest::newRow( stri + "or07" ) << QString("(?:a|b)") << QString("cc") << -1 << -1 << QStringList();
367         QTest::newRow( stri + "or08" ) << QString("(?:a|b)") << QString("abc") << 0 << 1 << QStringList();
368         QTest::newRow( stri + "or09" ) << QString("(?:a|b)") << QString("cba") << 1 << 1 << QStringList();
369         QTest::newRow( stri + "or10" ) << QString("(?:ab|ba)") << QString("aba") << 0 << 2
370                               << QStringList();
371         QTest::newRow( stri + "or11" ) << QString("(?:ab|ba)") << QString("bab") << 0 << 2
372                               << QStringList();
373         QTest::newRow( stri + "or12" ) << QString("(?:ab|ba)") << QString("caba") << 1 << 2
374                               << QStringList();
375         QTest::newRow( stri + "or13" ) << QString("(?:ab|ba)") << QString("cbab") << 1 << 2
376                               << QStringList();
377
378         // quantifiers
379         QTest::newRow( stri + "qua00" ) << QString("((([a-j])){0,0})") << QString("") << 0 << 0
380                                << QStringList( QStringList() << "" << "" << "" );
381         QTest::newRow( stri + "qua01" ) << QString("((([a-j])){0,0})") << QString("a") << 0 << 0
382                                << QStringList( QStringList() << "" << "" << "" );
383         QTest::newRow( stri + "qua02" ) << QString("((([a-j])){0,0})") << QString("xyz") << 0 << 0
384                                << QStringList( QStringList() << "" << "" << "" );
385         QTest::newRow( stri + "qua03" ) << QString("((([a-j]))?)") << QString("") << 0 << 0
386                                << QStringList( QStringList() << "" << "" << "" );
387         QTest::newRow( stri + "qua04" ) << QString("((([a-j]))?)") << QString("a") << 0 << 1
388                                << QStringList( QStringList() << "a" << "a" << "a" );
389         QTest::newRow( stri + "qua05" ) << QString("((([a-j]))?)") << QString("x") << 0 << 0
390                                << QStringList( QStringList() << "" << "" << "" );
391         QTest::newRow( stri + "qua06" ) << QString("((([a-j]))?)") << QString("ab") << 0 << 1
392                                << QStringList( QStringList() << "a" << "a" << "a" );
393         QTest::newRow( stri + "qua07" ) << QString("((([a-j]))?)") << QString("xa") << 0 << 0
394                                << QStringList( QStringList() << "" << "" << "" );
395         QTest::newRow( stri + "qua08" ) << QString("((([a-j])){0,3})") << QString("") << 0 << 0
396                                << QStringList( QStringList() << "" << "" << "" );
397         QTest::newRow( stri + "qua09" ) << QString("((([a-j])){0,3})") << QString("a") << 0 << 1
398                                << QStringList( QStringList() << "a" << "a" << "a" );
399         QTest::newRow( stri + "qua10" ) << QString("((([a-j])){0,3})") << QString("abcd") << 0 << 3
400                                << QStringList( QStringList() << "abc" << "c" << "c" );
401         QTest::newRow( stri + "qua11" ) << QString("((([a-j])){0,3})") << QString("abcde") << 0 << 3
402                                << QStringList( QStringList() << "abc" << "c" << "c" );
403         QTest::newRow( stri + "qua12" ) << QString("((([a-j])){2,4})") << QString("a") << -1 << -1
404                                << QStringList( QStringList() << QString()
405                                                   << QString()
406                                                   << QString() );
407         QTest::newRow( stri + "qua13" ) << QString("((([a-j])){2,4})") << QString("ab") << 0 << 2
408                                << QStringList( QStringList() << "ab" << "b" << "b" );
409         QTest::newRow( stri + "qua14" ) << QString("((([a-j])){2,4})") << QString("abcd") << 0 << 4
410                                << QStringList( QStringList() << "abcd" << "d" << "d" );
411         QTest::newRow( stri + "qua15" ) << QString("((([a-j])){2,4})") << QString("abcdef") << 0 << 4
412                                << QStringList( QStringList() << "abcd" << "d" << "d" );
413         QTest::newRow( stri + "qua16" ) << QString("((([a-j])){2,4})") << QString("xaybcd") << 3 << 3
414                                << QStringList( QStringList() << "bcd" << "d" << "d" );
415         QTest::newRow( stri + "qua17" ) << QString("((([a-j])){0,})") << QString("abcdefgh") << 0 << 8
416                                << QStringList( QStringList() << "abcdefgh" << "h" << "h" );
417         QTest::newRow( stri + "qua18" ) << QString("((([a-j])){,0})") << QString("abcdefgh") << 0 << 0
418                                << QStringList( QStringList() << "" << "" << "" );
419         QTest::newRow( stri + "qua19" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("123332333") << 0
420                                << 9
421                                << QStringList( QStringList() << "123332333" << "2333"
422                                                   << "3" );
423         QTest::newRow( stri + "qua20" ) << QString("(1(2(3){3,4}){2,3}){1,2}")
424                                << QString("12333323333233331233332333323333") << 0 << 32
425                                << QStringList( QStringList() << "1233332333323333"
426                                                   << "23333" << "3" );
427         QTest::newRow( stri + "qua21" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("") << -1 << -1
428                                << QStringList( QStringList() << QString()
429                                                   << QString()
430                                                   << QString() );
431         QTest::newRow( stri + "qua22" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333") << -1
432                                << -1
433                                << QStringList( QStringList() << QString()
434                                                   << QString()
435                                                   << QString() );
436         QTest::newRow( stri + "qua23" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333233") << -1
437                                << -1
438                                << QStringList( QStringList() << QString()
439                                                   << QString()
440                                                   << QString() );
441         QTest::newRow( stri + "qua24" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("122333") << -1
442                                << -1
443                                << QStringList( QStringList() << QString()
444                                                   << QString()
445                                                   << QString() );
446
447         // star operator
448         QTest::newRow( stri + "star00" ) << QString("(?:)*") << QString("") << 0 << 0 << QStringList();
449         QTest::newRow( stri + "star01" ) << QString("(?:)*") << QString("abc") << 0 << 0 << QStringList();
450         QTest::newRow( stri + "star02" ) << QString("(?:a)*") << QString("") << 0 << 0 << QStringList();
451         QTest::newRow( stri + "star03" ) << QString("(?:a)*") << QString("a") << 0 << 1 << QStringList();
452         QTest::newRow( stri + "star04" ) << QString("(?:a)*") << QString("aaa") << 0 << 3 << QStringList();
453         QTest::newRow( stri + "star05" ) << QString("(?:a)*") << QString("bbbbaaa") << 0 << 0
454                                 << QStringList();
455         QTest::newRow( stri + "star06" ) << QString("(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 0
456                                 << QStringList();
457         QTest::newRow( stri + "star07" ) << QString("(?:b)*(?:a)*") << QString("") << 0 << 0
458                                 << QStringList();
459         QTest::newRow( stri + "star08" ) << QString("(?:b)*(?:a)*") << QString("a") << 0 << 1
460                                 << QStringList();
461         QTest::newRow( stri + "star09" ) << QString("(?:b)*(?:a)*") << QString("aaa") << 0 << 3
462                                 << QStringList();
463         QTest::newRow( stri + "star10" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaa") << 0 << 7
464                                 << QStringList();
465         QTest::newRow( stri + "star11" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 7
466                                 << QStringList();
467         QTest::newRow( stri + "star12" ) << QString("(?:a|b)*") << QString("c") << 0 << 0 << QStringList();
468         QTest::newRow( stri + "star13" ) << QString("(?:a|b)*") << QString("abac") << 0 << 3
469                                 << QStringList();
470         QTest::newRow( stri + "star14" ) << QString("(?:a|b|)*") << QString("c") << 0 << 0
471                                 << QStringList();
472         QTest::newRow( stri + "star15" ) << QString("(?:a|b|)*") << QString("abac") << 0 << 3
473                                 << QStringList();
474         QTest::newRow( stri + "star16" ) << QString("(?:ab|ba|b)*") << QString("abbbababbbaaab") << 0 << 11
475                                 << QStringList();
476 }
477
478 void tst_QRegExp::exactMatch()
479 {
480     QRegExp rx_d( "\\d" );
481     QRegExp rx_s( "\\s" );
482     QRegExp rx_w( "\\w" );
483     QRegExp rx_D( "\\D" );
484     QRegExp rx_S( "\\S" );
485     QRegExp rx_W( "\\W" );
486
487     for ( int i = 0; i < 65536; i++ ) {
488         QChar ch( i );
489         bool is_d = ( ch.category() == QChar::Number_DecimalDigit );
490         bool is_s = ch.isSpace();
491         bool is_w = ( ch.isLetterOrNumber()
492         || ch.isMark()
493         || ch == '_' );
494
495         QVERIFY( rx_d.exactMatch(QString(ch)) == is_d );
496         QVERIFY( rx_s.exactMatch(QString(ch)) == is_s );
497         QVERIFY( rx_w.exactMatch(QString(ch)) == is_w );
498         QVERIFY( rx_D.exactMatch(QString(ch)) != is_d );
499         QVERIFY( rx_S.exactMatch(QString(ch)) != is_s );
500         QVERIFY( rx_W.exactMatch(QString(ch)) != is_w );
501     }
502 }
503
504 void tst_QRegExp::capturedTexts()
505 {
506     QRegExp rx1("a*(a*)", Qt::CaseSensitive, QRegExp::RegExp);
507     rx1.exactMatch("aaa");
508     QCOMPARE(rx1.matchedLength(), 3);
509     QCOMPARE(rx1.cap(0), QString("aaa"));
510     QCOMPARE(rx1.cap(1), QString("aaa"));
511
512     QRegExp rx2("a*(a*)", Qt::CaseSensitive, QRegExp::RegExp2);
513     rx2.exactMatch("aaa");
514     QCOMPARE(rx2.matchedLength(), 3);
515     QCOMPARE(rx2.cap(0), QString("aaa"));
516     QCOMPARE(rx2.cap(1), QString(""));
517
518     QRegExp rx3("(?:a|aa)(a*)", Qt::CaseSensitive, QRegExp::RegExp);
519     rx3.exactMatch("aaa");
520     QCOMPARE(rx3.matchedLength(), 3);
521     QCOMPARE(rx3.cap(0), QString("aaa"));
522     QCOMPARE(rx3.cap(1), QString("aa"));
523
524     QRegExp rx4("(?:a|aa)(a*)", Qt::CaseSensitive, QRegExp::RegExp2);
525     rx4.exactMatch("aaa");
526     QCOMPARE(rx4.matchedLength(), 3);
527     QCOMPARE(rx4.cap(0), QString("aaa"));
528     QCOMPARE(rx4.cap(1), QString("a"));
529
530     QRegExp rx5("(a)*(a*)", Qt::CaseSensitive, QRegExp::RegExp);
531     rx5.exactMatch("aaa");
532     QCOMPARE(rx5.matchedLength(), 3);
533     QCOMPARE(rx5.cap(0), QString("aaa"));
534     QCOMPARE(rx5.cap(1), QString("a"));
535     QCOMPARE(rx5.cap(2), QString("aa"));
536
537     QRegExp rx6("(a)*(a*)", Qt::CaseSensitive, QRegExp::RegExp2);
538     rx6.exactMatch("aaa");
539     QCOMPARE(rx6.matchedLength(), 3);
540     QCOMPARE(rx6.cap(0), QString("aaa"));
541     QCOMPARE(rx6.cap(1), QString("a"));
542     QCOMPARE(rx6.cap(2), QString(""));
543
544     QRegExp rx7("([A-Za-z_])([A-Za-z_0-9]*)");
545     rx7.setCaseSensitivity(Qt::CaseSensitive);
546     rx7.setPatternSyntax(QRegExp::RegExp);
547     QCOMPARE(rx7.captureCount(), 2);
548
549     int pos = rx7.indexIn("(10 + delta4) * 32");
550     QCOMPARE(pos, 6);
551     QCOMPARE(rx7.matchedLength(), 6);
552     QCOMPARE(rx7.cap(0), QString("delta4"));
553     QCOMPARE(rx7.cap(1), QString("d"));
554     QCOMPARE(rx7.cap(2), QString("elta4"));
555 }
556
557 void tst_QRegExp::indexIn()
558 {
559     QFETCH( QString, regexpStr );
560     QFETCH( QString, target );
561     QFETCH( int, pos );
562     QFETCH( int, len );
563     QFETCH( QStringList, caps );
564
565     caps.prepend( "dummy cap(0)" );
566
567     {
568         QRegExp rx( regexpStr );
569         QVERIFY( rx.isValid() );
570
571         int mypos = rx.indexIn( target );
572         int mylen = rx.matchedLength();
573         QStringList mycaps = rx.capturedTexts();
574
575         QCOMPARE( mypos, pos );
576         QCOMPARE( mylen, len );
577         if ( caps.size() > 1 && caps[1] != "IGNORE ME" ) {
578             QCOMPARE( mycaps.count(), caps.count() );
579             for ( int i = 1; i < (int) mycaps.count(); i++ )
580                 QCOMPARE( mycaps[i], caps[i] );
581         }
582     }
583
584     // same as above, but with RegExp2
585     {
586         QRegExp rx( regexpStr, Qt::CaseSensitive, QRegExp::RegExp2 );
587         QVERIFY( rx.isValid() );
588
589         int mypos = rx.indexIn( target );
590         int mylen = rx.matchedLength();
591         QStringList mycaps = rx.capturedTexts();
592
593         QCOMPARE( mypos, pos );
594         QCOMPARE( mylen, len );
595         if ( caps.size() > 1 && caps[1] != "IGNORE ME" ) {
596             QCOMPARE( mycaps.count(), caps.count() );
597             for ( int i = 1; i < (int) mycaps.count(); i++ )
598                 QCOMPARE( mycaps[i], caps[i] );
599         }
600     }
601 }
602
603 void tst_QRegExp::lastIndexIn()
604 {
605     QFETCH( QString, regexpStr );
606     QFETCH( QString, target );
607     QFETCH( int, pos );
608     QFETCH( int, len );
609     QFETCH( QStringList, caps );
610
611     caps.prepend( "dummy" );
612
613     /*
614       The test data was really designed for indexIn(), not
615       lastIndexIn(), but it turns out that we can reuse much of that
616       for lastIndexIn().
617     */
618
619     {
620         QRegExp rx( regexpStr );
621         QVERIFY( rx.isValid() );
622
623         int mypos = rx.lastIndexIn( target, target.length() );
624         int mylen = rx.matchedLength();
625         QStringList mycaps = rx.capturedTexts();
626
627         if ( mypos <= pos || pos == -1 ) {
628             QCOMPARE( mypos, pos );
629             QCOMPARE( mylen, len );
630
631             if (caps.size() > 1 && caps[1] != "IGNORE ME") {
632                 QCOMPARE( mycaps.count(), caps.count() );
633                 for ( int i = 1; i < (int) mycaps.count(); i++ )
634                     QCOMPARE( mycaps[i], caps[i] );
635             }
636         }
637     }
638
639     {
640         QRegExp rx( regexpStr, Qt::CaseSensitive, QRegExp::RegExp2 );
641         QVERIFY( rx.isValid() );
642
643         int mypos = rx.lastIndexIn( target, target.length() );
644         int mylen = rx.matchedLength();
645         QStringList mycaps = rx.capturedTexts();
646
647         if ( mypos <= pos || pos == -1 ) {
648             QCOMPARE( mypos, pos );
649             QCOMPARE( mylen, len );
650
651             if (caps.size() > 1 && caps[1] != "IGNORE ME") {
652                 QCOMPARE( mycaps.count(), caps.count() );
653                 for ( int i = 1; i < (int) mycaps.count(); i++ )
654                     QCOMPARE( mycaps[i], caps[i] );
655             }
656         }
657     }
658 }
659
660 void tst_QRegExp::matchedLength()
661 {
662     QRegExp r1( "a+" );
663     r1.exactMatch( "aaaba" );
664     QCOMPARE( r1.matchedLength(), 3 );
665 }
666
667 const char email[] =
668     "^[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff"
669     "]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\x"
670     "ff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:"
671     "(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@"
672     ",;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\""
673     "]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?"
674     ":\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x"
675     "80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*"
676     ")*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*"
677     "(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\"
678     "\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015("
679     ")]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>"
680     "@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\["
681     "\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\"
682     "x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\\\x"
683     "80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\"
684     "015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\"
685     "\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*@[\\040\\t]*(?:\\([^\\\\\\x"
686     "80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\"
687     "015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\"
688     "\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\["
689     "\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037"
690     "\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff"
691     "])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80"
692     "-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x"
693     "80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]"
694     "*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x"
695     "80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\"
696     "\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040"
697     "\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\"
698     "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xf"
699     "f\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-"
700     "\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015"
701     "()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x8"
702     "0-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*|(?:[^(\\040)<>@,;:\".\\\\\\[\\"
703     "]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x"
704     "80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^\\\\"
705     "\\x80-\\xff\\n\\015\"]*)*\")[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\"
706     "010\\012-\\037]*(?:(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x8"
707     "0-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\"
708     "x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)|\"[^\\\\"
709     "\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015"
710     "\"]*)*\")[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037]*)*<"
711     "[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]"
712     "|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xf"
713     "f\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:@"
714     "[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]"
715     "|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xf"
716     "f\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:["
717     "^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:"
718     "\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015"
719     "\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n"
720     "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:"
721     "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff"
722     "\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff"
723     "\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*("
724     "?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\x"
725     "ff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-"
726     "\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xf"
727     "f])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\"
728     "040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\"
729     "([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\"
730     "n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*(?:,["
731     "\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|"
732     "\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff"
733     "\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*@[\\0"
734     "40\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\("
735     "[^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n"
736     "\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\"
737     "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\"
738     "\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]"
739     "]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()"
740     "]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\"
741     "x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015"
742     "()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015"
743     "()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^"
744     "\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\0"
745     "15()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x8"
746     "0-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?"
747     ":[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*("
748     "?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\"
749     "x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]"
750     "*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*)*:[\\040\\t]*"
751     "(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\"
752     "\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015("
753     ")]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)?(?:[^(\\040)"
754     "<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\"
755     "[\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^"
756     "\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\"
757     "\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\"
758     "n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\"
759     "\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\"
760     "\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff"
761     "\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^"
762     "\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\"
763     "\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\0"
764     "37\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^"
765     "\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n"
766     "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:"
767     "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff"
768     "\\n\\015()]*)*\\)[\\040\\t]*)*)*@[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n"
769     "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:"
770     "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff"
771     "\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\0"
772     "37\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])"
773     "|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040"
774     "\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^"
775     "\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\"
776     "015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\0"
777     "40\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\("
778     "[^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n"
779     "\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\"
780     "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\"
781     "\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]"
782     "]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()"
783     "]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\"
784     "x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015"
785     "()]*)*\\)[\\040\\t]*)*)*>)$";
786
787 void tst_QRegExp::wildcard_data()
788 {
789     QTest::addColumn<QString>("rxp");
790     QTest::addColumn<QString>("string");
791     QTest::addColumn<int>("foundIndex");
792
793     QTest::newRow( "data0" ) << QString("*.html") << QString("test.html") << 0;
794     QTest::newRow( "data1" ) << QString("*.html") << QString("test.htm") << -1;
795     QTest::newRow( "data2" ) << QString("bar*") << QString("foobarbaz") << 3;
796     QTest::newRow( "data3" ) << QString("*") << QString("Qt Rocks!") << 0;
797     QTest::newRow( "data4" ) << QString(".html") << QString("test.html") << 4;
798     QTest::newRow( "data5" ) << QString(".h") << QString("test.cpp") << -1;
799     QTest::newRow( "data6" ) << QString(".???l") << QString("test.html") << 4;
800     QTest::newRow( "data7" ) << QString("?") << QString("test.html") << 0;
801     QTest::newRow( "data8" ) << QString("?m") << QString("test.html") << 6;
802     QTest::newRow( "data9" ) << QString(".h[a-z]ml") << QString("test.html") << 4;
803     QTest::newRow( "data10" ) << QString(".h[A-Z]ml") << QString("test.html") << -1;
804     QTest::newRow( "data11" ) << QString(".h[A-Z]ml") << QString("test.hTml") << 4;
805 }
806
807 void tst_QRegExp::wildcard()
808 {
809     QFETCH( QString, rxp );
810     QFETCH( QString, string );
811     QFETCH( int, foundIndex );
812
813     QRegExp r( rxp );
814     r.setPatternSyntax(QRegExp::WildcardUnix);
815     QCOMPARE( r.indexIn( string ), foundIndex );
816 }
817
818 void tst_QRegExp::testEscapingWildcard_data(){
819     QTest::addColumn<QString>("pattern");
820     QTest::addColumn<QString>("teststring");
821     QTest::addColumn<bool>("isMatching");
822
823     QTest::newRow("[ Not escaped") << "[Qt;" <<  "[Qt;" << false;
824     QTest::newRow("[ Escaped") << "\\[Qt;" <<  "[Qt;" << true;
825
826     QTest::newRow("] Not escaped") << "]Ik;" <<  "]Ik;" << false;
827     QTest::newRow("] Escaped") << "\\]Ip;" <<  "]Ip;" << true;
828
829     QTest::newRow("? Not escaped valid") << "?Ou:" <<  ".Ou:" << true;
830     QTest::newRow("? Not escaped invalid") << "?Tr;" <<  "Tr;" << false;
831     QTest::newRow("? Escaped") << "\\?O;" <<  "?O;" << true;
832
833     QTest::newRow("[] not escaped") << "[lL]" <<  "l" << true;
834     QTest::newRow("[] escaped") << "\\[\\]" <<  "[]" << true;
835
836     QTest::newRow("case [[]") << "[[abc]" <<  "[" << true;
837     QTest::newRow("case []abc] match ]") << "[]abc]" <<  "]" << true;
838     QTest::newRow("case []abc] match a") << "[]abc]" <<  "a" << true;
839     QTest::newRow("case [abc] match a") << "[abc]" <<  "a" << true;
840     QTest::newRow("case []] don't match [") << "[]abc]" <<  "[" << false;
841     QTest::newRow("case [^]abc] match d") << "[^]abc]" <<  "d" << true;
842     QTest::newRow("case [^]abc] don't match ]") << "[^]abc]" <<  "]" << false;
843
844     QTest::newRow("* Not escaped with char") << "*Te;" <<  "12345Te;" << true;
845     QTest::newRow("* Not escaped without char") << "*Ch;" <<  "Ch;" << true;
846     QTest::newRow("* Not escaped invalid") << "*Ro;" <<  "o;" << false;
847     QTest::newRow("* Escaped") << "\\[Cks;" <<  "[Cks;" << true;
848
849     QTest::newRow("a true '\\' in input") << "\\Qt;" <<  "\\Qt;" << true;
850     QTest::newRow("two true '\\' in input") << "\\\\Qt;" <<  "\\\\Qt;" << true;
851     QTest::newRow("a '\\' at the end") << "\\\\Qt;\\" <<  "\\\\Qt;\\" << true;
852 }
853
854 void tst_QRegExp::testEscapingWildcard(){
855     QFETCH(QString, pattern);
856
857     QRegExp re(pattern);
858     re.setPatternSyntax(QRegExp::WildcardUnix);
859
860     QFETCH(QString, teststring);
861     QFETCH(bool, isMatching);
862     QCOMPARE(re.exactMatch(teststring), isMatching);
863 }
864
865 void tst_QRegExp::testInvalidWildcard_data(){
866     QTest::addColumn<QString>("pattern");
867     QTest::addColumn<bool>("isValid");
868
869     QTest::newRow("valid []") << "[abc]" << true;
870     QTest::newRow("invalid [") << "[abc" << false;
871     QTest::newRow("ending [") << "abc[" << false;
872     QTest::newRow("ending ]") << "abc]" << false;
873     QTest::newRow("ending [^") << "abc[^" << false;
874     QTest::newRow("ending [\\") << "abc[\\" << false;
875     QTest::newRow("ending []") << "abc[]" << false;
876     QTest::newRow("ending [[") << "abc[[" << false;
877 }
878
879 void tst_QRegExp::testInvalidWildcard(){
880     QFETCH(QString, pattern);
881
882     QRegExp re(pattern);
883     re.setPatternSyntax(QRegExp::Wildcard);
884
885     QFETCH(bool, isValid);
886     QCOMPARE(re.isValid(), isValid);
887 }
888
889 void tst_QRegExp::caretAnchoredOptimization()
890 {
891     QString s = "---babnana----";
892     s.replace( QRegExp("^-*|(-*)$"), "" );
893     QVERIFY(s == "babnana");
894
895     s = "---babnana----";
896     s.replace( QRegExp("^-*|(-{0,})$"), "" );
897     QVERIFY(s == "babnana");
898
899     s = "---babnana----";
900     s.replace( QRegExp("^-*|(-{1,})$"), "" );
901     QVERIFY(s == "babnana");
902
903     s = "---babnana----";
904     s.replace( QRegExp("^-*|(-+)$"), "" );
905     QVERIFY(s == "babnana");
906 }
907
908 void tst_QRegExp::isEmpty()
909 {
910     QRegExp rx1;
911     QVERIFY(rx1.isEmpty());
912
913     QRegExp rx2 = rx1;
914     QVERIFY(rx2.isEmpty());
915
916     rx2.setPattern("");
917     QVERIFY(rx2.isEmpty());
918
919     rx2.setPattern("foo");
920     QVERIFY(!rx2.isEmpty());
921
922     rx2.setPattern(")(");
923     QVERIFY(!rx2.isEmpty());
924
925     rx2.setPattern("");
926     QVERIFY(rx2.isEmpty());
927
928     rx2.setPatternSyntax(QRegExp::Wildcard);
929     rx2.setPattern("");
930     QVERIFY(rx2.isEmpty());
931 }
932
933 static QRegExp re("foo.*bar");
934
935 void tst_QRegExp::staticRegExp()
936 {
937     QVERIFY(re.exactMatch("fooHARRYbar"));
938     // the actual test is that a static regexp should not crash
939 }
940
941 void tst_QRegExp::rainersSlowRegExpCopyBug()
942 {
943     // this test should take an extreme amount of time if QRegExp is broken
944     QRegExp original(email);
945 #if defined(Q_OS_WINCE)
946     for (int i = 0; i < 100; ++i) {
947 #else
948     for (int i = 0; i < 100000; ++i) {
949 #endif
950         QRegExp copy = original;
951         (void)copy.exactMatch("~");
952         QRegExp copy2 = original;
953     }
954 }
955
956 void tst_QRegExp::nonExistingBackReferenceBug()
957 {
958     {
959         QRegExp rx("<\\5>");
960         QVERIFY(rx.isValid());
961         QCOMPARE(rx.indexIn("<>"), 0);
962         QCOMPARE(rx.capturedTexts(), QStringList("<>"));
963     }
964
965     {
966         QRegExp rx("<\\1>");
967         QVERIFY(rx.isValid());
968         QCOMPARE(rx.indexIn("<>"), 0);
969         QCOMPARE(rx.capturedTexts(), QStringList("<>"));
970     }
971
972     {
973         QRegExp rx("(?:<\\1>)\\1\\5\\4");
974         QVERIFY(rx.isValid());
975         QCOMPARE(rx.indexIn("<>"), 0);
976         QCOMPARE(rx.capturedTexts(), QStringList("<>"));
977     }
978 }
979
980 class Thread : public QThread
981 {
982 public:
983     Thread(const QRegExp &rx) : rx(rx) {}
984
985     void run();
986
987     QRegExp rx;
988 };
989
990 void Thread::run()
991 {
992     QString str = "abc";
993     for (int i = 0; i < 10; ++i)
994         str += str;
995     str += "abbbdekcz";
996     int x;
997
998 #if defined(Q_OS_WINCE)
999     for (int j = 0; j < 100; ++j) {
1000 #else
1001     for (int j = 0; j < 10000; ++j) {
1002 #endif
1003         x = rx.indexIn(str);
1004     }
1005     QCOMPARE(x, 3072);
1006 }
1007
1008 void tst_QRegExp::reentrancy()
1009 {
1010     QRegExp rx("(ab{2,}d?e?f?[g-z]?)c");
1011     Thread *threads[10];
1012
1013     for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) {
1014         threads[i] = new Thread(rx);
1015         threads[i]->start();
1016     }
1017
1018     for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i)
1019         threads[i]->wait();
1020
1021     for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i)
1022         delete threads[i];
1023 }
1024
1025 class Thread2 : public QThread
1026 {
1027 public:
1028     void run();
1029 };
1030
1031 void Thread2::run()
1032 {
1033     QRegExp rx("(ab{2,}d?e?f?[g-z]?)c");
1034     QString str = "abc";
1035     for (int i = 0; i < 10; ++i)
1036         str += str;
1037     str += "abbbdekcz";
1038     int x;
1039
1040 #if defined(Q_OS_WINCE)
1041     for (int j = 0; j < 100; ++j) {
1042 #else
1043     for (int j = 0; j < 10000; ++j) {
1044 #endif
1045         x = rx.indexIn(str);
1046     }
1047     QCOMPARE(x, 3072);
1048 }
1049
1050 // Test that multiple threads can construct equal QRegExps.
1051 // (In the current QRegExp design each engine instatance will share
1052 // the same cache key, so the threads will race for the cache entry
1053 // in the global cache.)
1054 void tst_QRegExp::threadsafeEngineCache()
1055 {
1056     Thread2 *threads[10];
1057
1058     for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i) {
1059         threads[i] = new Thread2();
1060         threads[i]->start();
1061     }
1062
1063     for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i)
1064         threads[i]->wait();
1065
1066     for (int i = 0; i < int(sizeof(threads) / sizeof(threads[0])); ++i)
1067         delete threads[i];
1068 }
1069
1070
1071 void tst_QRegExp::prepareEngineOptimization()
1072 {
1073     QRegExp rx0("(f?)(?:(o?)(o?))?");
1074
1075     QRegExp rx1(rx0);
1076
1077     QCOMPARE(rx1.capturedTexts(), QStringList() << "" << "" << "" << "");
1078     QCOMPARE(rx1.matchedLength(), -1);
1079     QCOMPARE(rx1.matchedLength(), -1);
1080     QCOMPARE(rx1.captureCount(), 3);
1081
1082     QCOMPARE(rx1.exactMatch("foo"), true);
1083     QCOMPARE(rx1.matchedLength(), 3);
1084     QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1085     QCOMPARE(rx1.captureCount(), 3);
1086     QCOMPARE(rx1.matchedLength(), 3);
1087     QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1088     QCOMPARE(rx1.pos(3), 2);
1089
1090     QCOMPARE(rx1.exactMatch("foo"), true);
1091     QCOMPARE(rx1.captureCount(), 3);
1092     QCOMPARE(rx1.matchedLength(), 3);
1093     QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1094     QCOMPARE(rx1.pos(3), 2);
1095
1096     QRegExp rx2 = rx1;
1097
1098     QCOMPARE(rx1.captureCount(), 3);
1099     QCOMPARE(rx1.matchedLength(), 3);
1100     QCOMPARE(rx1.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1101     QCOMPARE(rx1.pos(3), 2);
1102
1103     QCOMPARE(rx2.captureCount(), 3);
1104     QCOMPARE(rx2.matchedLength(), 3);
1105     QCOMPARE(rx2.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1106     QCOMPARE(rx2.pos(3), 2);
1107
1108     QCOMPARE(rx1.exactMatch("fo"), true);
1109     QCOMPARE(rx1.captureCount(), 3);
1110     QCOMPARE(rx1.matchedLength(), 2);
1111     QCOMPARE(rx1.capturedTexts(), QStringList() << "fo" << "f" << "o" << "");
1112     QCOMPARE(rx1.pos(2), 1);
1113
1114     QRegExp rx3;
1115     QVERIFY(rx3.isValid());
1116
1117     QRegExp rx4("foo", Qt::CaseInsensitive, QRegExp::RegExp);
1118     QVERIFY(rx4.isValid());
1119
1120     QRegExp rx5("foo", Qt::CaseInsensitive, QRegExp::RegExp2);
1121     QVERIFY(rx5.isValid());
1122
1123     QRegExp rx6("foo", Qt::CaseInsensitive, QRegExp::FixedString);
1124     QVERIFY(rx6.isValid());
1125
1126     QRegExp rx7("foo", Qt::CaseInsensitive, QRegExp::Wildcard);
1127     QVERIFY(rx7.isValid());
1128
1129     QRegExp rx8("][", Qt::CaseInsensitive, QRegExp::RegExp);
1130     QVERIFY(!rx8.isValid());
1131
1132     QRegExp rx9("][", Qt::CaseInsensitive, QRegExp::RegExp2);
1133     QVERIFY(!rx9.isValid());
1134
1135     QRegExp rx10("][", Qt::CaseInsensitive, QRegExp::Wildcard);
1136     QVERIFY(!rx10.isValid());
1137
1138     QRegExp rx11("][", Qt::CaseInsensitive, QRegExp::FixedString);
1139     QVERIFY(rx11.isValid());
1140     QVERIFY(rx11.exactMatch("]["));
1141     QCOMPARE(rx11.matchedLength(), 2);
1142
1143     rx11.setPatternSyntax(QRegExp::Wildcard);
1144     QVERIFY(!rx11.isValid());
1145     QCOMPARE(rx11.captureCount(), 0);
1146     QCOMPARE(rx11.matchedLength(), -1);
1147
1148     rx11.setPatternSyntax(QRegExp::RegExp);
1149     QVERIFY(!rx11.isValid());
1150     QCOMPARE(rx11.captureCount(), 0);
1151     QCOMPARE(rx11.matchedLength(), -1);
1152
1153     rx11.setPattern("(foo)");
1154     QVERIFY(rx11.isValid());
1155     QCOMPARE(rx11.captureCount(), 1);
1156     QCOMPARE(rx11.matchedLength(), -1);
1157
1158     QCOMPARE(rx11.indexIn("ofoo"), 1);
1159     QCOMPARE(rx11.captureCount(), 1);
1160     QCOMPARE(rx11.matchedLength(), 3);
1161
1162     rx11.setPatternSyntax(QRegExp::RegExp);
1163     QCOMPARE(rx11.captureCount(), 1);
1164     QCOMPARE(rx11.matchedLength(), 3);
1165
1166     /*
1167         This behavior isn't entirely consistent with setPatter(),
1168         setPatternSyntax(), and setCaseSensitivity(), but I'm testing
1169         it here to ensure that it doesn't change subtly in future
1170         releases.
1171     */
1172     rx11.setMinimal(true);
1173     QCOMPARE(rx11.matchedLength(), 3);
1174     rx11.setMinimal(false);
1175     QCOMPARE(rx11.matchedLength(), 3);
1176
1177     rx11.setPatternSyntax(QRegExp::Wildcard);
1178     QCOMPARE(rx11.captureCount(), 0);
1179     QCOMPARE(rx11.matchedLength(), -1);
1180
1181     rx11.setPatternSyntax(QRegExp::RegExp);
1182     QCOMPARE(rx11.captureCount(), 1);
1183     QCOMPARE(rx11.matchedLength(), -1);
1184 }
1185
1186 void tst_QRegExp::swap()
1187 {
1188     QRegExp r1(QLatin1String(".*")), r2(QLatin1String("a*"));
1189     r1.swap(r2);
1190     QCOMPARE(r1.pattern(),QLatin1String("a*"));
1191     QCOMPARE(r2.pattern(),QLatin1String(".*"));
1192 }
1193
1194 void tst_QRegExp::operator_eq()
1195 {
1196     const int I = 2;
1197     const int J = 4;
1198     const int K = 2;
1199     const int ELL = 2;
1200     QRegExp rxtable[I * J * K * ELL];
1201     int n;
1202
1203     n = 0;
1204     for (int i = 0; i < I; ++i) {
1205         for (int j = 0; j < J; ++j) {
1206             for (int k = 0; k < K; ++k) {
1207                 for (int ell = 0; ell < ELL; ++ell) {
1208                     Qt::CaseSensitivity cs = i == 0 ? Qt::CaseSensitive : Qt::CaseInsensitive;
1209                     QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(j);
1210                     bool minimal = k == 0;
1211
1212                     if (ell == 0) {
1213                         QRegExp rx("foo", cs, syntax);
1214                         rx.setMinimal(minimal);
1215                         rxtable[n++] = rx;
1216                     } else {
1217                         QRegExp rx;
1218                         rx.setPattern("bar");
1219                         rx.setMinimal(true);
1220                         rx.exactMatch("bar");
1221                         rx.setCaseSensitivity(cs);
1222                         rx.setMinimal(minimal);
1223                         rx.setPattern("foo");
1224                         rx.setPatternSyntax(syntax);
1225                         rx.exactMatch("foo");
1226                         rxtable[n++] = rx;
1227                     }
1228                 }
1229             }
1230         }
1231     }
1232
1233     for (int i = 0; i < I * J * K * ELL; ++i) {
1234         for (int j = 0; j < I * J * K * ELL; ++j) {
1235             QCOMPARE(rxtable[i] == rxtable[j], i / ELL == j / ELL);
1236             QCOMPARE(rxtable[i] != rxtable[j], i / ELL != j / ELL);
1237         }
1238     }
1239 }
1240
1241 // This test aims to ensure that the values returned by pos() and cap()
1242 // are consistent.
1243 void tst_QRegExp::posAndCapConsistency_data()
1244 {
1245     QTest::addColumn<QString>("reStr");
1246     QTest::addColumn<QString>("text");
1247     QTest::addColumn<int>("matchIndex");
1248
1249     QTest::addColumn<int>("pos0");
1250     QTest::addColumn<int>("pos1");
1251     QTest::addColumn<int>("pos2");
1252
1253     QTest::addColumn<QString>("cap0");
1254     QTest::addColumn<QString>("cap1");
1255     QTest::addColumn<QString>("cap2");
1256
1257     QTest::newRow("no match")
1258         << QString("(a) (b)") << QString("b a") << -1
1259         << -1 << -1 << -1 << QString() << QString() << QString();
1260
1261     QTest::newRow("both captures match")
1262         << QString("(a) (b)") << QString("a b") << 0
1263         << 0 << 0 << 2 << QString("a b") << QString("a") << QString("b");
1264
1265     QTest::newRow("first capture matches @0")
1266         << QString("(a*)|(b*)") << QString("axx") << 0
1267         << 0 << 0 << -1 << QString("a") << QString("a") << QString();
1268     QTest::newRow("second capture matches @0")
1269         << QString("(a*)|(b*)") << QString("bxx") << 0
1270         << 0 << -1 << 0 << QString("b") << QString() << QString("b");
1271     QTest::newRow("first capture empty match @0")
1272         << QString("(a*)|(b*)") << QString("xx") << 0
1273         << 0 << -1 << -1 << QString("") << QString() << QString();
1274     QTest::newRow("second capture empty match @0")
1275         << QString("(a)|(b*)") << QString("xx") << 0
1276         << 0 << -1 << -1 << QString("") << QString() << QString();
1277
1278     QTest::newRow("first capture matches @1")
1279         << QString("x(?:(a*)|(b*))") << QString("-xa") << 1
1280         << 1 << 2 << -1 << QString("xa") << QString("a") << QString();
1281     QTest::newRow("second capture matches @1")
1282         << QString("x(?:(a*)|(b*))") << QString("-xb") << 1
1283         << 1 << -1 << 2 << QString("xb") << QString() << QString("b");
1284     QTest::newRow("first capture empty match @1")
1285         << QString("x(?:(a*)|(b*))") << QString("-xx") << 1
1286         << 1 << -1 << -1 << QString("x") << QString() << QString();
1287     QTest::newRow("second capture empty match @1")
1288         << QString("x(?:(a)|(b*))") << QString("-xx") << 1
1289         << 1 << -1 << -1 << QString("x") << QString() << QString();
1290
1291     QTest::newRow("first capture matches @2")
1292         << QString("(a)|(b)") << QString("xxa") << 2
1293         << 2 << 2 << -1 << QString("a") << QString("a") << QString();
1294     QTest::newRow("second capture matches @2")
1295         << QString("(a)|(b)") << QString("xxb") << 2
1296         << 2 << -1 << 2 << QString("b") << QString() << QString("b");
1297     QTest::newRow("no match - with options")
1298         << QString("(a)|(b)") << QString("xx") << -1
1299         << -1 << -1 << -1 << QString() << QString() << QString();
1300
1301 }
1302
1303 void tst_QRegExp::posAndCapConsistency()
1304 {
1305     QFETCH( QString, reStr );
1306     QFETCH( QString, text );
1307     QFETCH( int, matchIndex );
1308     QFETCH( int, pos0 );
1309     QFETCH( int, pos1 );
1310     QFETCH( int, pos2 );
1311     QFETCH( QString, cap0 );
1312     QFETCH( QString, cap1 );
1313     QFETCH( QString, cap2 );
1314
1315     QRegExp re(reStr);
1316     QCOMPARE(re.captureCount(), 2);
1317     QCOMPARE(re.capturedTexts().size(), 3);
1318
1319     QCOMPARE(re.indexIn(text), matchIndex);
1320
1321     QCOMPARE( re.pos(0), pos0 );
1322     QCOMPARE( re.pos(1), pos1 );
1323     QCOMPARE( re.pos(2), pos2 );
1324
1325     QCOMPARE( re.cap(0).isNull(), cap0.isNull() );
1326     QCOMPARE( re.cap(0), cap0 );
1327     QCOMPARE( re.cap(1).isNull(), cap1.isNull() );
1328     QCOMPARE( re.cap(1), cap1 );
1329     QCOMPARE( re.cap(2).isNull(), cap2.isNull() );
1330     QCOMPARE( re.cap(2), cap2 );
1331 }
1332
1333 void tst_QRegExp::interval()
1334 {
1335     {
1336         QRegExp exp("a{0,1}");
1337         QVERIFY(exp.isValid());
1338     }
1339     {
1340         QRegExp exp("a{1,1}");
1341         QVERIFY(exp.isValid());
1342     }
1343     {
1344         QRegExp exp("a{1,0}");
1345         QVERIFY(!exp.isValid());
1346     }
1347 }
1348
1349 void tst_QRegExp::validityCheck_data()
1350 {
1351     QTest::addColumn<QString>("pattern");
1352     QTest::addColumn<bool>("validity");
1353     QTest::newRow("validity01") << QString() << true;
1354     QTest::newRow("validity02") << QString("abc.*abc") << true;
1355     QTest::newRow("validity03") << QString("[a-z") << false;
1356     QTest::newRow("validity04") << QString("a(b") << false;
1357 }
1358
1359 void tst_QRegExp::validityCheck()
1360 {
1361     QFETCH(QString, pattern);
1362
1363     QRegExp rx(pattern);
1364     QTEST(rx.isValid(), "validity");
1365     QCOMPARE(rx.matchedLength(), -1);
1366     QCOMPARE(rx.pos(), -1);
1367     QCOMPARE(rx.cap(), QString(""));
1368
1369     QRegExp rx2(rx);
1370     QTEST(rx2.isValid(), "validity");
1371     QCOMPARE(rx2.matchedLength(), -1);
1372     QCOMPARE(rx2.pos(), -1);
1373     QCOMPARE(rx2.cap(), QString(""));
1374 }
1375
1376
1377 QTEST_APPLESS_MAIN(tst_QRegExp)
1378 #include "tst_qregexp.moc"