Serenity Operating System
1/*
2 * Copyright (c) 2020, Emanuel Sprung <emanuel.sprung@gmail.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibTest/TestCase.h>
8
9#include <AK/StringBuilder.h>
10#include <AK/Vector.h>
11#include <regex.h>
12#include <stdio.h>
13
14TEST_CASE(catch_all)
15{
16 DeprecatedString pattern = "^.*$";
17 regex_t regex;
18
19 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
20 EXPECT_EQ(regexec(®ex, "Hello World", 0, NULL, 0), REG_NOERR);
21
22 regfree(®ex);
23}
24
25TEST_CASE(simple_start)
26{
27 DeprecatedString pattern = "^hello friends";
28 regex_t regex;
29
30 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
31 EXPECT_EQ(regexec(®ex, "Hello!", 0, NULL, 0), REG_NOMATCH);
32 EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, 0), REG_NOERR);
33 EXPECT_EQ(regexec(®ex, "Well, hello friends", 0, NULL, 0), REG_NOMATCH);
34
35 regfree(®ex);
36}
37
38TEST_CASE(simple_end)
39{
40 DeprecatedString pattern = ".*hello\\.\\.\\. there$";
41 regex_t regex;
42
43 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
44 EXPECT_EQ(regexec(®ex, "Hallo", 0, NULL, 0), REG_NOMATCH);
45 EXPECT_EQ(regexec(®ex, "I said fyhello... there", 0, NULL, 0), REG_NOERR);
46 EXPECT_EQ(regexec(®ex, "ahello... therea", 0, NULL, 0), REG_NOMATCH);
47 EXPECT_EQ(regexec(®ex, "hello.. there", 0, NULL, 0), REG_NOMATCH);
48
49 regfree(®ex);
50}
51
52TEST_CASE(simple_period)
53{
54 DeprecatedString pattern = "hello.";
55 regex_t regex;
56
57 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
58 EXPECT_EQ(regexec(®ex, "Hello1", 0, NULL, 0), REG_NOMATCH);
59 EXPECT_EQ(regexec(®ex, "hello1", 0, NULL, 0), REG_NOERR);
60 EXPECT_EQ(regexec(®ex, "hello2", 0, NULL, 0), REG_NOERR);
61 EXPECT_EQ(regexec(®ex, "hello?", 0, NULL, 0), REG_NOERR);
62
63 regfree(®ex);
64}
65
66TEST_CASE(simple_period_end)
67{
68 DeprecatedString pattern = "hello.$";
69 regex_t regex;
70
71 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB), REG_NOERR);
72 EXPECT_EQ(regexec(®ex, "Hello1", 0, NULL, REG_NOSUB), REG_NOMATCH);
73 EXPECT_EQ(regexec(®ex, "hello1hello1", 0, NULL, REG_GLOBAL), REG_NOERR);
74 EXPECT_EQ(regexec(®ex, "hello2hell", 0, NULL, REG_GLOBAL), REG_NOMATCH);
75 EXPECT_EQ(regexec(®ex, "hello?", 0, NULL, REG_NOSUB), REG_NOERR);
76
77 regfree(®ex);
78}
79
80TEST_CASE(simple_escaped)
81{
82 DeprecatedString pattern = "hello\\.";
83 regex_t regex;
84
85 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
86 EXPECT_EQ(regexec(®ex, "hello", 0, NULL, 0), REG_NOMATCH);
87 EXPECT_EQ(regexec(®ex, "hello.", 0, NULL, 0), REG_NOERR);
88
89 regfree(®ex);
90}
91
92TEST_CASE(simple_period2_end)
93{
94 DeprecatedString pattern = ".*hi... there$";
95 regex_t regex;
96
97 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
98 EXPECT_EQ(regexec(®ex, "Hello there", 0, NULL, REG_GLOBAL), REG_NOMATCH);
99 EXPECT_EQ(regexec(®ex, "I said fyhi... there", 0, NULL, REG_GLOBAL), REG_NOERR);
100 EXPECT_EQ(regexec(®ex, "....hi... ", 0, NULL, REG_GLOBAL), REG_NOMATCH);
101 EXPECT_EQ(regexec(®ex, "I said fyhihii there", 0, NULL, REG_GLOBAL), REG_NOERR);
102 EXPECT_EQ(regexec(®ex, "I said fyhihi there", 0, NULL, REG_GLOBAL), REG_NOMATCH);
103
104 regfree(®ex);
105}
106
107TEST_CASE(simple_plus)
108{
109 DeprecatedString pattern = "a+";
110 regex_t regex;
111
112 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB), REG_NOERR);
113 EXPECT_EQ(regexec(®ex, "b", 0, NULL, REG_NOSUB), REG_NOMATCH);
114 EXPECT_EQ(regexec(®ex, "a", 0, NULL, REG_NOSUB), REG_NOERR);
115 EXPECT_EQ(regexec(®ex, "aaaaaabbbbb", 0, NULL, REG_GLOBAL), REG_NOERR);
116 EXPECT_EQ(regexec(®ex, "aaaaaaaaaaa", 0, NULL, REG_GLOBAL), REG_NOERR);
117
118 regfree(®ex);
119}
120
121TEST_CASE(simple_questionmark)
122{
123 DeprecatedString pattern = "da?d";
124 regex_t regex;
125
126 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
127 EXPECT_EQ(regexec(®ex, "a", 0, NULL, REG_GLOBAL), REG_NOMATCH);
128 EXPECT_EQ(regexec(®ex, "daa", 0, NULL, REG_GLOBAL), REG_NOMATCH);
129 EXPECT_EQ(regexec(®ex, "ddddd", 0, NULL, REG_GLOBAL), REG_NOERR);
130 EXPECT_EQ(regexec(®ex, "dd", 0, NULL, REG_GLOBAL), REG_NOERR);
131 EXPECT_EQ(regexec(®ex, "dad", 0, NULL, REG_GLOBAL), REG_NOERR);
132 EXPECT_EQ(regexec(®ex, "dada", 0, NULL, REG_GLOBAL), REG_NOERR);
133 EXPECT_EQ(regexec(®ex, "adadaa", 0, NULL, REG_GLOBAL), REG_NOERR);
134
135 regfree(®ex);
136}
137
138TEST_CASE(simple_questionmark_matchall)
139{
140 DeprecatedString pattern = "da?d";
141 regex_t regex;
142 static constexpr int num_matches { 5 };
143 regmatch_t matches[num_matches];
144
145 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
146 EXPECT_EQ(regexec(®ex, "a", num_matches, matches, REG_GLOBAL), REG_NOMATCH);
147 EXPECT_EQ(matches[0].rm_cnt, 0);
148 EXPECT_EQ(regexec(®ex, "daa", num_matches, matches, REG_GLOBAL), REG_NOMATCH);
149 EXPECT_EQ(matches[0].rm_cnt, 0);
150
151 EXPECT_EQ(regexec(®ex, "ddddd", num_matches, matches, REG_GLOBAL), REG_NOERR);
152 EXPECT_EQ(matches[0].rm_cnt, 2);
153
154 EXPECT_EQ(matches[0].rm_so, 0);
155 EXPECT_EQ(matches[0].rm_eo, 2);
156 EXPECT_EQ(matches[1].rm_so, 2);
157 EXPECT_EQ(matches[1].rm_eo, 4);
158
159 EXPECT_EQ(regexec(®ex, "dd", num_matches, matches, REG_GLOBAL), REG_NOERR);
160 EXPECT_EQ(matches[0].rm_cnt, 1);
161 EXPECT_EQ(regexec(®ex, "dad", num_matches, matches, REG_GLOBAL), REG_NOERR);
162 EXPECT_EQ(matches[0].rm_cnt, 1);
163 EXPECT_EQ(regexec(®ex, "dada", num_matches, matches, REG_GLOBAL), REG_NOERR);
164 EXPECT_EQ(matches[0].rm_cnt, 1);
165 EXPECT_EQ(regexec(®ex, "adadaa", num_matches, matches, REG_GLOBAL), REG_NOERR);
166 EXPECT_EQ(matches[0].rm_cnt, 1);
167
168 regfree(®ex);
169}
170
171TEST_CASE(character_class)
172{
173 DeprecatedString pattern = "[[:alpha:]]";
174 regex_t regex;
175 static constexpr int num_matches { 5 };
176 regmatch_t matches[num_matches];
177
178 DeprecatedString haystack = "[Window]\nOpacity=255\nAudibleBeep=0\n";
179 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
180 EXPECT_EQ(regexec(®ex, haystack.characters(), num_matches, matches, 0), REG_NOMATCH);
181 EXPECT_EQ(matches[0].rm_cnt, 0);
182 EXPECT_EQ(regexec(®ex, haystack.characters(), num_matches, matches, REG_GLOBAL), REG_NOERR);
183 EXPECT_EQ(matches[0].rm_cnt, 24);
184 EXPECT_EQ(haystack.substring_view(matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so), "W");
185 EXPECT_EQ(haystack.substring_view(matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so), "i");
186
187 regfree(®ex);
188}
189
190TEST_CASE(character_class2)
191{
192 DeprecatedString pattern = "[[:alpha:]]*=([[:digit:]]*)|\\[(.*)\\]";
193 regex_t regex;
194 static constexpr int num_matches { 9 };
195 regmatch_t matches[num_matches];
196
197 DeprecatedString haystack = "[Window]\nOpacity=255\nAudibleBeep=0\n";
198 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NEWLINE), REG_NOERR);
199 EXPECT_EQ(regexec(®ex, haystack.characters(), num_matches, matches, 0), REG_NOERR);
200
201 EXPECT_EQ(matches[0].rm_cnt, 3);
202#if 0
203 for (int i = 0; i < num_matches; ++i) {
204 fprintf(stderr, "Matches[%i].rm_so: %li, .rm_eo: %li .rm_cnt: %li: ", i, matches[i].rm_so, matches[i].rm_eo, matches[i].rm_cnt);
205 fprintf(stderr, "haystack length: %lu\n", haystack.length());
206 if (matches[i].rm_so != -1)
207 fprintf(stderr, "%s\n", haystack.substring_view(matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so).to_deprecated_string().characters());
208 }
209#endif
210
211 EXPECT_EQ(haystack.substring_view(matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so), "[Window]");
212
213 EXPECT_EQ(matches[1].rm_so, -1);
214 EXPECT_EQ(matches[1].rm_eo, -1);
215 EXPECT_EQ(matches[1].rm_cnt, 0);
216
217 EXPECT_EQ(haystack.substring_view(matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so), "Window");
218 EXPECT_EQ(haystack.substring_view(matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so), "Opacity=255");
219
220 EXPECT_EQ(haystack.substring_view(matches[4].rm_so, matches[4].rm_eo - matches[4].rm_so), "255");
221
222 EXPECT_EQ(matches[5].rm_so, -1);
223 EXPECT_EQ(matches[5].rm_eo, -1);
224 EXPECT_EQ(matches[5].rm_cnt, 0);
225
226 EXPECT_EQ(haystack.substring_view(matches[6].rm_so, matches[6].rm_eo - matches[6].rm_so), "AudibleBeep=0");
227 EXPECT_EQ(haystack.substring_view(matches[7].rm_so, matches[7].rm_eo - matches[7].rm_so), "0");
228
229 EXPECT_EQ(matches[8].rm_so, -1);
230 EXPECT_EQ(matches[8].rm_eo, -1);
231 EXPECT_EQ(matches[8].rm_cnt, 0);
232
233 regfree(®ex);
234}
235
236TEST_CASE(escaped_char_questionmark)
237{
238 DeprecatedString pattern = "This\\.?And\\.?That";
239 regex_t regex;
240
241 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
242 EXPECT_EQ(regexec(®ex, "ThisAndThat", 0, NULL, 0), REG_NOERR);
243 EXPECT_EQ(regexec(®ex, "This.And.That", 0, NULL, 0), REG_NOERR);
244 EXPECT_EQ(regexec(®ex, "This And That", 0, NULL, 0), REG_NOMATCH);
245 EXPECT_EQ(regexec(®ex, "This..And..That", 0, NULL, 0), REG_NOMATCH);
246
247 regfree(®ex);
248}
249
250TEST_CASE(char_qualifier_asterisk)
251{
252 DeprecatedString pattern = "regex*";
253 regex_t regex;
254 static constexpr int num_matches { 5 };
255 regmatch_t matches[num_matches];
256
257 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
258 EXPECT_EQ(regexec(®ex, "#include <regex.h>", num_matches, matches, REG_GLOBAL), REG_NOERR);
259 EXPECT_EQ(matches[0].rm_cnt, 1);
260
261 regfree(®ex);
262}
263
264TEST_CASE(char_utf8)
265{
266 DeprecatedString pattern = "😀";
267 regex_t regex;
268 static constexpr int num_matches { 5 };
269 regmatch_t matches[num_matches];
270
271 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
272 EXPECT_EQ(regexec(®ex, "Привет, мир! 😀 γειά σου κόσμος 😀 こんにちは世界", num_matches, matches, REG_GLOBAL), REG_NOERR);
273 EXPECT_EQ(matches[0].rm_cnt, 2);
274
275 regfree(®ex);
276}
277
278TEST_CASE(parens)
279{
280 DeprecatedString pattern = "test(hello)test";
281 regex_t regex;
282 static constexpr int num_matches { 5 };
283 regmatch_t matches[num_matches];
284
285 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
286
287 EXPECT_EQ(regexec(®ex, "testhellotest", num_matches, matches, 0), REG_NOERR);
288 EXPECT_EQ(matches[0].rm_cnt, 1);
289
290 EXPECT_EQ(matches[0].rm_so, 0);
291 EXPECT_EQ(matches[0].rm_eo, 13);
292 EXPECT_EQ(matches[1].rm_so, 4);
293 EXPECT_EQ(matches[1].rm_eo, 9);
294
295 regfree(®ex);
296}
297
298TEST_CASE(parser_error_parens)
299{
300 DeprecatedString pattern = "test()test";
301 regex_t regex;
302 static constexpr int num_matches { 5 };
303 regmatch_t matches[num_matches];
304
305 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
306 EXPECT_EQ(regexec(®ex, "testhellotest", num_matches, matches, 0), REG_EMPTY_EXPR);
307
308 regfree(®ex);
309}
310
311TEST_CASE(parser_error_special_characters_used_at_wrong_place)
312{
313 DeprecatedString pattern;
314 regex_t regex;
315 static constexpr int num_matches { 5 };
316 regmatch_t matches[num_matches];
317
318 Vector<char, 4> chars = { '*', '+', '?', '}' };
319 StringBuilder b;
320
321 for (auto& ch : chars) {
322
323 auto error_code_to_check = ch == '}' ? REG_EBRACE : REG_BADRPT;
324
325 // First in ere
326 b.clear();
327 b.append(ch);
328 pattern = b.to_deprecated_string();
329 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), error_code_to_check);
330 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), error_code_to_check);
331 regfree(®ex);
332
333 // After vertical line
334 b.clear();
335 b.append("a|"sv);
336 b.append(ch);
337 pattern = b.to_deprecated_string();
338 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), error_code_to_check);
339 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), error_code_to_check);
340 regfree(®ex);
341
342 // After circumflex
343 b.clear();
344 b.append('^');
345 b.append(ch);
346 pattern = b.to_deprecated_string();
347 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), error_code_to_check);
348 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), error_code_to_check);
349 regfree(®ex);
350
351 // After dollar
352 b.clear();
353 b.append('$');
354 b.append(ch);
355 pattern = b.to_deprecated_string();
356 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), error_code_to_check);
357 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), error_code_to_check);
358 regfree(®ex);
359
360 // After left parens
361 b.clear();
362 b.append('(');
363 b.append(ch);
364 b.append(')');
365 pattern = b.to_deprecated_string();
366 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), error_code_to_check);
367 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), error_code_to_check);
368 regfree(®ex);
369 }
370}
371
372TEST_CASE(parser_error_vertical_line_used_at_wrong_place)
373{
374 DeprecatedString pattern;
375 regex_t regex;
376 static constexpr int num_matches { 5 };
377 regmatch_t matches[num_matches];
378
379 // First in ere
380 pattern = "|asdf";
381 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
382 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
383 regfree(®ex);
384
385 // Last in ere
386 pattern = "asdf|";
387 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
388 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
389 regfree(®ex);
390
391 // After left parens
392 pattern = "(|asdf)";
393 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
394 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
395 regfree(®ex);
396
397 // Proceed right parens
398 pattern = "(asdf)|";
399 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
400 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
401 regfree(®ex);
402}
403
404TEST_CASE(parens_qualifier_questionmark)
405{
406 DeprecatedString pattern = "test(hello)?test";
407 regex_t regex;
408 static constexpr int num_matches { 5 };
409 regmatch_t matches[num_matches];
410 char const* match_str;
411
412 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
413
414 match_str = "testtest";
415 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
416 EXPECT_EQ(matches[0].rm_cnt, 1);
417 EXPECT_EQ(matches[0].rm_so, 0);
418 EXPECT_EQ(matches[0].rm_eo, 8);
419 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
420
421 match_str = "testhellotest";
422 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
423 EXPECT_EQ(matches[0].rm_cnt, 1);
424 EXPECT_EQ(matches[0].rm_so, 0);
425 EXPECT_EQ(matches[0].rm_eo, 13);
426 EXPECT_EQ(matches[1].rm_so, 4);
427 EXPECT_EQ(matches[1].rm_eo, 9);
428 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellotest");
429 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
430
431 regfree(®ex);
432}
433
434TEST_CASE(parens_qualifier_asterisk)
435{
436 DeprecatedString pattern = "test(hello)*test";
437 regex_t regex;
438 static constexpr int num_matches { 6 };
439 regmatch_t matches[num_matches];
440 char const* match_str;
441
442 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
443
444 match_str = "testtest";
445 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
446 EXPECT_EQ(matches[0].rm_cnt, 1);
447 EXPECT_EQ(matches[0].rm_so, 0);
448 EXPECT_EQ(matches[0].rm_eo, 8);
449 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
450
451 match_str = "testhellohellotest";
452 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
453 EXPECT_EQ(matches[0].rm_cnt, 1);
454 EXPECT_EQ(matches[0].rm_so, 0);
455 EXPECT_EQ(matches[0].rm_eo, 18);
456 EXPECT_EQ(matches[1].rm_so, 9);
457 EXPECT_EQ(matches[1].rm_eo, 14);
458 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellohellotest");
459 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
460
461 match_str = "testhellohellotest, testhellotest";
462 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
463 EXPECT_EQ(matches[0].rm_cnt, 2);
464 EXPECT_EQ(matches[0].rm_so, 0);
465 EXPECT_EQ(matches[0].rm_eo, 18);
466 EXPECT_EQ(matches[1].rm_so, 9);
467 EXPECT_EQ(matches[1].rm_eo, 14);
468 EXPECT_EQ(matches[2].rm_so, 20);
469 EXPECT_EQ(matches[2].rm_eo, 33);
470 EXPECT_EQ(matches[3].rm_so, 24);
471 EXPECT_EQ(matches[3].rm_eo, 29);
472 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellohellotest");
473 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
474 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "testhellotest");
475 EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "hello");
476
477 regfree(®ex);
478}
479
480TEST_CASE(parens_qualifier_asterisk_2)
481{
482 DeprecatedString pattern = "test(.*)test";
483 regex_t regex;
484 static constexpr int num_matches { 6 };
485 regmatch_t matches[num_matches];
486 char const* match_str;
487
488 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
489
490 match_str = "testasdftest";
491 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
492 EXPECT_EQ(matches[0].rm_cnt, 1);
493 EXPECT_EQ(matches[0].rm_so, 0);
494 EXPECT_EQ(matches[0].rm_eo, 12);
495 EXPECT_EQ(matches[1].rm_so, 4);
496 EXPECT_EQ(matches[1].rm_eo, 8);
497 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testasdftest");
498 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "asdf");
499
500 match_str = "testasdfasdftest";
501 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
502 EXPECT_EQ(matches[0].rm_cnt, 1);
503 EXPECT_EQ(matches[0].rm_so, 0);
504 EXPECT_EQ(matches[0].rm_eo, 16);
505 EXPECT_EQ(matches[1].rm_so, 4);
506 EXPECT_EQ(matches[1].rm_eo, 12);
507 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testasdfasdftest");
508 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "asdfasdf");
509
510 match_str = "testaaaatest, testbbbtest, testtest";
511 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
512 EXPECT_EQ(matches[0].rm_cnt, 1);
513 EXPECT_EQ(matches[0].rm_so, 0);
514 EXPECT_EQ(matches[0].rm_eo, 35);
515 EXPECT_EQ(matches[1].rm_so, 4);
516 EXPECT_EQ(matches[1].rm_eo, 31);
517
518 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testaaaatest, testbbbtest, testtest");
519 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "aaaatest, testbbbtest, test");
520
521 regfree(®ex);
522}
523
524TEST_CASE(mulit_parens_qualifier_too_less_result_values)
525{
526 DeprecatedString pattern = "test(a)?(b)?(c)?test";
527 regex_t regex;
528 static constexpr int num_matches { 4 };
529 regmatch_t matches[num_matches];
530 char const* match_str;
531
532 matches[3] = { -2, -2, 100 };
533
534 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
535
536 match_str = "testabtest";
537 EXPECT_EQ(regexec(®ex, match_str, num_matches - 1, matches, 0), REG_NOERR);
538 EXPECT_EQ(matches[0].rm_cnt, 1);
539 EXPECT_EQ(matches[0].rm_so, 0);
540 EXPECT_EQ(matches[0].rm_eo, 10);
541 EXPECT_EQ(matches[1].rm_so, 4);
542 EXPECT_EQ(matches[1].rm_eo, 5);
543 EXPECT_EQ(matches[2].rm_so, 5);
544 EXPECT_EQ(matches[2].rm_eo, 6);
545 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabtest");
546 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
547 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
548 EXPECT_EQ(matches[3].rm_so, -2);
549 EXPECT_EQ(matches[3].rm_eo, -2);
550 EXPECT_EQ(matches[3].rm_cnt, 100);
551
552 match_str = "testabctest";
553 EXPECT_EQ(regexec(®ex, match_str, num_matches - 1, matches, 0), REG_NOERR);
554 EXPECT_EQ(matches[0].rm_cnt, 1);
555 EXPECT_EQ(matches[0].rm_so, 0);
556 EXPECT_EQ(matches[0].rm_eo, 11);
557 EXPECT_EQ(matches[1].rm_so, 4);
558 EXPECT_EQ(matches[1].rm_eo, 5);
559 EXPECT_EQ(matches[2].rm_so, 5);
560 EXPECT_EQ(matches[2].rm_eo, 6);
561 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
562 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
563 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
564 EXPECT_EQ(matches[3].rm_so, -2);
565 EXPECT_EQ(matches[3].rm_eo, -2);
566 EXPECT_EQ(matches[3].rm_cnt, 100);
567
568 match_str = "testabctest, testabctest";
569
570 EXPECT_EQ(regexec(®ex, match_str, num_matches - 1, matches, REG_GLOBAL), REG_NOERR);
571 EXPECT_EQ(matches[0].rm_cnt, 2);
572 EXPECT_EQ(matches[0].rm_so, 0);
573 EXPECT_EQ(matches[0].rm_eo, 11);
574 EXPECT_EQ(matches[1].rm_so, 4);
575 EXPECT_EQ(matches[1].rm_eo, 5);
576 EXPECT_EQ(matches[2].rm_so, 5);
577 EXPECT_EQ(matches[2].rm_eo, 6);
578 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
579 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
580 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
581 EXPECT_EQ(matches[3].rm_so, -2);
582 EXPECT_EQ(matches[3].rm_eo, -2);
583 EXPECT_EQ(matches[3].rm_cnt, 100);
584
585 regfree(®ex);
586}
587
588TEST_CASE(multi_parens_qualifier_questionmark)
589{
590 DeprecatedString pattern = "test(a)?(b)?(c)?test";
591 regex_t regex;
592 static constexpr int num_matches { 8 };
593 regmatch_t matches[num_matches];
594 char const* match_str;
595
596 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
597
598 match_str = "testtest";
599 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
600 EXPECT_EQ(matches[0].rm_cnt, 1);
601 EXPECT_EQ(matches[0].rm_so, 0);
602 EXPECT_EQ(matches[0].rm_eo, 8);
603 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
604
605 match_str = "testabctest";
606 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
607 EXPECT_EQ(matches[0].rm_cnt, 1);
608 EXPECT_EQ(matches[0].rm_so, 0);
609 EXPECT_EQ(matches[0].rm_eo, 11);
610 EXPECT_EQ(matches[1].rm_so, 4);
611 EXPECT_EQ(matches[1].rm_eo, 5);
612 EXPECT_EQ(matches[2].rm_so, 5);
613 EXPECT_EQ(matches[2].rm_eo, 6);
614 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
615 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
616 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
617
618 match_str = "testabctest, testactest";
619
620 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
621 EXPECT_EQ(matches[0].rm_cnt, 2);
622 EXPECT_EQ(matches[0].rm_so, 0);
623 EXPECT_EQ(matches[0].rm_eo, 11);
624 EXPECT_EQ(matches[1].rm_so, 4);
625 EXPECT_EQ(matches[1].rm_eo, 5);
626 EXPECT_EQ(matches[2].rm_so, 5);
627 EXPECT_EQ(matches[2].rm_eo, 6);
628 EXPECT_EQ(matches[3].rm_so, 6);
629 EXPECT_EQ(matches[3].rm_eo, 7);
630
631 EXPECT_EQ(matches[4].rm_so, 13);
632 EXPECT_EQ(matches[4].rm_eo, 23);
633 EXPECT_EQ(matches[5].rm_so, 17);
634 EXPECT_EQ(matches[5].rm_eo, 18);
635 EXPECT_EQ(matches[6].rm_so, -1);
636 EXPECT_EQ(matches[6].rm_eo, -1);
637 EXPECT_EQ(matches[7].rm_so, 18);
638 EXPECT_EQ(matches[7].rm_eo, 19);
639
640 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
641 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
642 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
643 EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "c");
644 EXPECT_EQ(StringView(&match_str[matches[4].rm_so], matches[4].rm_eo - matches[4].rm_so), "testactest");
645 EXPECT_EQ(StringView(&match_str[matches[5].rm_so], matches[5].rm_eo - matches[5].rm_so), "a");
646 EXPECT_EQ(StringView(&match_str[matches[6].rm_so], matches[6].rm_eo - matches[6].rm_so), "");
647 EXPECT_EQ(StringView(&match_str[matches[7].rm_so], matches[7].rm_eo - matches[7].rm_so), "c");
648
649 regfree(®ex);
650}
651
652TEST_CASE(simple_alternative)
653{
654 DeprecatedString pattern = "test|hello|friends";
655 regex_t regex;
656 static constexpr int num_matches { 1 };
657 regmatch_t matches[num_matches];
658
659 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
660
661 EXPECT_EQ(regexec(®ex, "test", num_matches, matches, 0), REG_NOERR);
662 EXPECT_EQ(matches[0].rm_cnt, 1);
663 EXPECT_EQ(matches[0].rm_so, 0);
664 EXPECT_EQ(matches[0].rm_eo, 4);
665
666 EXPECT_EQ(regexec(®ex, "hello", num_matches, matches, 0), REG_NOERR);
667 EXPECT_EQ(matches[0].rm_cnt, 1);
668 EXPECT_EQ(matches[0].rm_so, 0);
669 EXPECT_EQ(matches[0].rm_eo, 5);
670
671 EXPECT_EQ(regexec(®ex, "friends", num_matches, matches, 0), REG_NOERR);
672 EXPECT_EQ(matches[0].rm_cnt, 1);
673 EXPECT_EQ(matches[0].rm_so, 0);
674 EXPECT_EQ(matches[0].rm_eo, 7);
675
676 regfree(®ex);
677}
678
679TEST_CASE(alternative_match_groups)
680{
681 DeprecatedString pattern = "test(a)?(b)?|hello ?(dear|my)? friends";
682 regex_t regex;
683 static constexpr int num_matches { 8 };
684 regmatch_t matches[num_matches];
685 char const* match_str;
686
687 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
688
689 match_str = "test";
690 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
691 EXPECT_EQ(matches[0].rm_cnt, 1);
692 EXPECT_EQ(matches[0].rm_so, 0);
693 EXPECT_EQ(matches[0].rm_eo, 4);
694 EXPECT_EQ(matches[1].rm_so, -1);
695 EXPECT_EQ(matches[1].rm_eo, -1);
696 EXPECT_EQ(matches[2].rm_so, -1);
697 EXPECT_EQ(matches[2].rm_eo, -1);
698 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "test");
699 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
700 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
701
702 match_str = "testa";
703 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
704 EXPECT_EQ(matches[0].rm_cnt, 1);
705 EXPECT_EQ(matches[0].rm_so, 0);
706 EXPECT_EQ(matches[0].rm_eo, 5);
707 EXPECT_EQ(matches[1].rm_so, 4);
708 EXPECT_EQ(matches[1].rm_eo, 5);
709 EXPECT_EQ(matches[2].rm_so, -1);
710 EXPECT_EQ(matches[2].rm_eo, -1);
711 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testa");
712 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
713 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
714
715 match_str = "testb";
716 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
717 EXPECT_EQ(matches[0].rm_cnt, 1);
718 EXPECT_EQ(matches[0].rm_so, 0);
719 EXPECT_EQ(matches[0].rm_eo, 5);
720 EXPECT_EQ(matches[1].rm_so, -1);
721 EXPECT_EQ(matches[1].rm_eo, -1);
722 EXPECT_EQ(matches[2].rm_so, 4);
723 EXPECT_EQ(matches[2].rm_eo, 5);
724 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testb");
725 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
726 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
727
728 match_str = "hello friends";
729 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
730 EXPECT_EQ(matches[0].rm_cnt, 1);
731 EXPECT_EQ(matches[0].rm_so, 0);
732 EXPECT_EQ(matches[0].rm_eo, 13);
733 EXPECT_EQ(matches[1].rm_so, -1);
734 EXPECT_EQ(matches[1].rm_eo, -1);
735 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello friends");
736 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
737
738 match_str = "hello dear friends";
739 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
740 EXPECT_EQ(matches[0].rm_cnt, 1);
741 EXPECT_EQ(matches[0].rm_so, 0);
742 EXPECT_EQ(matches[0].rm_eo, 18);
743 EXPECT_EQ(matches[1].rm_so, -1);
744 EXPECT_EQ(matches[1].rm_eo, -1);
745 EXPECT_EQ(matches[2].rm_so, -1);
746 EXPECT_EQ(matches[2].rm_eo, -1);
747 EXPECT_EQ(matches[3].rm_so, 6);
748 EXPECT_EQ(matches[3].rm_eo, 10);
749 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello dear friends");
750 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
751 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
752 EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "dear");
753
754 match_str = "hello my friends";
755 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
756 EXPECT_EQ(matches[0].rm_cnt, 1);
757 EXPECT_EQ(matches[0].rm_so, 0);
758 EXPECT_EQ(matches[0].rm_eo, 16);
759 EXPECT_EQ(matches[1].rm_so, -1);
760 EXPECT_EQ(matches[1].rm_eo, -1);
761 EXPECT_EQ(matches[2].rm_so, -1);
762 EXPECT_EQ(matches[2].rm_eo, -1);
763 EXPECT_EQ(matches[3].rm_so, 6);
764 EXPECT_EQ(matches[3].rm_eo, 8);
765 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello my friends");
766 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
767 EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
768 EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "my");
769
770 match_str = "testabc";
771 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOMATCH);
772 EXPECT_EQ(matches[0].rm_cnt, 0);
773 EXPECT_EQ(matches[0].rm_so, -1);
774 EXPECT_EQ(matches[0].rm_eo, -1);
775
776 match_str = "hello test friends";
777 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOMATCH);
778 EXPECT_EQ(matches[0].rm_cnt, 0);
779 EXPECT_EQ(matches[0].rm_so, -1);
780 EXPECT_EQ(matches[0].rm_eo, -1);
781
782 regfree(®ex);
783}
784
785TEST_CASE(parens_qualifier_exact)
786{
787 DeprecatedString pattern = "(hello){3}";
788 regex_t regex;
789 static constexpr int num_matches { 5 };
790 regmatch_t matches[num_matches];
791 char const* match_str;
792
793 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
794
795 match_str = "hello";
796 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOMATCH);
797 EXPECT_EQ(matches[0].rm_cnt, 0);
798
799 match_str = "hellohellohello";
800 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
801 EXPECT_EQ(matches[0].rm_cnt, 1);
802 EXPECT_EQ(matches[0].rm_so, 0);
803 EXPECT_EQ(matches[0].rm_eo, 15);
804 EXPECT_EQ(matches[1].rm_so, 10);
805 EXPECT_EQ(matches[1].rm_eo, 15);
806 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
807 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
808
809 match_str = "hellohellohellohello";
810 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
811 EXPECT_EQ(matches[0].rm_cnt, 1);
812 EXPECT_EQ(matches[0].rm_so, 0);
813 EXPECT_EQ(matches[0].rm_eo, 15);
814 EXPECT_EQ(matches[1].rm_so, 10);
815 EXPECT_EQ(matches[1].rm_eo, 15);
816 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
817 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
818
819 match_str = "test hellohellohello";
820 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
821 EXPECT_EQ(matches[0].rm_cnt, 1);
822 EXPECT_EQ(matches[0].rm_so, 5);
823 EXPECT_EQ(matches[0].rm_eo, 20);
824 EXPECT_EQ(matches[1].rm_so, 15);
825 EXPECT_EQ(matches[1].rm_eo, 20);
826 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
827 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
828
829 regfree(®ex);
830}
831
832TEST_CASE(parens_qualifier_minimum)
833{
834 DeprecatedString pattern = "(hello){3,}";
835 regex_t regex;
836 static constexpr int num_matches { 5 };
837 regmatch_t matches[num_matches];
838 char const* match_str;
839
840 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
841
842 match_str = "hello";
843 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOMATCH);
844 EXPECT_EQ(matches[0].rm_cnt, 0);
845
846 match_str = "hellohellohello";
847 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
848 EXPECT_EQ(matches[0].rm_cnt, 1);
849 EXPECT_EQ(matches[0].rm_so, 0);
850 EXPECT_EQ(matches[0].rm_eo, 15);
851 EXPECT_EQ(matches[1].rm_so, 10);
852 EXPECT_EQ(matches[1].rm_eo, 15);
853 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
854 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
855
856 match_str = "hellohellohellohello";
857
858 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_SEARCH), REG_NOERR);
859 EXPECT_EQ(matches[0].rm_cnt, 1);
860 EXPECT_EQ(matches[0].rm_so, 0);
861 EXPECT_EQ(matches[0].rm_eo, 20);
862 EXPECT_EQ(matches[1].rm_so, 15);
863 EXPECT_EQ(matches[1].rm_eo, 20);
864 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohellohello");
865 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
866
867 match_str = "test hellohellohello";
868 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
869 EXPECT_EQ(matches[0].rm_cnt, 1);
870 EXPECT_EQ(matches[0].rm_so, 5);
871 EXPECT_EQ(matches[0].rm_eo, 20);
872 EXPECT_EQ(matches[1].rm_so, 15);
873 EXPECT_EQ(matches[1].rm_eo, 20);
874 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
875 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
876
877 match_str = "test hellohellohellohello";
878 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
879 EXPECT_EQ(matches[0].rm_cnt, 1);
880 EXPECT_EQ(matches[0].rm_so, 5);
881 EXPECT_EQ(matches[0].rm_eo, 25);
882 EXPECT_EQ(matches[1].rm_so, 20);
883 EXPECT_EQ(matches[1].rm_eo, 25);
884 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohellohello");
885 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
886
887 regfree(®ex);
888}
889
890TEST_CASE(parens_qualifier_maximum)
891{
892 DeprecatedString pattern = "(hello){2,3}";
893 regex_t regex;
894 static constexpr int num_matches { 5 };
895 regmatch_t matches[num_matches];
896 char const* match_str;
897
898 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
899
900 match_str = "hello";
901 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOMATCH);
902 EXPECT_EQ(matches[0].rm_cnt, 0);
903
904 match_str = "hellohellohello";
905 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, 0), REG_NOERR);
906 EXPECT_EQ(matches[0].rm_cnt, 1);
907 EXPECT_EQ(matches[0].rm_so, 0);
908 EXPECT_EQ(matches[0].rm_eo, 15);
909 EXPECT_EQ(matches[1].rm_so, 10);
910 EXPECT_EQ(matches[1].rm_eo, 15);
911 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
912 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
913
914 match_str = "hellohellohellohello";
915 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
916 EXPECT_EQ(matches[0].rm_cnt, 1);
917 EXPECT_EQ(matches[0].rm_so, 0);
918 EXPECT_EQ(matches[0].rm_eo, 15);
919 EXPECT_EQ(matches[1].rm_so, 10);
920 EXPECT_EQ(matches[1].rm_eo, 15);
921 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
922 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
923
924 match_str = "test hellohellohello";
925 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
926 EXPECT_EQ(matches[0].rm_cnt, 1);
927 EXPECT_EQ(matches[0].rm_so, 5);
928 EXPECT_EQ(matches[0].rm_eo, 20);
929 EXPECT_EQ(matches[1].rm_so, 15);
930 EXPECT_EQ(matches[1].rm_eo, 20);
931 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
932 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
933
934 match_str = "test hellohellohellohello";
935 EXPECT_EQ(regexec(®ex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
936 EXPECT_EQ(matches[0].rm_cnt, 1);
937 EXPECT_EQ(matches[0].rm_so, 5);
938 EXPECT_EQ(matches[0].rm_eo, 20);
939 EXPECT_EQ(matches[1].rm_so, 15);
940 EXPECT_EQ(matches[1].rm_eo, 20);
941 EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
942 EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
943
944 regfree(®ex);
945}
946
947TEST_CASE(char_qualifier_min_max)
948{
949 DeprecatedString pattern = "c{3,30}";
950 regex_t regex;
951 static constexpr int num_matches { 5 };
952 regmatch_t matches[num_matches];
953
954 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
955
956 EXPECT_EQ(regexec(®ex, "cc", num_matches, matches, 0), REG_NOMATCH);
957 EXPECT_EQ(regexec(®ex, "ccc", num_matches, matches, 0), REG_NOERR);
958 EXPECT_EQ(regexec(®ex, "cccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOERR);
959 EXPECT_EQ(matches[0].rm_cnt, 1);
960 EXPECT_EQ(regexec(®ex, "ccccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOMATCH);
961 EXPECT_EQ(regexec(®ex, "ccccccccccccccccccccccccccccccc", num_matches, matches, REG_GLOBAL), REG_NOERR);
962 EXPECT_EQ(regexec(®ex, "cccccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOMATCH);
963
964 regfree(®ex);
965}
966
967TEST_CASE(simple_bracket_chars)
968{
969 DeprecatedString pattern = "[abc]";
970 regex_t regex;
971
972 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
973 EXPECT_EQ(regexec(®ex, "a", 0, NULL, 0), REG_NOERR);
974 EXPECT_EQ(regexec(®ex, "b", 0, NULL, 0), REG_NOERR);
975 EXPECT_EQ(regexec(®ex, "c", 0, NULL, 0), REG_NOERR);
976 EXPECT_EQ(regexec(®ex, "d", 0, NULL, 0), REG_NOMATCH);
977 EXPECT_EQ(regexec(®ex, "e", 0, NULL, 0), REG_NOMATCH);
978 regfree(®ex);
979}
980
981TEST_CASE(simple_bracket_chars_inverse)
982{
983 DeprecatedString pattern = "[^abc]";
984 regex_t regex;
985
986 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
987 EXPECT_EQ(regexec(®ex, "a", 0, NULL, 0), REG_NOMATCH);
988 EXPECT_EQ(regexec(®ex, "b", 0, NULL, 0), REG_NOMATCH);
989 EXPECT_EQ(regexec(®ex, "c", 0, NULL, 0), REG_NOMATCH);
990 EXPECT_EQ(regexec(®ex, "d", 0, NULL, 0), REG_NOERR);
991 EXPECT_EQ(regexec(®ex, "e", 0, NULL, 0), REG_NOERR);
992 regfree(®ex);
993}
994
995TEST_CASE(simple_bracket_chars_range)
996{
997 DeprecatedString pattern = "[a-d]";
998 regex_t regex;
999
1000 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
1001 EXPECT_EQ(regexec(®ex, "a", 0, NULL, 0), REG_NOERR);
1002 EXPECT_EQ(regexec(®ex, "b", 0, NULL, 0), REG_NOERR);
1003 EXPECT_EQ(regexec(®ex, "c", 0, NULL, 0), REG_NOERR);
1004 EXPECT_EQ(regexec(®ex, "d", 0, NULL, 0), REG_NOERR);
1005 EXPECT_EQ(regexec(®ex, "e", 0, NULL, 0), REG_NOMATCH);
1006 regfree(®ex);
1007}
1008
1009TEST_CASE(simple_bracket_chars_range_inverse)
1010{
1011 DeprecatedString pattern = "[^a-df-z]";
1012 regex_t regex;
1013
1014 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
1015 EXPECT_EQ(regexec(®ex, "a", 0, NULL, 0), REG_NOMATCH);
1016 EXPECT_EQ(regexec(®ex, "b", 0, NULL, 0), REG_NOMATCH);
1017 EXPECT_EQ(regexec(®ex, "c", 0, NULL, 0), REG_NOMATCH);
1018 EXPECT_EQ(regexec(®ex, "d", 0, NULL, 0), REG_NOMATCH);
1019 EXPECT_EQ(regexec(®ex, "e", 0, NULL, 0), REG_NOERR);
1020 EXPECT_EQ(regexec(®ex, "k", 0, NULL, 0), REG_NOMATCH);
1021 EXPECT_EQ(regexec(®ex, "z", 0, NULL, 0), REG_NOMATCH);
1022 regfree(®ex);
1023}
1024
1025TEST_CASE(bracket_character_class_uuid)
1026{
1027 DeprecatedString pattern = "^([[:xdigit:]]{8})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{12})$";
1028 regex_t regex;
1029
1030 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
1031 EXPECT_EQ(regexec(®ex, "fb9b62a2-1579-4e3a-afba-76239ccb6583", 0, NULL, 0), REG_NOERR);
1032 EXPECT_EQ(regexec(®ex, "fb9b62a2", 0, NULL, 0), REG_NOMATCH);
1033
1034 regfree(®ex);
1035}
1036
1037TEST_CASE(simple_bracket_character_class_inverse)
1038{
1039 DeprecatedString pattern = "[^[:digit:]]";
1040 regex_t regex;
1041
1042 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
1043 EXPECT_EQ(regexec(®ex, "1", 0, NULL, 0), REG_NOMATCH);
1044 EXPECT_EQ(regexec(®ex, "2", 0, NULL, 0), REG_NOMATCH);
1045 EXPECT_EQ(regexec(®ex, "3", 0, NULL, 0), REG_NOMATCH);
1046 EXPECT_EQ(regexec(®ex, "d", 0, NULL, 0), REG_NOERR);
1047 EXPECT_EQ(regexec(®ex, "e", 0, NULL, 0), REG_NOERR);
1048 regfree(®ex);
1049}
1050
1051TEST_CASE(email_address)
1052{
1053 DeprecatedString pattern = "^[A-Z0-9a-z._%+-]{1,64}@(?:[A-Za-z0-9-]{1,63}\\.){1,125}[A-Za-z]{2,63}$";
1054 regex_t regex;
1055
1056 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_NOERR);
1057 EXPECT_EQ(regexec(®ex, "emanuel.sprung@gmail.com", 0, NULL, 0), REG_NOERR);
1058 EXPECT_EQ(regexec(®ex, "kling@serenityos.org", 0, NULL, 0), REG_NOERR);
1059
1060 regfree(®ex);
1061}
1062
1063TEST_CASE(error_message)
1064{
1065 DeprecatedString pattern = "^[A-Z0-9[a-z._%+-]{1,64}@[A-Za-z0-9-]{1,63}\\.{1,125}[A-Za-z]{2,63}$";
1066 regex_t regex;
1067
1068 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED), REG_EBRACK);
1069 EXPECT_EQ(regexec(®ex, "asdf@asdf.com", 0, NULL, 0), REG_EBRACK);
1070 char buf[1024];
1071 size_t buflen = 1024;
1072 auto len = regerror(0, ®ex, buf, buflen);
1073 DeprecatedString expected = "Error during parsing of regular expression:\n ^[A-Z0-9[a-z._%+-]{1,64}@[A-Za-z0-9-]{1,63}\\.{1,125}[A-Za-z]{2,63}$\n ^---- [ ] imbalance.";
1074 for (size_t i = 0; i < len; ++i) {
1075 EXPECT_EQ(buf[i], expected[i]);
1076 }
1077
1078 regfree(®ex);
1079}
1080
1081TEST_CASE(simple_ignorecase)
1082{
1083 DeprecatedString pattern = "^hello friends";
1084 regex_t regex;
1085
1086 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
1087 EXPECT_EQ(regexec(®ex, "Hello Friends", 0, NULL, 0), REG_NOERR);
1088 EXPECT_EQ(regexec(®ex, "hello Friends", 0, NULL, 0), REG_NOERR);
1089
1090 EXPECT_EQ(regexec(®ex, "hello Friends!", 0, NULL, 0), REG_NOMATCH);
1091 EXPECT_EQ(regexec(®ex, "hello Friends!", 0, NULL, REG_GLOBAL), REG_NOERR);
1092
1093 EXPECT_EQ(regexec(®ex, "hell Friends", 0, NULL, 0), REG_NOMATCH);
1094 EXPECT_EQ(regexec(®ex, "hell Friends", 0, NULL, REG_GLOBAL), REG_NOMATCH);
1095
1096 regfree(®ex);
1097}
1098
1099TEST_CASE(simple_notbol_noteol)
1100{
1101 DeprecatedString pattern = "^hello friends$";
1102 DeprecatedString pattern2 = "hello friends";
1103 regex_t regex, regex2;
1104
1105 EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
1106 EXPECT_EQ(regcomp(®ex2, pattern2.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
1107
1108 EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
1109 EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH);
1110 EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
1111
1112 EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL), REG_NOMATCH);
1113 EXPECT_EQ(regexec(®ex, "a hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
1114 EXPECT_EQ(regexec(®ex, "a hello friends", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR);
1115 EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR);
1116
1117 EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
1118 EXPECT_EQ(regexec(®ex, "hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
1119 EXPECT_EQ(regexec(®ex, "hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOERR);
1120 EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOMATCH);
1121
1122 EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
1123 EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL | REG_SEARCH), REG_NOMATCH);
1124
1125 EXPECT_EQ(regexec(®ex2, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
1126 EXPECT_EQ(regexec(®ex2, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH);
1127
1128 regfree(®ex);
1129 regfree(®ex2);
1130}
1131
1132TEST_CASE(bre_basic)
1133{
1134 regex_t regex;
1135 EXPECT_EQ(regcomp(®ex, "hello friends", REG_NOSUB | REG_ICASE), REG_NOERR);
1136 EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, 0), REG_NOERR);
1137 regfree(®ex);
1138
1139 EXPECT_EQ(regcomp(®ex, "\\(15\\)\\1", REG_NOSUB | REG_ICASE), REG_NOERR);
1140 EXPECT_EQ(regexec(®ex, "1515", 0, NULL, 0), REG_NOERR);
1141 EXPECT_EQ(regexec(®ex, "55", 0, NULL, 0), REG_NOMATCH);
1142 regfree(®ex);
1143
1144 EXPECT_EQ(regcomp(®ex, "15\\{1,2\\}", REG_NOSUB | REG_ICASE), REG_NOERR);
1145 EXPECT_EQ(regexec(®ex, "15", 0, NULL, 0), REG_NOERR);
1146 EXPECT_EQ(regexec(®ex, "1515", 0, NULL, 0), REG_NOMATCH);
1147 EXPECT_EQ(regexec(®ex, "55", 0, NULL, 0), REG_NOMATCH);
1148 regfree(®ex);
1149
1150 EXPECT_EQ(regcomp(®ex, "15{1,2}", REG_NOSUB | REG_ICASE), REG_NOERR);
1151 EXPECT_EQ(regexec(®ex, "15{1,2}", 0, NULL, 0), REG_NOERR);
1152 regfree(®ex);
1153
1154 EXPECT_EQ(regcomp(®ex, "1[56]", REG_NOSUB | REG_ICASE), REG_NOERR);
1155 EXPECT_EQ(regexec(®ex, "15", 0, NULL, 0), REG_NOERR);
1156 EXPECT_EQ(regexec(®ex, "16", 0, NULL, 0), REG_NOERR);
1157 EXPECT_EQ(regexec(®ex, "17", 0, NULL, 0), REG_NOMATCH);
1158 regfree(®ex);
1159}