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 | |
32 | const int N = 1; |
33 | |
34 | class tst_QRegExp : public QObject |
35 | { |
36 | Q_OBJECT |
37 | private 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 |
75 | void 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 | |
88 | extern const char email[]; |
89 | |
90 | void tst_QRegExp::lastIndexIn_data() |
91 | { |
92 | indexIn_data(); |
93 | } |
94 | |
95 | void 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 | |
199 | void 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 | |
463 | void 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 | |
489 | void 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 | |
542 | void 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 | |
588 | void 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 | |
645 | void tst_QRegExp::matchedLength() |
646 | { |
647 | QRegExp r1( "a+"); |
648 | r1.exactMatch( str: "aaaba"); |
649 | QCOMPARE( r1.matchedLength(), 3 ); |
650 | } |
651 | |
652 | const 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 | |
772 | void 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 | |
792 | void 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 | |
803 | void 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 | |
846 | void 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 | |
857 | void 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 | |
871 | void 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 | |
881 | void 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 | |
900 | void 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 | |
925 | static QRegExp re("foo.*bar"); |
926 | |
927 | void tst_QRegExp::staticRegExp() |
928 | { |
929 | QVERIFY(re.exactMatch("fooHARRYbar")); |
930 | // the actual test is that a static regexp should not crash |
931 | } |
932 | |
933 | void 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 | |
944 | void 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 | |
968 | class Thread : public QThread |
969 | { |
970 | public: |
971 | Thread(const QRegExp &rx) : rx(rx) {} |
972 | |
973 | void run(); |
974 | |
975 | QRegExp rx; |
976 | }; |
977 | |
978 | void 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 | |
992 | void 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 | |
1009 | class Thread2 : public QThread |
1010 | { |
1011 | public: |
1012 | void run(); |
1013 | }; |
1014 | |
1015 | void 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.) |
1034 | void 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 | |
1051 | void 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 | |
1166 | void 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 | |
1174 | void 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. |
1226 | void 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 | |
1286 | void 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 | |
1316 | void 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 | |
1332 | void 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 | |
1342 | void 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 | |
1359 | void 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 | |
1385 | QTEST_APPLESS_MAIN(tst_QRegExp) |
1386 | #include "tst_qregexp.moc" |
1387 |
Definitions
- N
- tst_QRegExp
- getSetCheck
- lastIndexIn_data
- indexIn_data
- indexIn_addMoreRows
- exactMatch
- capturedTexts
- indexIn
- lastIndexIn
- matchedLength
- wildcard_data
- wildcard
- testEscapingWildcard_data
- testEscapingWildcard
- testInvalidWildcard_data
- testInvalidWildcard
- caretAnchoredOptimization
- isEmpty
- re
- staticRegExp
- rainersSlowRegExpCopyBug
- nonExistingBackReferenceBug
- Thread
- Thread
- run
- reentrancy
- Thread2
- run
- threadsafeEngineCache
- prepareEngineOptimization
- swap
- operator_eq
- posAndCapConsistency_data
- posAndCapConsistency
- interval
- validityCheck_data
- validityCheck
Learn to use CMake with our Intro Training
Find out more