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