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::() |
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 | |