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