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

source code of qtbase/tests/auto/corelib/text/qregexp/tst_qregexp.cpp