ReviewOS

also looking at this

zig-utils/zig-regex

Port to latest zig-master

#2
Closed armagidon-exception wants to merge main into main
53 files +1149 -1017
tests/stress_edge_cases.zigmodified+58-58
Changes to tests/stress_edge_cases.zig
@@ -11,7 +11,7 @@ const RegexError = @import("regex").RegexError;
1111test "stress: empty alternation branch" {
1212 const allocator = std.testing.allocator;
1313 // Pattern like (|a) should match empty string or "a"
14 var regex = try Regex.compile(allocator, "^(|a)$");
14 var regex = try Regex.compile(allocator, std.testing.io, "^(|a)$");
1515 defer regex.deinit();
1616
1717 try std.testing.expect(try regex.isMatch(""));
@@ -21,7 +21,7 @@ test "stress: empty alternation branch" {
2121
2222test "stress: pattern that only matches empty string" {
2323 const allocator = std.testing.allocator;
24 var regex = try Regex.compile(allocator, "^$");
24 var regex = try Regex.compile(allocator, std.testing.io, "^$");
2525 defer regex.deinit();
2626
2727 try std.testing.expect(try regex.isMatch(""));
@@ -31,7 +31,7 @@ test "stress: pattern that only matches empty string" {
3131
3232test "stress: dot star matches everything" {
3333 const allocator = std.testing.allocator;
34 var regex = try Regex.compile(allocator, ".*");
34 var regex = try Regex.compile(allocator, std.testing.io, ".*");
3535 defer regex.deinit();
3636
3737 try std.testing.expect(try regex.isMatch(""));
@@ -41,7 +41,7 @@ test "stress: dot star matches everything" {
4141
4242test "stress: single dot" {
4343 const allocator = std.testing.allocator;
44 var regex = try Regex.compile(allocator, "^.$");
44 var regex = try Regex.compile(allocator, std.testing.io, "^.$");
4545 defer regex.deinit();
4646
4747 try std.testing.expect(try regex.isMatch("a"));
@@ -55,7 +55,7 @@ test "stress: single dot" {
5555
5656test "stress: {1,1} is same as no quantifier" {
5757 const allocator = std.testing.allocator;
58 var regex = try Regex.compile(allocator, "^a{1,1}$");
58 var regex = try Regex.compile(allocator, std.testing.io, "^a{1,1}$");
5959 defer regex.deinit();
6060
6161 try std.testing.expect(try regex.isMatch("a"));
@@ -65,7 +65,7 @@ test "stress: {1,1} is same as no quantifier" {
6565
6666test "stress: {2,} matches 2 or more" {
6767 const allocator = std.testing.allocator;
68 var regex = try Regex.compile(allocator, "^a{2,}$");
68 var regex = try Regex.compile(allocator, std.testing.io, "^a{2,}$");
6969 defer regex.deinit();
7070
7171 try std.testing.expect(!try regex.isMatch(""));
@@ -77,7 +77,7 @@ test "stress: {2,} matches 2 or more" {
7777
7878test "stress: exact repeat {5}" {
7979 const allocator = std.testing.allocator;
80 var regex = try Regex.compile(allocator, "^x{5}$");
80 var regex = try Regex.compile(allocator, std.testing.io, "^x{5}$");
8181 defer regex.deinit();
8282
8383 try std.testing.expect(!try regex.isMatch("xxxx"));
@@ -87,7 +87,7 @@ test "stress: exact repeat {5}" {
8787
8888test "stress: mixed quantifiers in sequence" {
8989 const allocator = std.testing.allocator;
90 var regex = try Regex.compile(allocator, "^a+b*c?d{2}$");
90 var regex = try Regex.compile(allocator, std.testing.io, "^a+b*c?d{2}$");
9191 defer regex.deinit();
9292
9393 try std.testing.expect(try regex.isMatch("add"));
@@ -101,7 +101,7 @@ test "stress: mixed quantifiers in sequence" {
101101
102102test "stress: character class with hyphen at start" {
103103 const allocator = std.testing.allocator;
104 var regex = try Regex.compile(allocator, "^[-abc]+$");
104 var regex = try Regex.compile(allocator, std.testing.io, "^[-abc]+$");
105105 defer regex.deinit();
106106
107107 try std.testing.expect(try regex.isMatch("-"));
@@ -112,7 +112,7 @@ test "stress: character class with hyphen at start" {
112112
113113test "stress: character class with hyphen at end" {
114114 const allocator = std.testing.allocator;
115 var regex = try Regex.compile(allocator, "^[abc-]+$");
115 var regex = try Regex.compile(allocator, std.testing.io, "^[abc-]+$");
116116 defer regex.deinit();
117117
118118 try std.testing.expect(try regex.isMatch("-"));
@@ -121,7 +121,7 @@ test "stress: character class with hyphen at end" {
121121
122122test "stress: negated character class" {
123123 const allocator = std.testing.allocator;
124 var regex = try Regex.compile(allocator, "^[^abc]+$");
124 var regex = try Regex.compile(allocator, std.testing.io, "^[^abc]+$");
125125 defer regex.deinit();
126126
127127 try std.testing.expect(try regex.isMatch("xyz"));
@@ -132,7 +132,7 @@ test "stress: negated character class" {
132132
133133test "stress: character class with single char range" {
134134 const allocator = std.testing.allocator;
135 var regex = try Regex.compile(allocator, "^[a-a]+$");
135 var regex = try Regex.compile(allocator, std.testing.io, "^[a-a]+$");
136136 defer regex.deinit();
137137
138138 try std.testing.expect(try regex.isMatch("a"));
@@ -142,7 +142,7 @@ test "stress: character class with single char range" {
142142
143143test "stress: overlapping ranges in character class" {
144144 const allocator = std.testing.allocator;
145 var regex = try Regex.compile(allocator, "^[a-zA-Z]+$");
145 var regex = try Regex.compile(allocator, std.testing.io, "^[a-zA-Z]+$");
146146 defer regex.deinit();
147147
148148 try std.testing.expect(try regex.isMatch("hello"));
@@ -154,20 +154,20 @@ test "stress: overlapping ranges in character class" {
154154test "stress: shorthand classes \\d \\w \\s" {
155155 const allocator = std.testing.allocator;
156156 {
157 var regex = try Regex.compile(allocator, "^\\d+$");
157 var regex = try Regex.compile(allocator, std.testing.io, "^\\d+$");
158158 defer regex.deinit();
159159 try std.testing.expect(try regex.isMatch("12345"));
160160 try std.testing.expect(!try regex.isMatch("abc"));
161161 try std.testing.expect(!try regex.isMatch(""));
162162 }
163163 {
164 var regex = try Regex.compile(allocator, "^\\w+$");
164 var regex = try Regex.compile(allocator, std.testing.io, "^\\w+$");
165165 defer regex.deinit();
166166 try std.testing.expect(try regex.isMatch("hello_123"));
167167 try std.testing.expect(!try regex.isMatch("hello world"));
168168 }
169169 {
170 var regex = try Regex.compile(allocator, "^\\s+$");
170 var regex = try Regex.compile(allocator, std.testing.io, "^\\s+$");
171171 defer regex.deinit();
172172 try std.testing.expect(try regex.isMatch(" "));
173173 try std.testing.expect(try regex.isMatch("\t\n"));
@@ -178,19 +178,19 @@ test "stress: shorthand classes \\d \\w \\s" {
178178test "stress: negated shorthand classes \\D \\W \\S" {
179179 const allocator = std.testing.allocator;
180180 {
181 var regex = try Regex.compile(allocator, "^\\D+$");
181 var regex = try Regex.compile(allocator, std.testing.io, "^\\D+$");
182182 defer regex.deinit();
183183 try std.testing.expect(try regex.isMatch("abc"));
184184 try std.testing.expect(!try regex.isMatch("123"));
185185 }
186186 {
187 var regex = try Regex.compile(allocator, "^\\W+$");
187 var regex = try Regex.compile(allocator, std.testing.io, "^\\W+$");
188188 defer regex.deinit();
189189 try std.testing.expect(try regex.isMatch(" !@#"));
190190 try std.testing.expect(!try regex.isMatch("abc"));
191191 }
192192 {
193 var regex = try Regex.compile(allocator, "^\\S+$");
193 var regex = try Regex.compile(allocator, std.testing.io, "^\\S+$");
194194 defer regex.deinit();
195195 try std.testing.expect(try regex.isMatch("abc"));
196196 try std.testing.expect(!try regex.isMatch("a b"));
@@ -201,7 +201,7 @@ test "stress: negated shorthand classes \\D \\W \\S" {
201201
202202test "stress: ^ only matches at start" {
203203 const allocator = std.testing.allocator;
204 var regex = try Regex.compile(allocator, "^abc");
204 var regex = try Regex.compile(allocator, std.testing.io, "^abc");
205205 defer regex.deinit();
206206
207207 try std.testing.expect(try regex.isMatch("abcdef"));
@@ -210,7 +210,7 @@ test "stress: ^ only matches at start" {
210210
211211test "stress: $ only matches at end" {
212212 const allocator = std.testing.allocator;
213 var regex = try Regex.compile(allocator, "abc$");
213 var regex = try Regex.compile(allocator, std.testing.io, "abc$");
214214 defer regex.deinit();
215215
216216 try std.testing.expect(try regex.isMatch("xyzabc"));
@@ -219,7 +219,7 @@ test "stress: $ only matches at end" {
219219
220220test "stress: ^$ on empty string" {
221221 const allocator = std.testing.allocator;
222 var regex = try Regex.compile(allocator, "^$");
222 var regex = try Regex.compile(allocator, std.testing.io, "^$");
223223 defer regex.deinit();
224224
225225 try std.testing.expect(try regex.isMatch(""));
@@ -228,7 +228,7 @@ test "stress: ^$ on empty string" {
228228
229229test "stress: word boundary \\b" {
230230 const allocator = std.testing.allocator;
231 var regex = try Regex.compile(allocator, "\\bword\\b");
231 var regex = try Regex.compile(allocator, std.testing.io, "\\bword\\b");
232232 defer regex.deinit();
233233
234234 try std.testing.expect(try regex.isMatch("a word here"));
@@ -239,7 +239,7 @@ test "stress: word boundary \\b" {
239239
240240test "stress: non-word boundary \\B" {
241241 const allocator = std.testing.allocator;
242 var regex = try Regex.compile(allocator, "\\Bword\\B");
242 var regex = try Regex.compile(allocator, std.testing.io, "\\Bword\\B");
243243 defer regex.deinit();
244244
245245 try std.testing.expect(try regex.isMatch("swordwords"));
@@ -251,7 +251,7 @@ test "stress: non-word boundary \\B" {
251251
252252test "stress: alternation with different lengths" {
253253 const allocator = std.testing.allocator;
254 var regex = try Regex.compile(allocator, "^(a|bb|ccc)$");
254 var regex = try Regex.compile(allocator, std.testing.io, "^(a|bb|ccc)$");
255255 defer regex.deinit();
256256
257257 try std.testing.expect(try regex.isMatch("a"));
@@ -263,7 +263,7 @@ test "stress: alternation with different lengths" {
263263
264264test "stress: nested alternation" {
265265 const allocator = std.testing.allocator;
266 var regex = try Regex.compile(allocator, "^(a(b|c)d|efg)$");
266 var regex = try Regex.compile(allocator, std.testing.io, "^(a(b|c)d|efg)$");
267267 defer regex.deinit();
268268
269269 try std.testing.expect(try regex.isMatch("abd"));
@@ -275,7 +275,7 @@ test "stress: nested alternation" {
275275
276276test "stress: NFA finds longest match for alternation" {
277277 const allocator = std.testing.allocator;
278 var regex = try Regex.compile(allocator, "cat|catfish");
278 var regex = try Regex.compile(allocator, std.testing.io, "cat|catfish");
279279 defer regex.deinit();
280280
281281 if (try regex.find("catfish")) |match| {
@@ -292,7 +292,7 @@ test "stress: NFA finds longest match for alternation" {
292292
293293test "stress: capture group with alternation - only one branch matches" {
294294 const allocator = std.testing.allocator;
295 var regex = try Regex.compile(allocator, "(a)|(b)");
295 var regex = try Regex.compile(allocator, std.testing.io, "(a)|(b)");
296296 defer regex.deinit();
297297
298298 if (try regex.find("b")) |match| {
@@ -306,7 +306,7 @@ test "stress: capture group with alternation - only one branch matches" {
306306
307307test "stress: nested capture groups" {
308308 const allocator = std.testing.allocator;
309 var regex = try Regex.compile(allocator, "((a)(b))");
309 var regex = try Regex.compile(allocator, std.testing.io, "((a)(b))");
310310 defer regex.deinit();
311311
312312 if (try regex.find("ab")) |match| {
@@ -325,7 +325,7 @@ test "stress: nested capture groups" {
325325
326326test "stress: capture with quantifier" {
327327 const allocator = std.testing.allocator;
328 var regex = try Regex.compile(allocator, "(a)+");
328 var regex = try Regex.compile(allocator, std.testing.io, "(a)+");
329329 defer regex.deinit();
330330
331331 if (try regex.find("aaa")) |match| {
@@ -341,7 +341,7 @@ test "stress: capture with quantifier" {
341341
342342test "stress: findAll with no matches" {
343343 const allocator = std.testing.allocator;
344 var regex = try Regex.compile(allocator, "xyz");
344 var regex = try Regex.compile(allocator, std.testing.io, "xyz");
345345 defer regex.deinit();
346346
347347 const matches = try regex.findAll(allocator, "abc def ghi");
@@ -358,7 +358,7 @@ test "stress: findAll with no matches" {
358358
359359test "stress: findAll adjacent matches" {
360360 const allocator = std.testing.allocator;
361 var regex = try Regex.compile(allocator, "\\d");
361 var regex = try Regex.compile(allocator, std.testing.io, "\\d");
362362 defer regex.deinit();
363363
364364 const matches = try regex.findAll(allocator, "123");
@@ -378,7 +378,7 @@ test "stress: findAll adjacent matches" {
378378
379379test "stress: findAll non-overlapping" {
380380 const allocator = std.testing.allocator;
381 var regex = try Regex.compile(allocator, "aa");
381 var regex = try Regex.compile(allocator, std.testing.io, "aa");
382382 defer regex.deinit();
383383
384384 const matches = try regex.findAll(allocator, "aaaa");
@@ -398,7 +398,7 @@ test "stress: findAll non-overlapping" {
398398
399399test "stress: replace with no match returns input" {
400400 const allocator = std.testing.allocator;
401 var regex = try Regex.compile(allocator, "xyz");
401 var regex = try Regex.compile(allocator, std.testing.io, "xyz");
402402 defer regex.deinit();
403403
404404 const result = try regex.replace(allocator, "hello world", "!");
@@ -408,7 +408,7 @@ test "stress: replace with no match returns input" {
408408
409409test "stress: replace with empty replacement" {
410410 const allocator = std.testing.allocator;
411 var regex = try Regex.compile(allocator, "\\s+");
411 var regex = try Regex.compile(allocator, std.testing.io, "\\s+");
412412 defer regex.deinit();
413413
414414 const result = try regex.replace(allocator, "hello world", "");
@@ -418,7 +418,7 @@ test "stress: replace with empty replacement" {
418418
419419test "stress: replaceAll removes all matches" {
420420 const allocator = std.testing.allocator;
421 var regex = try Regex.compile(allocator, "\\d");
421 var regex = try Regex.compile(allocator, std.testing.io, "\\d");
422422 defer regex.deinit();
423423
424424 const result = try regex.replaceAll(allocator, "a1b2c3", "");
@@ -428,7 +428,7 @@ test "stress: replaceAll removes all matches" {
428428
429429test "stress: replace with $$ escaped dollar" {
430430 const allocator = std.testing.allocator;
431 var regex = try Regex.compile(allocator, "price");
431 var regex = try Regex.compile(allocator, std.testing.io, "price");
432432 defer regex.deinit();
433433
434434 const result = try regex.replace(allocator, "the price is", "$$5");
@@ -440,7 +440,7 @@ test "stress: replace with $$ escaped dollar" {
440440
441441test "stress: split with no match returns whole string" {
442442 const allocator = std.testing.allocator;
443 var regex = try Regex.compile(allocator, ",");
443 var regex = try Regex.compile(allocator, std.testing.io, ",");
444444 defer regex.deinit();
445445
446446 const parts = try regex.split(allocator, "hello");
@@ -452,7 +452,7 @@ test "stress: split with no match returns whole string" {
452452
453453test "stress: split on every character" {
454454 const allocator = std.testing.allocator;
455 var regex = try Regex.compile(allocator, ",");
455 var regex = try Regex.compile(allocator, std.testing.io, ",");
456456 defer regex.deinit();
457457
458458 const parts = try regex.split(allocator, "a,b,c");
@@ -466,7 +466,7 @@ test "stress: split on every character" {
466466
467467test "stress: split with regex separator" {
468468 const allocator = std.testing.allocator;
469 var regex = try Regex.compile(allocator, "\\s*,\\s*");
469 var regex = try Regex.compile(allocator, std.testing.io, "\\s*,\\s*");
470470 defer regex.deinit();
471471
472472 const parts = try regex.split(allocator, "a , b , c");
@@ -482,7 +482,7 @@ test "stress: split with regex separator" {
482482
483483test "stress: escaped special characters" {
484484 const allocator = std.testing.allocator;
485 var regex = try Regex.compile(allocator, "\\(\\)\\[\\]\\{\\}");
485 var regex = try Regex.compile(allocator, std.testing.io, "\\(\\)\\[\\]\\{\\}");
486486 defer regex.deinit();
487487
488488 try std.testing.expect(try regex.isMatch("()[]{}"));
@@ -491,7 +491,7 @@ test "stress: escaped special characters" {
491491
492492test "stress: escaped dot matches literal dot" {
493493 const allocator = std.testing.allocator;
494 var regex = try Regex.compile(allocator, "a\\.b");
494 var regex = try Regex.compile(allocator, std.testing.io, "a\\.b");
495495 defer regex.deinit();
496496
497497 try std.testing.expect(try regex.isMatch("a.b"));
@@ -500,7 +500,7 @@ test "stress: escaped dot matches literal dot" {
500500
501501test "stress: escaped backslash" {
502502 const allocator = std.testing.allocator;
503 var regex = try Regex.compile(allocator, "\\\\");
503 var regex = try Regex.compile(allocator, std.testing.io, "\\\\");
504504 defer regex.deinit();
505505
506506 try std.testing.expect(try regex.isMatch("\\"));
@@ -511,7 +511,7 @@ test "stress: escaped backslash" {
511511
512512test "stress: match at end of long input" {
513513 const allocator = std.testing.allocator;
514 var regex = try Regex.compile(allocator, "needle");
514 var regex = try Regex.compile(allocator, std.testing.io, "needle");
515515 defer regex.deinit();
516516
517517 // Build a long haystack with needle at the very end
@@ -531,7 +531,7 @@ test "stress: match at end of long input" {
531531
532532test "stress: no match in long input" {
533533 const allocator = std.testing.allocator;
534 var regex = try Regex.compile(allocator, "needle");
534 var regex = try Regex.compile(allocator, std.testing.io, "needle");
535535 defer regex.deinit();
536536
537537 var buf: [1024]u8 = undefined;
@@ -544,7 +544,7 @@ test "stress: no match in long input" {
544544
545545test "stress: multiline ^ matches after each newline" {
546546 const allocator = std.testing.allocator;
547 var regex = try Regex.compileWithFlags(allocator, "^\\w+", .{ .multiline = true });
547 var regex = try Regex.compileWithFlags(allocator, std.testing.io, "^\\w+", .{ .multiline = true });
548548 defer regex.deinit();
549549
550550 const matches = try regex.findAll(allocator, "hello\nworld\nfoo");
@@ -567,7 +567,7 @@ test "stress: dot does not match newline by default - find first line" {
567567 // Without multiline, $ only matches at end of input
568568 // So .+ matches "hello" but $ doesn't match at position 5
569569 // Use multiline to match lines, or just test .+ without $
570 var regex = try Regex.compile(allocator, ".+");
570 var regex = try Regex.compile(allocator, std.testing.io, ".+");
571571 defer regex.deinit();
572572
573573 if (try regex.find("hello\nworld")) |match| {
@@ -582,7 +582,7 @@ test "stress: dot does not match newline by default - find first line" {
582582
583583test "stress: dot_all makes dot match newline" {
584584 const allocator = std.testing.allocator;
585 var regex = try Regex.compileWithFlags(allocator, "^.+$", .{ .dot_all = true });
585 var regex = try Regex.compileWithFlags(allocator, std.testing.io, "^.+$", .{ .dot_all = true });
586586 defer regex.deinit();
587587
588588 if (try regex.find("hello\nworld")) |match| {
@@ -598,7 +598,7 @@ test "stress: dot_all makes dot match newline" {
598598
599599test "stress: case insensitive literal" {
600600 const allocator = std.testing.allocator;
601 var regex = try Regex.compileWithFlags(allocator, "hello", .{ .case_insensitive = true });
601 var regex = try Regex.compileWithFlags(allocator, std.testing.io, "hello", .{ .case_insensitive = true });
602602 defer regex.deinit();
603603
604604 try std.testing.expect(try regex.isMatch("HELLO"));
@@ -610,38 +610,38 @@ test "stress: case insensitive literal" {
610610
611611test "stress: unmatched closing paren" {
612612 const allocator = std.testing.allocator;
613 const result = Regex.compile(allocator, "abc)");
613 const result = Regex.compile(allocator, std.testing.io, "abc)");
614614 try std.testing.expectError(RegexError.UnmatchedParenthesis, result);
615615}
616616
617617test "stress: unmatched opening paren" {
618618 const allocator = std.testing.allocator;
619 const result = Regex.compile(allocator, "(abc");
619 const result = Regex.compile(allocator, std.testing.io, "(abc");
620620 try std.testing.expectError(RegexError.UnexpectedCharacter, result);
621621}
622622
623623test "stress: unmatched bracket" {
624624 const allocator = std.testing.allocator;
625 const result = Regex.compile(allocator, "[abc");
625 const result = Regex.compile(allocator, std.testing.io, "[abc");
626626 try std.testing.expectError(RegexError.UnexpectedCharacter, result);
627627}
628628
629629test "stress: quantifier star at start" {
630630 const allocator = std.testing.allocator;
631 const result = Regex.compile(allocator, "*abc");
631 const result = Regex.compile(allocator, std.testing.io, "*abc");
632632 try std.testing.expectError(RegexError.UnexpectedCharacter, result);
633633}
634634
635635test "stress: quantifier plus at start" {
636636 const allocator = std.testing.allocator;
637 const result = Regex.compile(allocator, "+abc");
637 const result = Regex.compile(allocator, std.testing.io, "+abc");
638638 try std.testing.expectError(RegexError.UnexpectedCharacter, result);
639639}
640640
641641test "stress: empty character class" {
642642 const allocator = std.testing.allocator;
643643 // [] followed by ] - parser sees empty class then stray ]
644 if (Regex.compile(allocator, "[]")) |*r| {
644 if (Regex.compile(allocator, std.testing.io, "[]")) |*r| {
645645 var mut_r = r.*;
646646 mut_r.deinit();
647647 } else |_| {
@@ -653,7 +653,7 @@ test "stress: empty character class" {
653653
654654test "stress: greedy star matches longest" {
655655 const allocator = std.testing.allocator;
656 var regex = try Regex.compile(allocator, "a.*b");
656 var regex = try Regex.compile(allocator, std.testing.io, "a.*b");
657657 defer regex.deinit();
658658
659659 if (try regex.find("aXXbYYb")) |match| {
@@ -669,7 +669,7 @@ test "stress: greedy star matches longest" {
669669test "stress: complex pattern with multiple features" {
670670 const allocator = std.testing.allocator;
671671 // Email-like pattern with captures
672 var regex = try Regex.compile(allocator, "([a-zA-Z0-9.]+)@([a-zA-Z0-9]+)\\.([a-zA-Z]{2,})");
672 var regex = try Regex.compile(allocator, std.testing.io, "([a-zA-Z0-9.]+)@([a-zA-Z0-9]+)\\.([a-zA-Z]{2,})");
673673 defer regex.deinit();
674674
675675 if (try regex.find("contact: user.name@example.com today")) |match| {
@@ -692,7 +692,7 @@ test "stress: compile many patterns sequentially" {
692692
693693 var i: usize = 0;
694694 while (i < 100) : (i += 1) {
695 var regex = try Regex.compile(allocator, "test\\d+");
695 var regex = try Regex.compile(allocator, std.testing.io, "test\\d+");
696696 defer regex.deinit();
697697 try std.testing.expect(try regex.isMatch("test123"));
698698 }