1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
51 class tst_QRegExp
: public QObject
57 virtual ~tst_QRegExp();
66 void indexIn_addMoreRows(const QByteArray
&stri
);
68 void lastIndexIn_data();
73 void testEscapingWildcard_data();
74 void testEscapingWildcard();
75 void testInvalidWildcard_data();
76 void testInvalidWildcard();
77 void caretAnchoredOptimization();
79 void prepareEngineOptimization();
87 void setCaseSensitive();
100 void rainersSlowRegExpCopyBug();
101 void nonExistingBackReferenceBug();
104 void threadsafeEngineCache();
107 // Testing get/set functions
108 void tst_QRegExp::getSetCheck()
111 // PatternSyntax QRegExp::patternSyntax()
112 // void QRegExp::setPatternSyntax(PatternSyntax)
113 obj1
.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::RegExp
));
114 QCOMPARE(QRegExp::PatternSyntax(QRegExp::RegExp
), obj1
.patternSyntax());
115 obj1
.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::Wildcard
));
116 QCOMPARE(QRegExp::PatternSyntax(QRegExp::Wildcard
), obj1
.patternSyntax());
117 obj1
.setPatternSyntax(QRegExp::PatternSyntax(QRegExp::FixedString
));
118 QCOMPARE(QRegExp::PatternSyntax(QRegExp::FixedString
), obj1
.patternSyntax());
121 extern const char email
[];
123 tst_QRegExp::tst_QRegExp()
127 tst_QRegExp::~tst_QRegExp()
131 void tst_QRegExp::lastIndexIn_data()
136 void tst_QRegExp::indexIn_data()
138 QTest::addColumn
<QString
>("regexpStr");
139 QTest::addColumn
<QString
>("target");
140 QTest::addColumn
<int>("pos");
141 QTest::addColumn
<int>("len");
142 QTest::addColumn
<QStringList
>("caps");
144 for (int i
= 0; i
< N
; ++i
) {
150 QTest::newRow( stri
+ "anc00" ) << QString("a(?=)z") << QString("az") << 0 << 2 << QStringList();
151 QTest::newRow( stri
+ "anc01" ) << QString("a(?!)z") << QString("az") << -1 << -1 << QStringList();
152 QTest::newRow( stri
+ "anc02" ) << QString("a(?:(?=)|(?=))z") << QString("az") << 0 << 2
154 QTest::newRow( stri
+ "anc03" ) << QString("a(?:(?=)|(?!))z") << QString("az") << 0 << 2
156 QTest::newRow( stri
+ "anc04" ) << QString("a(?:(?!)|(?=))z") << QString("az") << 0 << 2
158 QTest::newRow( stri
+ "anc05" ) << QString("a(?:(?!)|(?!))z") << QString("az") << -1 << -1
160 QTest::newRow( stri
+ "anc06" ) << QString("a(?:(?=)|b)z") << QString("az") << 0 << 2
162 QTest::newRow( stri
+ "anc07" ) << QString("a(?:(?=)|b)z") << QString("abz") << 0 << 3
164 QTest::newRow( stri
+ "anc08" ) << QString("a(?:(?!)|b)z") << QString("az") << -1 << -1
166 QTest::newRow( stri
+ "anc09" ) << QString("a(?:(?!)|b)z") << QString("abz") << 0 << 3
169 QTest::newRow( stri
+ "anc10" ) << QString("a?(?=^b$)") << QString("ab") << 0 << 1
171 QTest::newRow( stri
+ "anc11" ) << QString("a?(?=^b$)") << QString("b") << 0 << 0
176 QTest::newRow( stri
+ "bref00" ) << QString("(a*)(\\1)") << QString("aaaaa") << 0 << 4
177 << QStringList( QStringList() << "aa" << "aa" );
178 QTest::newRow( stri
+ "bref01" ) << QString("<(\\w*)>.+</\\1>") << QString("<b>blabla</b>bla</>")
179 << 0 << 13 << QStringList( QStringList() << "b" );
180 QTest::newRow( stri
+ "bref02" ) << QString("<(\\w*)>.+</\\1>") << QString("<>blabla</b>bla</>")
181 << 0 << 18 << QStringList( QStringList() << "" );
182 QTest::newRow( stri
+ "bref03" ) << QString("((a*\\2)\\2)") << QString("aaaa") << 0 << 4
183 << QStringList( QStringList() << QString("aaaa") << "aa" );
184 QTest::newRow( stri
+ "bref04" ) << QString("^(aa+)\\1+$") << QString("aaaaaa") << 0 << 6
185 << QStringList( QStringList() << QString("aa") );
186 QTest::newRow( stri
+ "bref05" ) << QString("^(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)"
187 "\\14\\13\\12\\11\\10\\9\\8\\7\\6\\5\\4\\3\\2\\1")
188 << QString("12345678910111213141413121110987654321") << 0 << 38
189 << QStringList( QStringList() << "1" << "2" << "3" << "4" << "5" << "6"
190 << "7" << "8" << "9" << "10" << "11"
191 << "12" << "13" << "14");
194 QTest::newRow( stri
+ "cap00" ) << QString("(a*)") << QString("") << 0 << 0
195 << QStringList( QStringList() << QString("") );
196 QTest::newRow( stri
+ "cap01" ) << QString("(a*)") << QString("aaa") << 0 << 3
197 << QStringList( QStringList() << "aaa" );
198 QTest::newRow( stri
+ "cap02" ) << QString("(a*)") << QString("baaa") << 0 << 0
199 << QStringList( QStringList() << QString("") );
200 QTest::newRow( stri
+ "cap03" ) << QString("(a*)(a*)") << QString("aaa") << 0 << 3
201 << QStringList( QStringList() << QString("aaa") << QString("") );
202 QTest::newRow( stri
+ "cap04" ) << QString("(a*)(b*)") << QString("aaabbb") << 0 << 6
203 << QStringList( QStringList() << QString("aaa") << QString("bbb") );
204 QTest::newRow( stri
+ "cap06" ) << QString("(a*)a*") << QString("aaa") << 0 << 3
205 << QStringList( QStringList() << QString("aaa") );
206 QTest::newRow( stri
+ "cap07" ) << QString("((a*a*)*)") << QString("aaa") << 0 << 3
207 << QStringList( QStringList() << "aaa" << QString("aaa") );
208 QTest::newRow( stri
+ "cap08" ) << QString("(((a)*(b)*)*)") << QString("ababa") << 0 << 5
209 << QStringList( QStringList() << QString("ababa") << QString("a") << QString("a")
211 QTest::newRow( stri
+ "cap09" ) << QString("(((a)*(b)*)c)*") << QString("") << 0 << 0
212 << QStringList( QStringList() << QString("") << QString("") << QString("") << QString("") );
213 QTest::newRow( stri
+ "cap10" ) << QString("(((a)*(b)*)c)*") << QString("abc") << 0 << 3
214 << QStringList( QStringList() << "abc" << "ab" << "a"
216 QTest::newRow( stri
+ "cap11" ) << QString("(((a)*(b)*)c)*") << QString("abcc") << 0 << 4
217 << QStringList( QStringList() << "c" << "" << "" << "" );
218 QTest::newRow( stri
+ "cap12" ) << QString("(((a)*(b)*)c)*") << QString("abcac") << 0 << 5
219 << QStringList( QStringList() << "ac" << "a" << "a" << "" );
220 QTest::newRow( stri
+ "cap13" ) << QString("(to|top)?(o|polo)?(gical|o?logical)")
221 << QString("topological") << 0 << 11
222 << QStringList( QStringList() << "top" << "o"
224 QTest::newRow( stri
+ "cap14" ) << QString("(a)+") << QString("aaaa") << 0 << 4
225 << QStringList( QStringList() << "a" );
228 QTest::newRow( stri
+ "cat00" ) << QString("") << QString("") << 0 << 0 << QStringList();
229 QTest::newRow( stri
+ "cat01" ) << QString("") << QString("a") << 0 << 0 << QStringList();
230 QTest::newRow( stri
+ "cat02" ) << QString("a") << QString("") << -1 << -1 << QStringList();
231 QTest::newRow( stri
+ "cat03" ) << QString("a") << QString("a") << 0 << 1 << QStringList();
232 QTest::newRow( stri
+ "cat04" ) << QString("a") << QString("b") << -1 << -1 << QStringList();
233 QTest::newRow( stri
+ "cat05" ) << QString("b") << QString("a") << -1 << -1 << QStringList();
234 QTest::newRow( stri
+ "cat06" ) << QString("ab") << QString("ab") << 0 << 2 << QStringList();
235 QTest::newRow( stri
+ "cat07" ) << QString("ab") << QString("ba") << -1 << -1 << QStringList();
236 QTest::newRow( stri
+ "cat08" ) << QString("abab") << QString("abbaababab") << 4 << 4
239 indexIn_addMoreRows(stri
);
245 void tst_QRegExp::indexIn_addMoreRows(const QByteArray
&stri
)
248 // from Perl Cookbook
249 QTest::newRow( stri
+ "cook00" ) << QString("^(m*)(d?c{0,3}|c[dm])(1?x{0,3}|x[lc])(v?i{0"
251 << QString("mmxl") << 0 << 4
252 << QStringList( QStringList() << "mm" << "" << "xl"
254 QTest::newRow( stri
+ "cook01" ) << QString("(\\S+)(\\s+)(\\S+)") << QString(" a b") << 1 << 5
255 << QStringList( QStringList() << "a" << " " << "b" );
256 QTest::newRow( stri
+ "cook02" ) << QString("(\\w+)\\s*=\\s*(.*)\\s*$") << QString(" PATH=. ") << 1
257 << 7 << QStringList( QStringList() << "PATH" << ". " );
258 QTest::newRow( stri
+ "cook03" ) << QString(".{80,}")
259 << QString("0000000011111111222222223333333344444444555"
260 "5555566666666777777778888888899999999000000"
262 << 0 << 96 << QStringList();
263 QTest::newRow( stri
+ "cook04" ) << QString("(\\d+)/(\\d+)/(\\d+) (\\d+):(\\d+):(\\d+)")
264 << QString("1978/05/24 07:30:00") << 0 << 19
265 << QStringList( QStringList() << "1978" << "05" << "24"
266 << "07" << "30" << "00" );
267 QTest::newRow( stri
+ "cook05" ) << QString("/usr/bin") << QString("/usr/local/bin:/usr/bin")
268 << 15 << 8 << QStringList();
269 QTest::newRow( stri
+ "cook06" ) << QString("%([0-9A-Fa-f]{2})") << QString("http://%7f") << 7 << 3
270 << QStringList( QStringList() << "7f" );
271 QTest::newRow( stri
+ "cook07" ) << QString("/\\*.*\\*/") << QString("i++; /* increment i */") << 5
272 << 17 << QStringList();
273 QTest::newRow( stri
+ "cook08" ) << QString("^\\s+") << QString(" aaa ") << 0 << 3
275 QTest::newRow( stri
+ "cook09" ) << QString("\\s+$") << QString(" aaa ") << 6 << 3
277 QTest::newRow( stri
+ "cook10" ) << QString("^.*::") << QString("Box::cat") << 0 << 5
279 QTest::newRow( stri
+ "cook11" ) << QString("^([01]?\\d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\"
280 "d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-"
281 "4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-4]\\d|25["
283 << QString("255.00.40.30") << 0 << 12
284 << QStringList( QStringList() << "255" << "00" << "40"
286 QTest::newRow( stri
+ "cook12" ) << QString("^.*/") << QString(" /usr/local/bin/moc") << 0 << 16
288 QTest::newRow( stri
+ "cook13" ) << QString(":co#(\\d+):") << QString("bla:co#55:") << 3 << 7
289 << QStringList( QStringList() << "55" );
290 QTest::newRow( stri
+ "cook14" ) << QString("linux") << QString("alphalinuxinunix") << 5 << 5
292 QTest::newRow( stri
+ "cook15" ) << QString("(\\d+\\.?\\d*|\\.\\d+)") << QString("0.0.5") << 0 << 3
293 << QStringList( QStringList() << "0.0" );
295 // mathematical trivia
296 QTest::newRow( stri
+ "math00" ) << QString("^(a\\1*)$") << QString("a") << 0 << 1
297 << QStringList( QStringList() << "a" );
298 QTest::newRow( stri
+ "math01" ) << QString("^(a\\1*)$") << QString("aa") << 0 << 2
299 << QStringList( QStringList() << "aa" );
300 QTest::newRow( stri
+ "math02" ) << QString("^(a\\1*)$") << QString("aaa") << -1 << -1
301 << QStringList( QStringList() << QString() );
302 QTest::newRow( stri
+ "math03" ) << QString("^(a\\1*)$") << QString("aaaa") << 0 << 4
303 << QStringList( QStringList() << "aaaa" );
304 QTest::newRow( stri
+ "math04" ) << QString("^(a\\1*)$") << QString("aaaaa") << -1 << -1
305 << QStringList( QStringList() << QString() );
306 QTest::newRow( stri
+ "math05" ) << QString("^(a\\1*)$") << QString("aaaaaa") << -1 << -1
307 << QStringList( QStringList() << QString() );
308 QTest::newRow( stri
+ "math06" ) << QString("^(a\\1*)$") << QString("aaaaaaa") << -1 << -1
309 << QStringList( QStringList() << QString() );
310 QTest::newRow( stri
+ "math07" ) << QString("^(a\\1*)$") << QString("aaaaaaaa") << 0 << 8
311 << QStringList( QStringList() << "aaaaaaaa" );
312 QTest::newRow( stri
+ "math08" ) << QString("^(a\\1*)$") << QString("aaaaaaaaa") << -1 << -1
313 << QStringList( QStringList() << QString() );
314 QTest::newRow( stri
+ "math09" ) << QString("^a(?:a(\\1a))*$") << QString("a") << 0 << 1
315 << QStringList( QStringList() << "" );
316 QTest::newRow( stri
+ "math10" ) << QString("^a(?:a(\\1a))*$") << QString("aaa") << 0 << 3
317 << QStringList( QStringList() << "a" );
319 QTest::newRow( stri
+ "math13" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|("
321 << QString("aaa") << 0 << 3
322 << QStringList( QStringList() << "a" << "a" << "" );
323 QTest::newRow( stri
+ "math14" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|("
325 << QString("aaaaa") << 0 << 5
326 << QStringList( QStringList() << "a" << "a" << "aa" );
327 QTest::newRow( stri
+ "math17" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
328 ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
329 << QString("aaa") << 0 << 3
330 << QStringList( QStringList() << "" << "" << "" << "aaa"
332 QTest::newRow( stri
+ "math18" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
333 ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
334 << QString("aaaaa") << 0 << 5
335 << QStringList( QStringList() << "aaaaa" << "a" << "aaa"
337 QTest::newRow( stri
+ "math19" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
338 ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
339 << QString("aaaaaaaa") << 0 << 8
340 << QStringList( QStringList() << "" << "" << ""
343 QTest::newRow( stri
+ "math20" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?"
344 ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$")
345 << QString("aaaaaaaaa") << -1 << -1
346 << QStringList( QStringList() << QString()
352 QTest::newRow( stri
+ "math21" ) << QString("^(aa+)\\1+$") << QString("aaaaaaaaaaaa") << 0 << 12
353 << QStringList( QStringList() << "aa" );
355 static const char * const squareRegExp
[] = {
359 "^(?:(\\B\\1aa|^a))+$",
361 "^((\\2a)*)\\1\\2a$",
367 while ( squareRegExp
[ii
] != 0 ) {
368 for ( int j
= 0; j
< 100; j
++ ) {
370 name
.sprintf( "square%.1d%.2d", ii
, j
);
373 target
.fill( 'a', j
);
378 for ( int k
= 1; k
* k
<= j
; k
++ ) {
386 QTest::newRow( name
.toLatin1() ) << QString( squareRegExp
[ii
] ) << target
387 << pos
<< len
<< QStringList( "IGNORE ME" );
393 QTest::newRow( stri
+ "misc00" ) << QString(email
)
394 << QString("troll1@trolltech.com") << 0 << 20
396 QTest::newRow( stri
+ "misc01" ) << QString("[0-9]*\\.[0-9]+") << QString("pi = 3.14") << 5 << 4
400 QTest::newRow( stri
+ "or00" ) << QString("(?:|b)") << QString("xxx") << 0 << 0 << QStringList();
401 QTest::newRow( stri
+ "or01" ) << QString("(?:|b)") << QString("b") << 0 << 1 << QStringList();
402 QTest::newRow( stri
+ "or02" ) << QString("(?:b|)") << QString("") << 0 << 0 << QStringList();
403 QTest::newRow( stri
+ "or03" ) << QString("(?:b|)") << QString("b") << 0 << 1 << QStringList();
404 QTest::newRow( stri
+ "or04" ) << QString("(?:||b||)") << QString("") << 0 << 0 << QStringList();
405 QTest::newRow( stri
+ "or05" ) << QString("(?:||b||)") << QString("b") << 0 << 1 << QStringList();
406 QTest::newRow( stri
+ "or06" ) << QString("(?:a|b)") << QString("") << -1 << -1 << QStringList();
407 QTest::newRow( stri
+ "or07" ) << QString("(?:a|b)") << QString("cc") << -1 << -1 << QStringList();
408 QTest::newRow( stri
+ "or08" ) << QString("(?:a|b)") << QString("abc") << 0 << 1 << QStringList();
409 QTest::newRow( stri
+ "or09" ) << QString("(?:a|b)") << QString("cba") << 1 << 1 << QStringList();
410 QTest::newRow( stri
+ "or10" ) << QString("(?:ab|ba)") << QString("aba") << 0 << 2
412 QTest::newRow( stri
+ "or11" ) << QString("(?:ab|ba)") << QString("bab") << 0 << 2
414 QTest::newRow( stri
+ "or12" ) << QString("(?:ab|ba)") << QString("caba") << 1 << 2
416 QTest::newRow( stri
+ "or13" ) << QString("(?:ab|ba)") << QString("cbab") << 1 << 2
420 QTest::newRow( stri
+ "qua00" ) << QString("((([a-j])){0,0})") << QString("") << 0 << 0
421 << QStringList( QStringList() << "" << "" << "" );
422 QTest::newRow( stri
+ "qua01" ) << QString("((([a-j])){0,0})") << QString("a") << 0 << 0
423 << QStringList( QStringList() << "" << "" << "" );
424 QTest::newRow( stri
+ "qua02" ) << QString("((([a-j])){0,0})") << QString("xyz") << 0 << 0
425 << QStringList( QStringList() << "" << "" << "" );
426 QTest::newRow( stri
+ "qua03" ) << QString("((([a-j]))?)") << QString("") << 0 << 0
427 << QStringList( QStringList() << "" << "" << "" );
428 QTest::newRow( stri
+ "qua04" ) << QString("((([a-j]))?)") << QString("a") << 0 << 1
429 << QStringList( QStringList() << "a" << "a" << "a" );
430 QTest::newRow( stri
+ "qua05" ) << QString("((([a-j]))?)") << QString("x") << 0 << 0
431 << QStringList( QStringList() << "" << "" << "" );
432 QTest::newRow( stri
+ "qua06" ) << QString("((([a-j]))?)") << QString("ab") << 0 << 1
433 << QStringList( QStringList() << "a" << "a" << "a" );
434 QTest::newRow( stri
+ "qua07" ) << QString("((([a-j]))?)") << QString("xa") << 0 << 0
435 << QStringList( QStringList() << "" << "" << "" );
436 QTest::newRow( stri
+ "qua08" ) << QString("((([a-j])){0,3})") << QString("") << 0 << 0
437 << QStringList( QStringList() << "" << "" << "" );
438 QTest::newRow( stri
+ "qua09" ) << QString("((([a-j])){0,3})") << QString("a") << 0 << 1
439 << QStringList( QStringList() << "a" << "a" << "a" );
440 QTest::newRow( stri
+ "qua10" ) << QString("((([a-j])){0,3})") << QString("abcd") << 0 << 3
441 << QStringList( QStringList() << "abc" << "c" << "c" );
442 QTest::newRow( stri
+ "qua11" ) << QString("((([a-j])){0,3})") << QString("abcde") << 0 << 3
443 << QStringList( QStringList() << "abc" << "c" << "c" );
444 QTest::newRow( stri
+ "qua12" ) << QString("((([a-j])){2,4})") << QString("a") << -1 << -1
445 << QStringList( QStringList() << QString()
448 QTest::newRow( stri
+ "qua13" ) << QString("((([a-j])){2,4})") << QString("ab") << 0 << 2
449 << QStringList( QStringList() << "ab" << "b" << "b" );
450 QTest::newRow( stri
+ "qua14" ) << QString("((([a-j])){2,4})") << QString("abcd") << 0 << 4
451 << QStringList( QStringList() << "abcd" << "d" << "d" );
452 QTest::newRow( stri
+ "qua15" ) << QString("((([a-j])){2,4})") << QString("abcdef") << 0 << 4
453 << QStringList( QStringList() << "abcd" << "d" << "d" );
454 QTest::newRow( stri
+ "qua16" ) << QString("((([a-j])){2,4})") << QString("xaybcd") << 3 << 3
455 << QStringList( QStringList() << "bcd" << "d" << "d" );
456 QTest::newRow( stri
+ "qua17" ) << QString("((([a-j])){0,})") << QString("abcdefgh") << 0 << 8
457 << QStringList( QStringList() << "abcdefgh" << "h" << "h" );
458 QTest::newRow( stri
+ "qua18" ) << QString("((([a-j])){,0})") << QString("abcdefgh") << 0 << 0
459 << QStringList( QStringList() << "" << "" << "" );
460 QTest::newRow( stri
+ "qua19" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("123332333") << 0
462 << QStringList( QStringList() << "123332333" << "2333"
464 QTest::newRow( stri
+ "qua20" ) << QString("(1(2(3){3,4}){2,3}){1,2}")
465 << QString("12333323333233331233332333323333") << 0 << 32
466 << QStringList( QStringList() << "1233332333323333"
468 QTest::newRow( stri
+ "qua21" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("") << -1 << -1
469 << QStringList( QStringList() << QString()
472 QTest::newRow( stri
+ "qua22" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333") << -1
474 << QStringList( QStringList() << QString()
477 QTest::newRow( stri
+ "qua23" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333233") << -1
479 << QStringList( QStringList() << QString()
482 QTest::newRow( stri
+ "qua24" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("122333") << -1
484 << QStringList( QStringList() << QString()
489 QTest::newRow( stri
+ "star00" ) << QString("(?:)*") << QString("") << 0 << 0 << QStringList();
490 QTest::newRow( stri
+ "star01" ) << QString("(?:)*") << QString("abc") << 0 << 0 << QStringList();
491 QTest::newRow( stri
+ "star02" ) << QString("(?:a)*") << QString("") << 0 << 0 << QStringList();
492 QTest::newRow( stri
+ "star03" ) << QString("(?:a)*") << QString("a") << 0 << 1 << QStringList();
493 QTest::newRow( stri
+ "star04" ) << QString("(?:a)*") << QString("aaa") << 0 << 3 << QStringList();
494 QTest::newRow( stri
+ "star05" ) << QString("(?:a)*") << QString("bbbbaaa") << 0 << 0
496 QTest::newRow( stri
+ "star06" ) << QString("(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 0
498 QTest::newRow( stri
+ "star07" ) << QString("(?:b)*(?:a)*") << QString("") << 0 << 0
500 QTest::newRow( stri
+ "star08" ) << QString("(?:b)*(?:a)*") << QString("a") << 0 << 1
502 QTest::newRow( stri
+ "star09" ) << QString("(?:b)*(?:a)*") << QString("aaa") << 0 << 3
504 QTest::newRow( stri
+ "star10" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaa") << 0 << 7
506 QTest::newRow( stri
+ "star11" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 7
508 QTest::newRow( stri
+ "star12" ) << QString("(?:a|b)*") << QString("c") << 0 << 0 << QStringList();
509 QTest::newRow( stri
+ "star13" ) << QString("(?:a|b)*") << QString("abac") << 0 << 3
511 QTest::newRow( stri
+ "star14" ) << QString("(?:a|b|)*") << QString("c") << 0 << 0
513 QTest::newRow( stri
+ "star15" ) << QString("(?:a|b|)*") << QString("abac") << 0 << 3
515 QTest::newRow( stri
+ "star16" ) << QString("(?:ab|ba|b)*") << QString("abbbababbbaaab") << 0 << 11
520 void tst_QRegExp::init()
524 void tst_QRegExp::cleanup()
529 void tst_QRegExp::isEmpty()
533 void tst_QRegExp::isValid()
537 void tst_QRegExp::pattern()
541 void tst_QRegExp::setPattern()
545 void tst_QRegExp::caseSensitive()
549 void tst_QRegExp::setCaseSensitive()
553 void tst_QRegExp::minimal()
557 void tst_QRegExp::setMinimal()
562 void tst_QRegExp::exactMatch()
564 QRegExp
rx_d( "\\d" );
565 QRegExp
rx_s( "\\s" );
566 QRegExp
rx_w( "\\w" );
567 QRegExp
rx_D( "\\D" );
568 QRegExp
rx_S( "\\S" );
569 QRegExp
rx_W( "\\W" );
571 for ( int i
= 0; i
< 65536; i
++ ) {
573 bool is_d
= ( ch
.category() == QChar::Number_DecimalDigit
);
574 bool is_s
= ch
.isSpace();
575 bool is_w
= ( ch
.isLetterOrNumber()
579 QVERIFY( rx_d
.exactMatch(QString(ch
)) == is_d
);
580 QVERIFY( rx_s
.exactMatch(QString(ch
)) == is_s
);
581 QVERIFY( rx_w
.exactMatch(QString(ch
)) == is_w
);
582 QVERIFY( rx_D
.exactMatch(QString(ch
)) != is_d
);
583 QVERIFY( rx_S
.exactMatch(QString(ch
)) != is_s
);
584 QVERIFY( rx_W
.exactMatch(QString(ch
)) != is_w
);
588 void tst_QRegExp::capturedTexts()
590 QRegExp
rx1("a*(a*)", Qt::CaseSensitive
, QRegExp::RegExp
);
591 rx1
.exactMatch("aaa");
592 QCOMPARE(rx1
.matchedLength(), 3);
593 QCOMPARE(rx1
.cap(0), QString("aaa"));
594 QCOMPARE(rx1
.cap(1), QString("aaa"));
596 QRegExp
rx2("a*(a*)", Qt::CaseSensitive
, QRegExp::RegExp2
);
597 rx2
.exactMatch("aaa");
598 QCOMPARE(rx2
.matchedLength(), 3);
599 QCOMPARE(rx2
.cap(0), QString("aaa"));
600 QCOMPARE(rx2
.cap(1), QString(""));
602 QRegExp
rx3("(?:a|aa)(a*)", Qt::CaseSensitive
, QRegExp::RegExp
);
603 rx3
.exactMatch("aaa");
604 QCOMPARE(rx3
.matchedLength(), 3);
605 QCOMPARE(rx3
.cap(0), QString("aaa"));
606 QCOMPARE(rx3
.cap(1), QString("aa"));
608 QRegExp
rx4("(?:a|aa)(a*)", Qt::CaseSensitive
, QRegExp::RegExp2
);
609 rx4
.exactMatch("aaa");
610 QCOMPARE(rx4
.matchedLength(), 3);
611 QCOMPARE(rx4
.cap(0), QString("aaa"));
612 QCOMPARE(rx4
.cap(1), QString("a"));
614 QRegExp
rx5("(a)*(a*)", Qt::CaseSensitive
, QRegExp::RegExp
);
615 rx5
.exactMatch("aaa");
616 QCOMPARE(rx5
.matchedLength(), 3);
617 QCOMPARE(rx5
.cap(0), QString("aaa"));
618 QCOMPARE(rx5
.cap(1), QString("a"));
619 QCOMPARE(rx5
.cap(2), QString("aa"));
621 QRegExp
rx6("(a)*(a*)", Qt::CaseSensitive
, QRegExp::RegExp2
);
622 rx6
.exactMatch("aaa");
623 QCOMPARE(rx6
.matchedLength(), 3);
624 QCOMPARE(rx6
.cap(0), QString("aaa"));
625 QCOMPARE(rx6
.cap(1), QString("a"));
626 QCOMPARE(rx6
.cap(2), QString(""));
628 QRegExp
rx7("([A-Za-z_])([A-Za-z_0-9]*)");
629 rx7
.setCaseSensitivity(Qt::CaseSensitive
);
630 rx7
.setPatternSyntax(QRegExp::RegExp
);
631 QCOMPARE(rx7
.numCaptures(), 2);
633 int pos
= rx7
.indexIn("(10 + delta4) * 32");
635 QCOMPARE(rx7
.matchedLength(), 6);
636 QCOMPARE(rx7
.cap(0), QString("delta4"));
637 QCOMPARE(rx7
.cap(1), QString("d"));
638 QCOMPARE(rx7
.cap(2), QString("elta4"));
642 void tst_QRegExp::cap()
646 void tst_QRegExp::pos()
650 void tst_QRegExp::errorString()
654 void tst_QRegExp::escape()
659 void tst_QRegExp::indexIn()
661 QFETCH( QString
, regexpStr
);
662 QFETCH( QString
, target
);
665 QFETCH( QStringList
, caps
);
667 caps
.prepend( "dummy cap(0)" );
670 QRegExp
rx( regexpStr
);
671 QVERIFY( rx
.isValid() );
673 int mypos
= rx
.indexIn( target
);
674 int mylen
= rx
.matchedLength();
675 QStringList mycaps
= rx
.capturedTexts();
677 QCOMPARE( mypos
, pos
);
678 QCOMPARE( mylen
, len
);
679 if ( caps
.size() > 1 && caps
[1] != "IGNORE ME" ) {
680 QCOMPARE( mycaps
.count(), caps
.count() );
681 for ( int i
= 1; i
< (int) mycaps
.count(); i
++ )
682 QCOMPARE( mycaps
[i
], caps
[i
] );
686 // same as above, but with RegExp2
688 QRegExp
rx( regexpStr
, Qt::CaseSensitive
, QRegExp::RegExp2
);
689 QVERIFY( rx
.isValid() );
691 int mypos
= rx
.indexIn( target
);
692 int mylen
= rx
.matchedLength();
693 QStringList mycaps
= rx
.capturedTexts();
695 QCOMPARE( mypos
, pos
);
696 QCOMPARE( mylen
, len
);
697 if ( caps
.size() > 1 && caps
[1] != "IGNORE ME" ) {
698 QCOMPARE( mycaps
.count(), caps
.count() );
699 for ( int i
= 1; i
< (int) mycaps
.count(); i
++ )
700 QCOMPARE( mycaps
[i
], caps
[i
] );
705 void tst_QRegExp::lastIndexIn()
707 QFETCH( QString
, regexpStr
);
708 QFETCH( QString
, target
);
711 QFETCH( QStringList
, caps
);
713 caps
.prepend( "dummy" );
716 The test data was really designed for indexIn(), not
717 lastIndexIn(), but it turns out that we can reuse much of that
722 QRegExp
rx( regexpStr
);
723 QVERIFY( rx
.isValid() );
725 int mypos
= rx
.lastIndexIn( target
, target
.length() );
726 int mylen
= rx
.matchedLength();
727 QStringList mycaps
= rx
.capturedTexts();
729 if ( mypos
<= pos
|| pos
== -1 ) {
730 QCOMPARE( mypos
, pos
);
731 QCOMPARE( mylen
, len
);
733 if (caps
.size() > 1 && caps
[1] != "IGNORE ME") {
734 QCOMPARE( mycaps
.count(), caps
.count() );
735 for ( int i
= 1; i
< (int) mycaps
.count(); i
++ )
736 QCOMPARE( mycaps
[i
], caps
[i
] );
742 QRegExp
rx( regexpStr
, Qt::CaseSensitive
, QRegExp::RegExp2
);
743 QVERIFY( rx
.isValid() );
745 int mypos
= rx
.lastIndexIn( target
, target
.length() );
746 int mylen
= rx
.matchedLength();
747 QStringList mycaps
= rx
.capturedTexts();
749 if ( mypos
<= pos
|| pos
== -1 ) {
750 QCOMPARE( mypos
, pos
);
751 QCOMPARE( mylen
, len
);
753 if (caps
.size() > 1 && caps
[1] != "IGNORE ME") {
754 QCOMPARE( mycaps
.count(), caps
.count() );
755 for ( int i
= 1; i
< (int) mycaps
.count(); i
++ )
756 QCOMPARE( mycaps
[i
], caps
[i
] );
762 void tst_QRegExp::matchedLength()
765 r1
.exactMatch( "aaaba" );
766 QCOMPARE( r1
.matchedLength(), 3 );
770 "^[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff"
771 "]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\x"
772 "ff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:"
773 "(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@"
774 ",;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\""
775 "]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?"
776 ":\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x"
777 "80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*"
778 ")*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*"
779 "(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\"
780 "\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015("
781 ")]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>"
782 "@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\["
783 "\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\"
784 "x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\\\x"
785 "80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\"
786 "015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\"
787 "\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*@[\\040\\t]*(?:\\([^\\\\\\x"
788 "80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\"
789 "015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\"
790 "\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\["
791 "\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037"
792 "\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff"
793 "])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80"
794 "-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x"
795 "80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]"
796 "*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x"
797 "80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\"
798 "\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040"
799 "\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\"
800 "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xf"
801 "f\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-"
802 "\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015"
803 "()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x8"
804 "0-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*|(?:[^(\\040)<>@,;:\".\\\\\\[\\"
805 "]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x"
806 "80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^\\\\"
807 "\\x80-\\xff\\n\\015\"]*)*\")[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\"
808 "010\\012-\\037]*(?:(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x8"
809 "0-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\"
810 "x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)|\"[^\\\\"
811 "\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015"
812 "\"]*)*\")[^()<>@,;:\".\\\\\\[\\]\\x80-\\xff\\000-\\010\\012-\\037]*)*<"
813 "[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]"
814 "|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xf"
815 "f\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:@"
816 "[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]"
817 "|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xf"
818 "f\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:["
819 "^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:"
820 "\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015"
821 "\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n"
822 "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:"
823 "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff"
824 "\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff"
825 "\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*("
826 "?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\x"
827 "ff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-"
828 "\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xf"
829 "f])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\"
830 "040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\"
831 "([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\"
832 "n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*(?:,["
833 "\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|"
834 "\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff"
835 "\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*@[\\0"
836 "40\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\("
837 "[^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n"
838 "\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\"
839 "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\"
840 "\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]"
841 "]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()"
842 "]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\"
843 "x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015"
844 "()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015"
845 "()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^"
846 "\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\0"
847 "15()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x8"
848 "0-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?"
849 ":[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*("
850 "?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\"
851 "x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]"
852 "*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)*)*:[\\040\\t]*"
853 "(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\"
854 "\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015("
855 ")]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*)?(?:[^(\\040)"
856 "<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\"
857 "[\\]\\000-\\037\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^"
858 "\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\"
859 "\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\"
860 "n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\"
861 "\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\040\\t]*(?:\\([^\\"
862 "\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff"
863 "\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^"
864 "\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\"
865 "\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\0"
866 "37\\x80-\\xff])|\"[^\\\\\\x80-\\xff\\n\\015\"]*(?:\\\\[^\\x80-\\xff][^"
867 "\\\\\\x80-\\xff\\n\\015\"]*)*\")[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n"
868 "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:"
869 "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff"
870 "\\n\\015()]*)*\\)[\\040\\t]*)*)*@[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n"
871 "\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:"
872 "\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff"
873 "\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\0"
874 "37\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff])"
875 "|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]]|\\\\[^\\x80-\\xff])*\\])[\\040"
876 "\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\([^"
877 "\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n\\"
878 "015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:\\.[\\0"
879 "40\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()]*(?:(?:\\\\[^\\x80-\\xff]|\\("
880 "[^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\x80-\\xff][^\\\\\\x80-\\xff\\n"
881 "\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015()]*)*\\)[\\040\\t]*)*(?:[^(\\"
882 "040)<>@,;:\".\\\\\\[\\]\\000-\\037\\x80-\\xff]+(?![^(\\040)<>@,;:\".\\"
883 "\\\\[\\]\\000-\\037\\x80-\\xff])|\\[(?:[^\\\\\\x80-\\xff\\n\\015\\[\\]"
884 "]|\\\\[^\\x80-\\xff])*\\])[\\040\\t]*(?:\\([^\\\\\\x80-\\xff\\n\\015()"
885 "]*(?:(?:\\\\[^\\x80-\\xff]|\\([^\\\\\\x80-\\xff\\n\\015()]*(?:\\\\[^\\"
886 "x80-\\xff][^\\\\\\x80-\\xff\\n\\015()]*)*\\))[^\\\\\\x80-\\xff\\n\\015"
887 "()]*)*\\)[\\040\\t]*)*)*>)$";
889 void tst_QRegExp::wildcard_data()
891 QTest::addColumn
<QString
>("rxp");
892 QTest::addColumn
<QString
>("string");
893 QTest::addColumn
<int>("foundIndex");
895 QTest::newRow( "data0" ) << QString("*.html") << QString("test.html") << 0;
896 QTest::newRow( "data1" ) << QString("*.html") << QString("test.htm") << -1;
897 QTest::newRow( "data2" ) << QString("bar*") << QString("foobarbaz") << 3;
898 QTest::newRow( "data3" ) << QString("*") << QString("Trolltech") << 0;
899 QTest::newRow( "data4" ) << QString(".html") << QString("test.html") << 4;
900 QTest::newRow( "data5" ) << QString(".h") << QString("test.cpp") << -1;
901 QTest::newRow( "data6" ) << QString(".???l") << QString("test.html") << 4;
902 QTest::newRow( "data7" ) << QString("?") << QString("test.html") << 0;
903 QTest::newRow( "data8" ) << QString("?m") << QString("test.html") << 6;
904 QTest::newRow( "data9" ) << QString(".h[a-z]ml") << QString("test.html") << 4;
905 QTest::newRow( "data10" ) << QString(".h[A-Z]ml") << QString("test.html") << -1;
906 QTest::newRow( "data11" ) << QString(".h[A-Z]ml") << QString("test.hTml") << 4;
909 void tst_QRegExp::wildcard()
911 QFETCH( QString
, rxp
);
912 QFETCH( QString
, string
);
913 QFETCH( int, foundIndex
);
916 r
.setPatternSyntax(QRegExp::WildcardUnix
);
917 QCOMPARE( r
.indexIn( string
), foundIndex
);
920 void tst_QRegExp::testEscapingWildcard_data(){
921 QTest::addColumn
<QString
>("pattern");
922 QTest::addColumn
<QString
>("teststring");
923 QTest::addColumn
<bool>("isMatching");
925 QTest::newRow("[ Not escaped") << "[Qt;" << "[Qt;" << false;
926 QTest::newRow("[ Escaped") << "\\[Qt;" << "[Qt;" << true;
928 QTest::newRow("] Not escaped") << "]Ik;" << "]Ik;" << false;
929 QTest::newRow("] Escaped") << "\\]Ip;" << "]Ip;" << true;
931 QTest::newRow("? Not escaped valid") << "?Ou:" << ".Ou:" << true;
932 QTest::newRow("? Not escaped invalid") << "?Tr;" << "Tr;" << false;
933 QTest::newRow("? Escaped") << "\\?O;" << "?O;" << true;
935 QTest::newRow("[] not escaped") << "[lL]" << "l" << true;
936 QTest::newRow("case [[]") << "[[abc]" << "[" << true;
937 QTest::newRow("case []abc] match ]") << "[]abc]" << "]" << true;
938 QTest::newRow("case []abc] match a") << "[]abc]" << "a" << true;
939 QTest::newRow("case [abc] match a") << "[abc]" << "a" << true;
940 QTest::newRow("case []] don't match [") << "[]abc]" << "[" << false;
941 QTest::newRow("case [^]abc] match d") << "[^]abc]" << "d" << true;
942 QTest::newRow("case [^]abc] don't match ]") << "[^]abc]" << "]" << false;
944 QTest::newRow("* Not escaped with char") << "*Te;" << "12345Te;" << true;
945 QTest::newRow("* Not escaped without char") << "*Ch;" << "Ch;" << true;
946 QTest::newRow("* Not escaped invalid") << "*Ro;" << "o;" << false;
947 QTest::newRow("* Escaped") << "\\[Cks;" << "[Cks;" << true;
949 QTest::newRow("a true '\\' in input") << "\\Qt;" << "\\Qt;" << true;
950 QTest::newRow("two true '\\' in input") << "\\\\Qt;" << "\\\\Qt;" << true;
951 QTest::newRow("a '\\' at the end") << "\\\\Qt;" << "\\\\Qt;" << true;
954 void tst_QRegExp::testEscapingWildcard(){
955 QFETCH(QString
, pattern
);
958 re
.setPatternSyntax(QRegExp::WildcardUnix
);
960 QFETCH(QString
, teststring
);
961 QFETCH(bool, isMatching
);
962 QCOMPARE(re
.exactMatch(teststring
), isMatching
);
965 void tst_QRegExp::testInvalidWildcard_data(){
966 QTest::addColumn
<QString
>("pattern");
967 QTest::addColumn
<bool>("isValid");
969 QTest::newRow("valid []") << "[abc]" << true;
970 QTest::newRow("invalid [") << "[abc" << false;
971 QTest::newRow("ending [") << "abc[" << false;
972 QTest::newRow("ending ]") << "abc]" << false;
973 QTest::newRow("ending [^") << "abc[^" << false;
974 QTest::newRow("ending [\\") << "abc[\\" << false;
975 QTest::newRow("ending []") << "abc[]" << false;
976 QTest::newRow("ending [[") << "abc[[" << false;
979 void tst_QRegExp::testInvalidWildcard(){
980 QFETCH(QString
, pattern
);
983 re
.setPatternSyntax(QRegExp::Wildcard
);
985 QFETCH(bool, isValid
);
986 QCOMPARE(re
.isValid(), isValid
);
989 void tst_QRegExp::caretAnchoredOptimization()
991 QString s
= "---babnana----";
992 s
.replace( QRegExp("^-*|(-*)$"), "" );
993 QVERIFY(s
== "babnana");
995 s
= "---babnana----";
996 s
.replace( QRegExp("^-*|(-{0,})$"), "" );
997 QVERIFY(s
== "babnana");
999 s
= "---babnana----";
1000 s
.replace( QRegExp("^-*|(-{1,})$"), "" );
1001 QVERIFY(s
== "babnana");
1003 s
= "---babnana----";
1004 s
.replace( QRegExp("^-*|(-+)$"), "" );
1005 QVERIFY(s
== "babnana");
1008 void tst_QRegExp::isEmpty()
1011 QVERIFY(rx1
.isEmpty());
1014 QVERIFY(rx2
.isEmpty());
1017 QVERIFY(rx2
.isEmpty());
1019 rx2
.setPattern("foo");
1020 QVERIFY(!rx2
.isEmpty());
1022 rx2
.setPattern(")(");
1023 QVERIFY(!rx2
.isEmpty());
1026 QVERIFY(rx2
.isEmpty());
1028 rx2
.setPatternSyntax(QRegExp::Wildcard
);
1030 QVERIFY(rx2
.isEmpty());
1033 static QRegExp
re("foo.*bar");
1035 void tst_QRegExp::staticRegExp()
1037 QVERIFY(re
.exactMatch("fooHARRYbar"));
1038 // the actual test is that a static regexp should not crash
1041 void tst_QRegExp::rainersSlowRegExpCopyBug()
1043 // this test should take an extreme amount of time if QRegExp is broken
1044 QRegExp
original(email
);
1045 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
1046 for (int i
= 0; i
< 100; ++i
) {
1048 for (int i
= 0; i
< 100000; ++i
) {
1050 QRegExp copy
= original
;
1051 (void)copy
.exactMatch("~");
1052 QRegExp copy2
= original
;
1056 void tst_QRegExp::nonExistingBackReferenceBug()
1059 QRegExp
rx("<\\5>");
1060 QVERIFY(rx
.isValid());
1061 QCOMPARE(rx
.indexIn("<>"), 0);
1062 QCOMPARE(rx
.capturedTexts(), QStringList("<>"));
1066 QRegExp
rx("<\\1>");
1067 QVERIFY(rx
.isValid());
1068 QCOMPARE(rx
.indexIn("<>"), 0);
1069 QCOMPARE(rx
.capturedTexts(), QStringList("<>"));
1073 QRegExp
rx("(?:<\\1>)\\1\\5\\4");
1074 QVERIFY(rx
.isValid());
1075 QCOMPARE(rx
.indexIn("<>"), 0);
1076 QCOMPARE(rx
.capturedTexts(), QStringList("<>"));
1080 class Thread
: public QThread
1083 Thread(const QRegExp
&rx
) : rx(rx
) {}
1092 QString str
= "abc";
1093 for (int i
= 0; i
< 10; ++i
)
1098 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
1099 for (int j
= 0; j
< 100; ++j
) {
1101 for (int j
= 0; j
< 10000; ++j
) {
1103 x
= rx
.indexIn(str
);
1108 void tst_QRegExp::reentrancy()
1110 QRegExp
rx("(ab{2,}d?e?f?[g-z]?)c");
1111 Thread
*threads
[10];
1113 for (int i
= 0; i
< int(sizeof(threads
) / sizeof(threads
[0])); ++i
) {
1114 threads
[i
] = new Thread(rx
);
1115 threads
[i
]->start();
1118 for (int i
= 0; i
< int(sizeof(threads
) / sizeof(threads
[0])); ++i
)
1121 for (int i
= 0; i
< int(sizeof(threads
) / sizeof(threads
[0])); ++i
)
1125 class Thread2
: public QThread
1133 QRegExp
rx("(ab{2,}d?e?f?[g-z]?)c");
1134 QString str
= "abc";
1135 for (int i
= 0; i
< 10; ++i
)
1140 #if defined(Q_OS_WINCE)
1141 for (int j
= 0; j
< 100; ++j
) {
1143 for (int j
= 0; j
< 10000; ++j
) {
1145 x
= rx
.indexIn(str
);
1150 // Test that multiple threads can construct equal QRegExps.
1151 // (In the current QRegExp design each engine instatance will share
1152 // the same cache key, so the threads will race for the cache entry
1153 // in the global cache.)
1154 void tst_QRegExp::threadsafeEngineCache()
1156 Thread2
*threads
[10];
1158 for (int i
= 0; i
< int(sizeof(threads
) / sizeof(threads
[0])); ++i
) {
1159 threads
[i
] = new Thread2();
1160 threads
[i
]->start();
1163 for (int i
= 0; i
< int(sizeof(threads
) / sizeof(threads
[0])); ++i
)
1166 for (int i
= 0; i
< int(sizeof(threads
) / sizeof(threads
[0])); ++i
)
1171 void tst_QRegExp::prepareEngineOptimization()
1173 QRegExp
rx0("(f?)(?:(o?)(o?))?");
1177 QCOMPARE(rx1
.capturedTexts(), QStringList() << "" << "" << "" << "");
1178 QCOMPARE(rx1
.matchedLength(), -1);
1179 QCOMPARE(rx1
.matchedLength(), -1);
1180 QCOMPARE(rx1
.numCaptures(), 3);
1182 QCOMPARE(rx1
.exactMatch("foo"), true);
1183 QCOMPARE(rx1
.matchedLength(), 3);
1184 QCOMPARE(rx1
.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1185 QCOMPARE(rx1
.numCaptures(), 3);
1186 QCOMPARE(rx1
.matchedLength(), 3);
1187 QCOMPARE(rx1
.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1188 QCOMPARE(rx1
.pos(3), 2);
1190 QCOMPARE(rx1
.exactMatch("foo"), true);
1191 QCOMPARE(rx1
.numCaptures(), 3);
1192 QCOMPARE(rx1
.matchedLength(), 3);
1193 QCOMPARE(rx1
.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1194 QCOMPARE(rx1
.pos(3), 2);
1198 QCOMPARE(rx1
.numCaptures(), 3);
1199 QCOMPARE(rx1
.matchedLength(), 3);
1200 QCOMPARE(rx1
.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1201 QCOMPARE(rx1
.pos(3), 2);
1203 QCOMPARE(rx2
.numCaptures(), 3);
1204 QCOMPARE(rx2
.matchedLength(), 3);
1205 QCOMPARE(rx2
.capturedTexts(), QStringList() << "foo" << "f" << "o" << "o");
1206 QCOMPARE(rx2
.pos(3), 2);
1208 QCOMPARE(rx1
.exactMatch("fo"), true);
1209 QCOMPARE(rx1
.numCaptures(), 3);
1210 QCOMPARE(rx1
.matchedLength(), 2);
1211 QCOMPARE(rx1
.capturedTexts(), QStringList() << "fo" << "f" << "o" << "");
1212 QCOMPARE(rx1
.pos(2), 1);
1214 QCOMPARE(rx1
.pos(3), -1); // ###
1218 QVERIFY(rx3
.isValid());
1220 QRegExp
rx4("foo", Qt::CaseInsensitive
, QRegExp::RegExp
);
1221 QVERIFY(rx4
.isValid());
1223 QRegExp
rx5("foo", Qt::CaseInsensitive
, QRegExp::RegExp2
);
1224 QVERIFY(rx5
.isValid());
1226 QRegExp
rx6("foo", Qt::CaseInsensitive
, QRegExp::FixedString
);
1227 QVERIFY(rx6
.isValid());
1229 QRegExp
rx7("foo", Qt::CaseInsensitive
, QRegExp::Wildcard
);
1230 QVERIFY(rx7
.isValid());
1232 QRegExp
rx8("][", Qt::CaseInsensitive
, QRegExp::RegExp
);
1233 QVERIFY(!rx8
.isValid());
1235 QRegExp
rx9("][", Qt::CaseInsensitive
, QRegExp::RegExp2
);
1236 QVERIFY(!rx9
.isValid());
1238 QRegExp
rx10("][", Qt::CaseInsensitive
, QRegExp::Wildcard
);
1239 QVERIFY(!rx10
.isValid());
1241 QRegExp
rx11("][", Qt::CaseInsensitive
, QRegExp::FixedString
);
1242 QVERIFY(rx11
.isValid());
1243 QVERIFY(rx11
.exactMatch("]["));
1244 QCOMPARE(rx11
.matchedLength(), 2);
1246 rx11
.setPatternSyntax(QRegExp::Wildcard
);
1247 QVERIFY(!rx11
.isValid());
1248 QCOMPARE(rx11
.numCaptures(), 0);
1249 QCOMPARE(rx11
.matchedLength(), -1);
1251 rx11
.setPatternSyntax(QRegExp::RegExp
);
1252 QVERIFY(!rx11
.isValid());
1253 QCOMPARE(rx11
.numCaptures(), 0);
1254 QCOMPARE(rx11
.matchedLength(), -1);
1256 rx11
.setPattern("(foo)");
1257 QVERIFY(rx11
.isValid());
1258 QCOMPARE(rx11
.numCaptures(), 1);
1259 QCOMPARE(rx11
.matchedLength(), -1);
1261 QCOMPARE(rx11
.indexIn("ofoo"), 1);
1262 QCOMPARE(rx11
.numCaptures(), 1);
1263 QCOMPARE(rx11
.matchedLength(), 3);
1265 rx11
.setPatternSyntax(QRegExp::RegExp
);
1266 QCOMPARE(rx11
.numCaptures(), 1);
1267 QCOMPARE(rx11
.matchedLength(), 3);
1270 This behavior isn't entirely consistent with setPatter(),
1271 setPatternSyntax(), and setCaseSensitivity(), but I'm testing
1272 it here to ensure that it doesn't change subtly in future
1275 rx11
.setMinimal(true);
1276 QCOMPARE(rx11
.matchedLength(), 3);
1277 rx11
.setMinimal(false);
1278 QCOMPARE(rx11
.matchedLength(), 3);
1280 rx11
.setPatternSyntax(QRegExp::Wildcard
);
1281 QCOMPARE(rx11
.numCaptures(), 0);
1282 QCOMPARE(rx11
.matchedLength(), -1);
1284 rx11
.setPatternSyntax(QRegExp::RegExp
);
1285 QCOMPARE(rx11
.numCaptures(), 1);
1286 QCOMPARE(rx11
.matchedLength(), -1);
1289 void tst_QRegExp::operator_eq()
1295 QRegExp rxtable
[I
* J
* K
* ELL
];
1299 for (int i
= 0; i
< I
; ++i
) {
1300 for (int j
= 0; j
< J
; ++j
) {
1301 for (int k
= 0; k
< K
; ++k
) {
1302 for (int ell
= 0; ell
< ELL
; ++ell
) {
1303 Qt::CaseSensitivity cs
= i
== 0 ? Qt::CaseSensitive
: Qt::CaseInsensitive
;
1304 QRegExp::PatternSyntax syntax
= QRegExp::PatternSyntax(j
);
1305 bool minimal
= k
== 0;
1308 QRegExp
rx("foo", cs
, syntax
);
1309 rx
.setMinimal(minimal
);
1313 rx
.setPattern("bar");
1314 rx
.setMinimal(true);
1315 rx
.exactMatch("bar");
1316 rx
.setCaseSensitivity(cs
);
1317 rx
.setMinimal(minimal
);
1318 rx
.setPattern("foo");
1319 rx
.setPatternSyntax(syntax
);
1320 rx
.exactMatch("foo");
1328 for (int i
= 0; i
< I
* J
* K
* ELL
; ++i
) {
1329 for (int j
= 0; j
< I
* J
* K
* ELL
; ++j
) {
1330 QCOMPARE(rxtable
[i
] == rxtable
[j
], i
/ ELL
== j
/ ELL
);
1331 QCOMPARE(rxtable
[i
] != rxtable
[j
], i
/ ELL
!= j
/ ELL
);
1336 QTEST_APPLESS_MAIN(tst_QRegExp
)
1337 #include "tst_qregexp.moc"