re2 2.23.0 → 2.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,6 +39,77 @@ RSpec.describe RE2::Regexp do
39
39
 
40
40
  expect(re).to be_a(RE2::Regexp)
41
41
  end
42
+
43
+ it "returns a frozen object" do
44
+ expect(RE2::Regexp.new('woo')).to be_frozen
45
+ end
46
+
47
+ it "cannot be re-initialized" do
48
+ re = RE2::Regexp.new('woo')
49
+
50
+ expect { re.send(:initialize, 'bar') }.to raise_error(FrozenError)
51
+ end
52
+ end
53
+
54
+ describe "#dup" do
55
+ it "returns a copy with the same pattern" do
56
+ re = described_class.new('(\d+)')
57
+ copy = re.dup
58
+
59
+ expect(copy.to_s).to eq('(\d+)')
60
+ end
61
+
62
+ it "returns a different object" do
63
+ re = described_class.new('(\d+)')
64
+ copy = re.dup
65
+
66
+ expect(copy).to_not equal(re)
67
+ end
68
+
69
+ it "returns a valid copy" do
70
+ re = described_class.new('(\d+)')
71
+ copy = re.dup
72
+
73
+ expect(copy.ok?).to eq(true)
74
+ end
75
+
76
+ it "copies options from the original" do
77
+ re = described_class.new('(\d+)', case_sensitive: false)
78
+ copy = re.dup
79
+
80
+ expect(copy).to_not be_case_sensitive
81
+ end
82
+
83
+ it "returns a frozen copy" do
84
+ re = described_class.new('(\d+)')
85
+ copy = re.dup
86
+
87
+ expect(copy).to be_frozen
88
+ end
89
+
90
+ it "raises an error when called on an uninitialized object" do
91
+ expect { described_class.allocate.dup }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
92
+ end
93
+ end
94
+
95
+ describe "#clone" do
96
+ it "returns a copy with the same pattern" do
97
+ re = described_class.new('woo')
98
+ copy = re.clone
99
+
100
+ expect(copy.to_s).to eq('woo')
101
+ end
102
+
103
+ it "returns a frozen copy" do
104
+ re = described_class.new('woo')
105
+ copy = re.clone
106
+
107
+ expect(copy).to be_frozen
108
+ end
109
+
110
+ it "raises an error when called on an uninitialized object" do
111
+ expect { described_class.allocate.clone }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
112
+ end
42
113
  end
43
114
 
44
115
  describe ".compile" do
@@ -102,6 +173,10 @@ RSpec.describe RE2::Regexp do
102
173
 
103
174
  expect(options).to include(case_sensitive: false)
104
175
  end
176
+
177
+ it "raises an error when called on an uninitialized object" do
178
+ expect { described_class.allocate.options }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
179
+ end
105
180
  end
106
181
 
107
182
  describe "#error" do
@@ -117,6 +192,10 @@ RSpec.describe RE2::Regexp do
117
192
 
118
193
  expect(error).to eq("missing ): wo(o")
119
194
  end
195
+
196
+ it "raises an error when called on an uninitialized object" do
197
+ expect { described_class.allocate.error }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
198
+ end
120
199
  end
121
200
 
122
201
  describe "#error_arg" do
@@ -131,6 +210,10 @@ RSpec.describe RE2::Regexp do
131
210
 
132
211
  expect(error_arg).to eq("wo(o")
133
212
  end
213
+
214
+ it "raises an error when called on an uninitialized object" do
215
+ expect { described_class.allocate.error_arg }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
216
+ end
134
217
  end
135
218
 
136
219
  describe "#program_size" do
@@ -145,6 +228,10 @@ RSpec.describe RE2::Regexp do
145
228
 
146
229
  expect(program_size).to eq(-1)
147
230
  end
231
+
232
+ it "raises an error when called on an uninitialized object" do
233
+ expect { described_class.allocate.program_size }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
234
+ end
148
235
  end
149
236
 
150
237
  describe "#to_str" do
@@ -159,6 +246,10 @@ RSpec.describe RE2::Regexp do
159
246
 
160
247
  expect(string).to eq("???")
161
248
  end
249
+
250
+ it "raises an error when called on an uninitialized object" do
251
+ expect { described_class.allocate.to_str }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
252
+ end
162
253
  end
163
254
 
164
255
  describe "#pattern" do
@@ -173,6 +264,10 @@ RSpec.describe RE2::Regexp do
173
264
 
174
265
  expect(pattern).to eq("???")
175
266
  end
267
+
268
+ it "raises an error when called on an uninitialized object" do
269
+ expect { described_class.allocate.pattern }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
270
+ end
176
271
  end
177
272
 
178
273
  describe "#inspect" do
@@ -187,6 +282,10 @@ RSpec.describe RE2::Regexp do
187
282
 
188
283
  expect(string.encoding).to eq(Encoding::ISO_8859_1)
189
284
  end
285
+
286
+ it "raises an error when called on an uninitialized object" do
287
+ expect { described_class.allocate.inspect }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
288
+ end
190
289
  end
191
290
 
192
291
  describe "#utf8?" do
@@ -199,6 +298,10 @@ RSpec.describe RE2::Regexp do
199
298
 
200
299
  expect(re).to_not be_utf8
201
300
  end
301
+
302
+ it "raises an error when called on an uninitialized object" do
303
+ expect { described_class.allocate.utf8? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
304
+ end
202
305
  end
203
306
 
204
307
  describe "#posix_syntax?" do
@@ -211,6 +314,10 @@ RSpec.describe RE2::Regexp do
211
314
 
212
315
  expect(re).to be_posix_syntax
213
316
  end
317
+
318
+ it "raises an error when called on an uninitialized object" do
319
+ expect { described_class.allocate.posix_syntax? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
320
+ end
214
321
  end
215
322
 
216
323
  describe "#literal?" do
@@ -223,6 +330,10 @@ RSpec.describe RE2::Regexp do
223
330
 
224
331
  expect(re).to be_literal
225
332
  end
333
+
334
+ it "raises an error when called on an uninitialized object" do
335
+ expect { described_class.allocate.literal? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
336
+ end
226
337
  end
227
338
 
228
339
  describe "#never_nl?" do
@@ -235,6 +346,10 @@ RSpec.describe RE2::Regexp do
235
346
 
236
347
  expect(re).to be_never_nl
237
348
  end
349
+
350
+ it "raises an error when called on an uninitialized object" do
351
+ expect { described_class.allocate.never_nl? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
352
+ end
238
353
  end
239
354
 
240
355
  describe "#case_sensitive?" do
@@ -246,6 +361,10 @@ RSpec.describe RE2::Regexp do
246
361
  re = RE2::Regexp.new('woo', case_sensitive: false)
247
362
  expect(re).to_not be_case_sensitive
248
363
  end
364
+
365
+ it "raises an error when called on an uninitialized object" do
366
+ expect { described_class.allocate.case_sensitive? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
367
+ end
249
368
  end
250
369
 
251
370
  describe "#case_insensitive?" do
@@ -258,6 +377,10 @@ RSpec.describe RE2::Regexp do
258
377
 
259
378
  expect(re).to be_case_insensitive
260
379
  end
380
+
381
+ it "raises an error when called on an uninitialized object" do
382
+ expect { described_class.allocate.case_insensitive? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
383
+ end
261
384
  end
262
385
 
263
386
  describe "#casefold?" do
@@ -270,6 +393,10 @@ RSpec.describe RE2::Regexp do
270
393
 
271
394
  expect(re).to be_casefold
272
395
  end
396
+
397
+ it "raises an error when called on an uninitialized object" do
398
+ expect { described_class.allocate.casefold? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
399
+ end
273
400
  end
274
401
 
275
402
  describe "#longest_match?" do
@@ -282,6 +409,10 @@ RSpec.describe RE2::Regexp do
282
409
 
283
410
  expect(re).to be_longest_match
284
411
  end
412
+
413
+ it "raises an error when called on an uninitialized object" do
414
+ expect { described_class.allocate.longest_match? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
415
+ end
285
416
  end
286
417
 
287
418
  describe "#log_errors?" do
@@ -294,6 +425,10 @@ RSpec.describe RE2::Regexp do
294
425
 
295
426
  expect(re).to_not be_log_errors
296
427
  end
428
+
429
+ it "raises an error when called on an uninitialized object" do
430
+ expect { described_class.allocate.log_errors? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
431
+ end
297
432
  end
298
433
 
299
434
  describe "#perl_classes?" do
@@ -306,6 +441,10 @@ RSpec.describe RE2::Regexp do
306
441
 
307
442
  expect(re).to be_perl_classes
308
443
  end
444
+
445
+ it "raises an error when called on an uninitialized object" do
446
+ expect { described_class.allocate.perl_classes? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
447
+ end
309
448
  end
310
449
 
311
450
  describe "#word_boundary?" do
@@ -318,6 +457,10 @@ RSpec.describe RE2::Regexp do
318
457
 
319
458
  expect(re).to be_word_boundary
320
459
  end
460
+
461
+ it "raises an error when called on an uninitialized object" do
462
+ expect { described_class.allocate.word_boundary? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
463
+ end
321
464
  end
322
465
 
323
466
  describe "#one_line?" do
@@ -330,6 +473,10 @@ RSpec.describe RE2::Regexp do
330
473
 
331
474
  expect(re).to be_one_line
332
475
  end
476
+
477
+ it "raises an error when called on an uninitialized object" do
478
+ expect { described_class.allocate.one_line? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
479
+ end
333
480
  end
334
481
 
335
482
  describe "#max_mem" do
@@ -342,6 +489,10 @@ RSpec.describe RE2::Regexp do
342
489
 
343
490
  expect(re.max_mem).to eq(1024)
344
491
  end
492
+
493
+ it "raises an error when called on an uninitialized object" do
494
+ expect { described_class.allocate.max_mem }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
495
+ end
345
496
  end
346
497
 
347
498
  describe "#match" do
@@ -463,6 +614,24 @@ RSpec.describe RE2::Regexp do
463
614
  expect { re.match("one two three", endpos: 3) }.to raise_error(RE2::Regexp::UnsupportedError)
464
615
  end
465
616
 
617
+ it "does not truncate startpos to 32 bits" do
618
+ skip "Underlying RE2::Match does not have endpos argument" unless RE2::Regexp.match_has_endpos_argument?
619
+ skip "size_t is not larger than a 32-bit int" if RbConfig::SIZEOF.fetch("size_t") <= (32 / 8)
620
+
621
+ re = RE2::Regexp.new('(\w+)', log_errors: false)
622
+
623
+ expect(re.match("one two three", startpos: 2_147_483_648, endpos: 2_147_483_649)).to be_nil
624
+ end
625
+
626
+ it "does not truncate endpos to 32 bits" do
627
+ skip "Underlying RE2::Match does not have endpos argument" unless RE2::Regexp.match_has_endpos_argument?
628
+ skip "size_t is not larger than a 32-bit int" if RbConfig::SIZEOF.fetch("size_t") <= (32 / 8)
629
+
630
+ re = RE2::Regexp.new('(\w+)', log_errors: false)
631
+
632
+ expect(re.match("one two three", endpos: 2_147_483_648)).to be_nil
633
+ end
634
+
466
635
  it "does not anchor matches by default when extracting submatches" do
467
636
  re = RE2::Regexp.new('(two)')
468
637
 
@@ -596,7 +765,6 @@ RSpec.describe RE2::Regexp do
596
765
 
597
766
  it "raises an exception if given too large a number of submatches instead of options" do
598
767
  re = RE2::Regexp.new('(\w+) (\w+) (\w+)')
599
- md = re.match("one two three", 2)
600
768
 
601
769
  expect { re.match("one two three", INT_MAX) }.to raise_error(RangeError, "number of matches should be < #{INT_MAX}")
602
770
  end
@@ -612,6 +780,29 @@ RSpec.describe RE2::Regexp do
612
780
 
613
781
  expect(re.match("one two three", nil)).to be_a(RE2::MatchData)
614
782
  end
783
+
784
+ it "raises an error when startpos exceeds INT_MAX on old RE2 ABI" do
785
+ skip "Underlying RE2::Match does not take int startpos" if RE2::Regexp.match_has_endpos_argument?
786
+ skip "size_t is not larger than a 32-bit int" if RbConfig::SIZEOF.fetch("size_t") <= (32 / 8)
787
+
788
+ re = RE2::Regexp.new('(\w+)', log_errors: false)
789
+
790
+ expect { re.match("test", start_pos: 2_147_483_648) }.to raise_error(RangeError, /startpos should be <=/)
791
+ end
792
+
793
+ it "raises an error when called on an uninitialized object" do
794
+ expect { described_class.allocate.match("test") }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
795
+ end
796
+
797
+ it "can be run concurrently" do
798
+ re = RE2::Regexp.new('(\w+)\s(\w+)')
799
+
800
+ threads = 10.times.map do
801
+ Thread.new { re.match("one two").values_at(1, 2) }
802
+ end
803
+
804
+ expect(threads.map(&:value)).to all(eq(["one", "two"]))
805
+ end
615
806
  end
616
807
 
617
808
  describe "#match?" do
@@ -633,6 +824,20 @@ RSpec.describe RE2::Regexp do
633
824
 
634
825
  expect { re.match?(0) }.to raise_error(TypeError)
635
826
  end
827
+
828
+ it "raises an error when called on an uninitialized object" do
829
+ expect { described_class.allocate.match?("test") }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
830
+ end
831
+
832
+ it "can be run concurrently" do
833
+ re = RE2::Regexp.new('(\w+)\s(\w+)')
834
+
835
+ threads = 10.times.map do
836
+ Thread.new { re.match?("one two") }
837
+ end
838
+
839
+ expect(threads.map(&:value)).to all(eq(true))
840
+ end
636
841
  end
637
842
 
638
843
  describe "#partial_match?" do
@@ -661,6 +866,20 @@ RSpec.describe RE2::Regexp do
661
866
 
662
867
  expect { re.partial_match?(0) }.to raise_error(TypeError)
663
868
  end
869
+
870
+ it "raises an error when called on an uninitialized object" do
871
+ expect { described_class.allocate.partial_match?("test") }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
872
+ end
873
+
874
+ it "can be run concurrently" do
875
+ re = RE2::Regexp.new('(\d+)')
876
+
877
+ threads = 10.times.map do
878
+ Thread.new { re.partial_match?("alice 123") }
879
+ end
880
+
881
+ expect(threads.map(&:value)).to all(eq(true))
882
+ end
664
883
  end
665
884
 
666
885
  describe "#=~" do
@@ -689,6 +908,10 @@ RSpec.describe RE2::Regexp do
689
908
 
690
909
  expect { re =~ 0 }.to raise_error(TypeError)
691
910
  end
911
+
912
+ it "raises an error when called on an uninitialized object" do
913
+ expect { described_class.allocate =~ "test" }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
914
+ end
692
915
  end
693
916
 
694
917
  describe "#===" do
@@ -710,6 +933,10 @@ RSpec.describe RE2::Regexp do
710
933
 
711
934
  expect { re === 0 }.to raise_error(TypeError)
712
935
  end
936
+
937
+ it "raises an error when called on an uninitialized object" do
938
+ expect { described_class.allocate === "test" }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
939
+ end
713
940
  end
714
941
 
715
942
  describe "#full_match?" do
@@ -738,6 +965,20 @@ RSpec.describe RE2::Regexp do
738
965
 
739
966
  expect { re.full_match?(0) }.to raise_error(TypeError)
740
967
  end
968
+
969
+ it "raises an error when called on an uninitialized object" do
970
+ expect { described_class.allocate.full_match?("test") }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
971
+ end
972
+
973
+ it "can be run concurrently" do
974
+ re = RE2::Regexp.new('(\w+) (\d+)')
975
+
976
+ threads = 10.times.map do
977
+ Thread.new { re.full_match?("alice 123") }
978
+ end
979
+
980
+ expect(threads.map(&:value)).to all(eq(true))
981
+ end
741
982
  end
742
983
 
743
984
  describe "#ok?" do
@@ -752,6 +993,10 @@ RSpec.describe RE2::Regexp do
752
993
  expect(RE2::Regexp.new('wo[o', log_errors: false)).to_not be_ok
753
994
  expect(RE2::Regexp.new('*', log_errors: false)).to_not be_ok
754
995
  end
996
+
997
+ it "raises an error when called on an uninitialized object" do
998
+ expect { described_class.allocate.ok? }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
999
+ end
755
1000
  end
756
1001
 
757
1002
  describe ".escape" do
@@ -776,6 +1021,10 @@ RSpec.describe RE2::Regexp do
776
1021
  it "returns -1 for an invalid pattern" do
777
1022
  expect(RE2::Regexp.new('???', log_errors: false).number_of_capturing_groups).to eq(-1)
778
1023
  end
1024
+
1025
+ it "raises an error when called on an uninitialized object" do
1026
+ expect { described_class.allocate.number_of_capturing_groups }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
1027
+ end
779
1028
  end
780
1029
 
781
1030
  describe "#named_capturing_groups" do
@@ -798,6 +1047,68 @@ RSpec.describe RE2::Regexp do
798
1047
  it "returns an empty hash for an invalid regexp" do
799
1048
  expect(RE2::Regexp.new('???', log_errors: false).named_capturing_groups).to be_empty
800
1049
  end
1050
+
1051
+ it "raises an error when called on an uninitialized object" do
1052
+ expect { described_class.allocate.named_capturing_groups }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
1053
+ end
1054
+ end
1055
+
1056
+ describe "#names" do
1057
+ it "returns an array of names of named capturing groups" do
1058
+ expect(RE2::Regexp.new('(?P<bob>a)(?P<rob>b)').names).to eq(["bob", "rob"])
1059
+ end
1060
+
1061
+ it "returns an empty array if there are no named capturing groups" do
1062
+ expect(RE2::Regexp.new('(a)(b)').names).to be_empty
1063
+ end
1064
+
1065
+ it "returns an empty array for a pattern with no capturing groups" do
1066
+ expect(RE2::Regexp.new('ab').names).to be_empty
1067
+ end
1068
+
1069
+ it "returns an empty array for an invalid regexp" do
1070
+ expect(RE2::Regexp.new('???', log_errors: false).names).to be_empty
1071
+ end
1072
+
1073
+ it "returns UTF-8 strings if the pattern is UTF-8" do
1074
+ names = RE2::Regexp.new('(?P<bob>a)').names
1075
+
1076
+ expect(names.first.encoding).to eq(Encoding::UTF_8)
1077
+ end
1078
+
1079
+ it "returns ISO-8859-1 strings if the pattern is not UTF-8" do
1080
+ names = RE2::Regexp.new('(?P<bob>a)', utf8: false).names
1081
+
1082
+ expect(names.first.encoding).to eq(Encoding::ISO_8859_1)
1083
+ end
1084
+
1085
+ it "raises an error when called on an uninitialized object" do
1086
+ expect { described_class.allocate.names }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
1087
+ end
1088
+ end
1089
+
1090
+ describe "#named_captures" do
1091
+ it "returns a hash of names to indices" do
1092
+ expect(RE2::Regexp.new('(?P<bob>a)').named_captures).to eq("bob" => 1)
1093
+ end
1094
+
1095
+ it "maps names to indices with several groups" do
1096
+ groups = RE2::Regexp.new('(?P<bob>a)(o)(?P<rob>e)').named_captures
1097
+
1098
+ expect(groups).to eq("bob" => 1, "rob" => 3)
1099
+ end
1100
+
1101
+ it "returns an empty hash for a pattern with no named groups" do
1102
+ expect(RE2::Regexp.new('(a)(b)').named_captures).to be_empty
1103
+ end
1104
+
1105
+ it "returns an empty hash for an invalid regexp" do
1106
+ expect(RE2::Regexp.new('???', log_errors: false).named_captures).to be_empty
1107
+ end
1108
+
1109
+ it "raises an error when called on an uninitialized object" do
1110
+ expect { described_class.allocate.named_captures }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
1111
+ end
801
1112
  end
802
1113
 
803
1114
  describe "#scan" do
@@ -813,6 +1124,10 @@ RSpec.describe RE2::Regexp do
813
1124
 
814
1125
  expect { r.scan(nil) }.to raise_error(TypeError)
815
1126
  end
1127
+
1128
+ it "raises an error when called on an uninitialized object" do
1129
+ expect { described_class.allocate.scan("test") }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
1130
+ end
816
1131
  end
817
1132
 
818
1133
  describe "#partial_match" do
@@ -868,6 +1183,10 @@ RSpec.describe RE2::Regexp do
868
1183
 
869
1184
  expect(r.partial_match('ruby:1234', anchor: :anchor_both)).to be_a(RE2::MatchData)
870
1185
  end
1186
+
1187
+ it "raises an error when called on an uninitialized object" do
1188
+ expect { described_class.allocate.partial_match('test') }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
1189
+ end
871
1190
  end
872
1191
 
873
1192
  describe "#full_match" do
@@ -924,5 +1243,9 @@ RSpec.describe RE2::Regexp do
924
1243
 
925
1244
  expect(r.full_match('ruby:1234', anchor: :unanchored)).to be_nil
926
1245
  end
1246
+
1247
+ it "raises an error when called on an uninitialized object" do
1248
+ expect { described_class.allocate.full_match('test') }.to raise_error(TypeError, /uninitialized RE2::Regexp/)
1249
+ end
927
1250
  end
928
1251
  end