re2 0.7.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 32a2347d40362a3014dfd03f948405964468a3c2
4
- data.tar.gz: ea15968dae15568249200c6ba91bad66d0e28f6f
3
+ metadata.gz: 118d0c677843bd7166804670d548504e6a30410b
4
+ data.tar.gz: 9efe563b54262ad28c5b71c2317b3f18117e2706
5
5
  SHA512:
6
- metadata.gz: 00588950e6c82fb5720043c04d0f833d819f3107a3c953f2284d9eaede74210c0c803f34b3e9fd89413c886fae1e4b853b5a85b18b3c2d788ff0a7e8b46036cf
7
- data.tar.gz: af2d23503d089a15ea6dd32e00bc80622cd7b0b1773ed471edcc982ac6791a6d1bf0bf5332d2440446796b5a4da15a169fd7396e3cf729af8a300e52a5985bad
6
+ metadata.gz: 07d895cafa392c75483586a37b44f57b5d5979b7473529c52eff05f3c6bccca3b11f8d406363ece9f3ab2ad02df4952031dcdb8104cdc275484666a0ceb7db01
7
+ data.tar.gz: 8147a0194f92a7850285339d9d81fe74b4865d12f67a1e64fa9db3eeec35c3adaaf4cfd97862f1d954b7b475b4dc4b0d01ef28dd10c3f39cba3338caac6ff51a
data/README.md CHANGED
@@ -4,8 +4,8 @@ re2 [![Build Status](https://travis-ci.org/mudge/re2.svg?branch=master)](http://
4
4
  A Ruby binding to [re2][], an "efficient, principled regular expression
5
5
  library".
6
6
 
7
- **Current version:** 0.7.0
8
- **Supported Ruby versions:** 1.8.7, 1.9.2, 1.9.3, 2.0.0, 2.1.0, Rubinius 2.2
7
+ **Current version:** 1.0.0
8
+ **Supported Ruby versions:** 1.8.7, 1.9.2, 1.9.3, 2.0.0, 2.1.0, 2.2, 2.3, Rubinius 2.2
9
9
 
10
10
  Installation
11
11
  ------------
@@ -21,6 +21,8 @@ If you are using Debian, you can install the [libre2-dev][] package like so:
21
21
 
22
22
  $ sudo apt-get install libre2-dev
23
23
 
24
+ Recent versions of re2 require a compiler with C++11 support such as [clang](http://clang.llvm.org/) 3.4 or [gcc](https://gcc.gnu.org/) 4.8.
25
+
24
26
  If you are using a packaged Ruby distribution, make sure you also have the
25
27
  Ruby header files installed such as those provided by the [ruby-dev][] package
26
28
  on Debian and Ubuntu.
@@ -35,14 +37,17 @@ Documentation
35
37
  Full documentation automatically generated from the latest version is
36
38
  available at <http://mudge.name/re2/>.
37
39
 
38
- Bear in mind that re2's regular expression syntax differs from PCRE, see the
39
- [official syntax page][] for more details.
40
+ Note that re2's regular expression syntax differs from PCRE and Ruby's
41
+ built-in [`Regexp`][Regexp] library, see the [official syntax page][] for more
42
+ details.
40
43
 
41
44
  Usage
42
45
  -----
43
46
 
44
- You can use re2 as a mostly drop-in replacement for Ruby's own [Regexp][] and
45
- [MatchData][] classes:
47
+ While re2 uses the same naming scheme as Ruby's built-in regular expression
48
+ library (with [`Regexp`](http://mudge.name/re2/RE2/Regexp.html) and
49
+ [`MatchData`](http://mudge.name/re2/RE2/MatchData.html)), its API is slightly
50
+ different:
46
51
 
47
52
  ```console
48
53
  $ irb -rubygems
@@ -67,9 +72,11 @@ $ irb -rubygems
67
72
  => nil
68
73
  ```
69
74
 
70
- As `RE2::Regexp.new` (or `RE2::Regexp.compile`) can be quite verbose, a helper
71
- method has been defined against `Kernel` so you can use a shorter version to
72
- create regular expressions:
75
+ As
76
+ [`RE2::Regexp.new`](http://mudge.name/re2/RE2/Regexp.html#initialize-instance_method)
77
+ (or `RE2::Regexp.compile`) can be quite verbose, a helper method has been
78
+ defined against `Kernel` so you can use a shorter version to create regular
79
+ expressions:
73
80
 
74
81
  ```console
75
82
  > RE2('(\d+)')
@@ -123,7 +130,7 @@ Features
123
130
  --------
124
131
 
125
132
  * Pre-compiling regular expressions with
126
- [`RE2::Regexp.new(re)`](http://code.google.com/p/re2/source/browse/re2/re2.h#96),
133
+ [`RE2::Regexp.new(re)`](https://github.com/google/re2/blob/2016-02-01/re2/re2.h#L100),
127
134
  `RE2::Regexp.compile(re)` or `RE2(re)` (including specifying options, e.g.
128
135
  `RE2::Regexp.new("pattern", :case_sensitive => false)`
129
136
 
@@ -152,21 +159,22 @@ Features
152
159
  `pattern.replace_all(replacement, original)`
153
160
 
154
161
  * Escaping regular expressions with
155
- [`RE2.escape(unquoted)`](http://code.google.com/p/re2/source/browse/re2/re2.h#377) and
162
+ [`RE2.escape(unquoted)`](https://github.com/google/re2/blob/2016-02-01/re2/re2.h#L418) and
156
163
  `RE2.quote(unquoted)`
157
164
 
158
165
  Contributions
159
166
  -------------
160
167
 
161
- Thanks to [Jason Woods](https://github.com/driskell) who contributed the
162
- original implementations of `RE2::MatchData#begin` and `RE2::MatchData#end`.
168
+ * Thanks to [Jason Woods](https://github.com/driskell) who contributed the
169
+ original implementations of `RE2::MatchData#begin` and `RE2::MatchData#end`;
170
+ * Thanks to [Stefano Rivera](https://github.com/stefanor) who first contributed C++11 support.
163
171
 
164
172
  Contact
165
173
  -------
166
174
 
167
175
  All feedback should go to the mailing list: <mailto:ruby.re2@librelist.com>
168
176
 
169
- [re2]: http://code.google.com/p/re2/
177
+ [re2]: https://github.com/google/re2
170
178
  [gcc]: http://gcc.gnu.org/
171
179
  [ruby-dev]: http://packages.debian.org/ruby-dev
172
180
  [build-essential]: http://packages.debian.org/build-essential
@@ -174,5 +182,5 @@ All feedback should go to the mailing list: <mailto:ruby.re2@librelist.com>
174
182
  [MatchData]: http://ruby-doc.org/core/classes/MatchData.html
175
183
  [Homebrew]: http://mxcl.github.com/homebrew
176
184
  [libre2-dev]: http://packages.debian.org/search?keywords=libre2-dev
177
- [official syntax page]: http://code.google.com/p/re2/wiki/Syntax
185
+ [official syntax page]: https://github.com/google/re2/wiki/Syntax
178
186
 
data/Rakefile CHANGED
@@ -1,15 +1,10 @@
1
1
  require 'rake/extensiontask'
2
- require 'rake/testtask'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  Rake::ExtensionTask.new('re2')
5
5
 
6
- Rake::TestTask.new do |t|
7
- t.libs << "spec"
8
- t.test_files = FileList["spec/**/*_spec.rb"]
9
- t.verbose = true
10
- end
6
+ RSpec::Core::RakeTask.new(:spec)
11
7
 
12
- task :test => :compile
13
- task :spec => :test
14
- task :default => :test
8
+ task :spec => :compile
9
+ task :default => :spec
15
10
 
@@ -10,20 +10,46 @@ incl, lib = dir_config("re2", "/usr/local/include", "/usr/local/lib")
10
10
 
11
11
  $CFLAGS << " -Wall -Wextra -funroll-loops"
12
12
 
13
+ # Pass -x c++ to force gcc to compile the test program
14
+ # as C++ (as it will end in .c by default).
15
+ compile_options = "-x c++"
16
+
13
17
  have_library("stdc++")
14
18
  have_header("stdint.h")
15
19
  have_func("rb_str_sublen")
16
20
 
17
- if have_library("re2")
21
+ unless have_library("re2")
22
+ abort "You must have re2 installed and specified with --with-re2-dir, please see https://github.com/google/re2/wiki/Install"
23
+ end
18
24
 
19
- # Determine which version of re2 the user has installed.
20
- # Revision d9f8806c004d added an `endpos` argument to the
21
- # generic Match() function.
22
- #
23
- # To test for this, try to compile a simple program that uses
24
- # the newer form of Match() and set a flag if it is successful.
25
- checking_for("RE2::Match() with endpos argument") do
26
- test_re2_match_signature = <<SRC
25
+ # Recent versions of re2 now require a compiler with C++11 support
26
+ checking_for("re2 requires C++11 compiler") do
27
+ minimal_program = <<SRC
28
+ #include <re2/re2.h>
29
+ int main() { return 0; }
30
+ SRC
31
+
32
+ unless try_compile(minimal_program, compile_options)
33
+ if try_compile(minimal_program, compile_options + " -std=c++11")
34
+ compile_options << " -std=c++11"
35
+ $CPPFLAGS << " -std=c++11"
36
+ elsif try_compile(minimal_program, compile_options + " -std=c++0x")
37
+ compile_options << " -std=c++0x"
38
+ $CPPFLAGS << " -std=c++0x"
39
+ else
40
+ abort "Cannot compile re2 with your compiler: recent versions require C++11 support."
41
+ end
42
+ end
43
+ end
44
+
45
+ # Determine which version of re2 the user has installed.
46
+ # Revision d9f8806c004d added an `endpos` argument to the
47
+ # generic Match() function.
48
+ #
49
+ # To test for this, try to compile a simple program that uses
50
+ # the newer form of Match() and set a flag if it is successful.
51
+ checking_for("RE2::Match() with endpos argument") do
52
+ test_re2_match_signature = <<SRC
27
53
  #include <re2/re2.h>
28
54
 
29
55
  int main() {
@@ -35,14 +61,9 @@ int main() {
35
61
  }
36
62
  SRC
37
63
 
38
- # Pass -x c++ to force gcc to compile the test program
39
- # as C++ (as it will end in .c by default).
40
- if try_compile(test_re2_match_signature, "-x c++")
41
- $defs.push("-DHAVE_ENDPOS_ARGUMENT")
42
- end
64
+ if try_compile(test_re2_match_signature, compile_options)
65
+ $defs.push("-DHAVE_ENDPOS_ARGUMENT")
43
66
  end
44
-
45
- create_makefile("re2")
46
- else
47
- abort "You must have re2 installed and specified with --with-re2-dir, please see http://code.google.com/p/re2/wiki/Install"
48
67
  end
68
+
69
+ create_makefile("re2")
@@ -6,8 +6,8 @@
6
6
  * Released under the BSD Licence, please see LICENSE.txt
7
7
  */
8
8
 
9
- #include <re2/re2.h>
10
9
  #include <ruby.h>
10
+ #include <re2/re2.h>
11
11
  #include <stdint.h>
12
12
  #include <string>
13
13
  #include <sstream>
@@ -1,15 +1,13 @@
1
- require "spec_helper"
2
-
3
- describe Kernel do
1
+ RSpec.describe Kernel do
4
2
  describe "#RE2" do
5
3
  it "returns an RE2::Regexp instance given a pattern" do
6
- RE2('w(o)(o)').must_be_instance_of(RE2::Regexp)
4
+ expect(RE2('w(o)(o)')).to be_a(RE2::Regexp)
7
5
  end
8
6
 
9
7
  it "returns an RE2::Regexp instance given a pattern and options" do
10
8
  re = RE2('w(o)(o)', :case_sensitive => false)
11
- re.must_be_instance_of(RE2::Regexp)
12
- re.wont_be(:case_sensitive?)
9
+ expect(re).to be_a(RE2::Regexp)
10
+ expect(re).to_not be_case_sensitive
13
11
  end
14
12
  end
15
13
  end
@@ -1,94 +1,90 @@
1
1
  # encoding: utf-8
2
-
3
- require "spec_helper"
4
-
5
- describe RE2::MatchData do
6
-
2
+ RSpec.describe RE2::MatchData do
7
3
  describe "#to_a" do
8
4
  it "is populated with the match and capturing groups" do
9
5
  a = RE2::Regexp.new('w(o)(o)').match('woo').to_a
10
- a.must_equal(["woo", "o", "o"])
6
+ expect(a).to eq(["woo", "o", "o"])
11
7
  end
12
8
 
13
9
  it "populates optional capturing groups with nil if they are missing" do
14
10
  a = RE2::Regexp.new('(\d?)(a)(b)').match('ab').to_a
15
- a.must_equal(["ab", nil, "a", "b"])
11
+ expect(a).to eq(["ab", nil, "a", "b"])
16
12
  end
17
13
  end
18
14
 
19
15
  describe "#[]" do
20
16
  it "accesses capturing groups by numerical index" do
21
17
  md = RE2::Regexp.new('(\d)(\d{2})').match("123")
22
- md[1].must_equal("1")
23
- md[2].must_equal("23")
18
+ expect(md[1]).to eq("1")
19
+ expect(md[2]).to eq("23")
24
20
  end
25
21
 
26
22
  it "has the whole match as the 0th item" do
27
23
  md = RE2::Regexp.new('(\d)(\d{2})').match("123")
28
- md[0].must_equal("123")
24
+ expect(md[0]).to eq("123")
29
25
  end
30
26
 
31
27
  it "supports access by numerical ranges" do
32
28
  md = RE2::Regexp.new('(\d+) (\d+) (\d+)').match("123 456 789")
33
- md[1..3].must_equal(["123", "456", "789"])
34
- md[1...3].must_equal(["123", "456"])
29
+ expect(md[1..3]).to eq(["123", "456", "789"])
30
+ expect(md[1...3]).to eq(["123", "456"])
35
31
  end
36
32
 
37
33
  it "supports slicing" do
38
34
  md = RE2::Regexp.new('(\d+) (\d+) (\d+)').match("123 456 789")
39
- md[1, 3].must_equal(["123", "456", "789"])
40
- md[1, 2].must_equal(["123", "456"])
35
+ expect(md[1, 3]).to eq(["123", "456", "789"])
36
+ expect(md[1, 2]).to eq(["123", "456"])
41
37
  end
42
38
 
43
39
  it "returns nil if attempting to access non-existent capturing groups by index" do
44
40
  md = RE2::Regexp.new('(\d+)').match('bob 123')
45
- md[2].must_be_nil
46
- md[3].must_be_nil
41
+ expect(md[2]).to be_nil
42
+ expect(md[3]).to be_nil
47
43
  end
48
44
 
49
45
  it "allows access by string names when there are named groups" do
50
46
  md = RE2::Regexp.new('(?P<numbers>\d+)').match('bob 123')
51
- md["numbers"].must_equal("123")
47
+ expect(md["numbers"]).to eq("123")
52
48
  end
53
49
 
54
50
  it "allows access by symbol names when there are named groups" do
55
51
  md = RE2::Regexp.new('(?P<numbers>\d+)').match('bob 123')
56
- md[:numbers].must_equal("123")
52
+ expect(md[:numbers]).to eq("123")
57
53
  end
58
54
 
59
55
  it "allows access by names and indices with mixed groups" do
60
56
  md = RE2::Regexp.new('(?P<name>\w+)(\s*)(?P<numbers>\d+)').match("bob 123")
61
- md["name"].must_equal("bob")
62
- md[:name].must_equal("bob")
63
- md[2].must_equal(" ")
64
- md["numbers"].must_equal("123")
65
- md[:numbers].must_equal("123")
57
+ expect(md["name"]).to eq("bob")
58
+ expect(md[:name]).to eq("bob")
59
+ expect(md[2]).to eq(" ")
60
+ expect(md["numbers"]).to eq("123")
61
+ expect(md[:numbers]).to eq("123")
66
62
  end
67
63
 
68
64
  it "returns nil if no such named group exists" do
69
65
  md = RE2::Regexp.new('(\d+)').match("bob 123")
70
- md["missing"].must_be_nil
71
- md[:missing].must_be_nil
66
+ expect(md["missing"]).to be_nil
67
+ expect(md[:missing]).to be_nil
72
68
  end
73
69
 
74
70
  it "raises an error if given an inappropriate index" do
75
71
  md = RE2::Regexp.new('(\d+)').match("bob 123")
76
- lambda { md[nil] }.must_raise(TypeError)
72
+ expect { md[nil] }.to raise_error(TypeError)
77
73
  end
78
74
 
79
75
  if String.method_defined?(:encoding)
80
76
  it "returns UTF-8 encoded strings by default" do
81
77
  md = RE2::Regexp.new('(?P<name>\S+)').match("bob")
82
- md[0].encoding.name.must_equal("UTF-8")
83
- md["name"].encoding.name.must_equal("UTF-8")
84
- md[:name].encoding.name.must_equal("UTF-8")
78
+ expect(md[0].encoding.name).to eq("UTF-8")
79
+ expect(md["name"].encoding.name).to eq("UTF-8")
80
+ expect(md[:name].encoding.name).to eq("UTF-8")
85
81
  end
86
82
 
87
83
  it "returns Latin 1 strings encoding when utf-8 is false" do
88
84
  md = RE2::Regexp.new('(?P<name>\S+)', :utf8 => false).match('bob')
89
- md[0].encoding.name.must_equal("ISO-8859-1")
90
- md["name"].encoding.name.must_equal("ISO-8859-1")
91
- md[:name].encoding.name.must_equal("ISO-8859-1")
85
+ expect(md[0].encoding.name).to eq("ISO-8859-1")
86
+ expect(md["name"].encoding.name).to eq("ISO-8859-1")
87
+ expect(md[:name].encoding.name).to eq("ISO-8859-1")
92
88
  end
93
89
  end
94
90
  end
@@ -96,32 +92,32 @@ describe RE2::MatchData do
96
92
  describe "#string" do
97
93
  it "returns the original string to match against" do
98
94
  re = RE2::Regexp.new('(\D+)').match("bob")
99
- re.string.must_equal("bob")
95
+ expect(re.string).to eq("bob")
100
96
  end
101
97
 
102
98
  it "returns a copy, not the actual original" do
103
99
  string = "bob"
104
100
  re = RE2::Regexp.new('(\D+)').match(string)
105
- re.string.wont_be_same_as(string)
101
+ expect(re.string).to_not equal(string)
106
102
  end
107
103
 
108
104
  it "returns a frozen string" do
109
105
  re = RE2::Regexp.new('(\D+)').match("bob")
110
- re.string.must_be(:frozen?)
106
+ expect(re.string).to be_frozen
111
107
  end
112
108
  end
113
109
 
114
110
  describe "#size" do
115
111
  it "returns the number of capturing groups plus the matching string" do
116
112
  md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
117
- md.size.must_equal(3)
113
+ expect(md.size).to eq(3)
118
114
  end
119
115
  end
120
116
 
121
117
  describe "#length" do
122
118
  it "returns the number of capturing groups plus the matching string" do
123
119
  md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
124
- md.length.must_equal(3)
120
+ expect(md.length).to eq(3)
125
121
  end
126
122
  end
127
123
 
@@ -129,26 +125,26 @@ describe RE2::MatchData do
129
125
  it "returns the original RE2::Regexp used" do
130
126
  re = RE2::Regexp.new('(\d+)')
131
127
  md = re.match("123")
132
- md.regexp.must_be_same_as(re)
128
+ expect(md.regexp).to equal(re)
133
129
  end
134
130
  end
135
131
 
136
132
  describe "#inspect" do
137
133
  it "returns a text representation of the object and indices" do
138
134
  md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
139
- md.inspect.must_equal('#<RE2::MatchData "1234 56" 1:"1234" 2:"56">')
135
+ expect(md.inspect).to eq('#<RE2::MatchData "1234 56" 1:"1234" 2:"56">')
140
136
  end
141
137
 
142
138
  it "represents missing matches as nil" do
143
139
  md = RE2::Regexp.new('(\d+) (\d+)?').match("1234 ")
144
- md.inspect.must_equal('#<RE2::MatchData "1234 " 1:"1234" 2:nil>')
140
+ expect(md.inspect).to eq('#<RE2::MatchData "1234 " 1:"1234" 2:nil>')
145
141
  end
146
142
  end
147
143
 
148
144
  describe "#to_s" do
149
145
  it "returns the matching part of the original string" do
150
146
  md = RE2::Regexp.new('(\d{2,5})').match("one two 23456")
151
- md.to_s.must_equal("23456")
147
+ expect(md.to_s).to eq("23456")
152
148
  end
153
149
  end
154
150
 
@@ -156,53 +152,93 @@ describe RE2::MatchData do
156
152
  it "allows the object to be expanded with an asterisk" do
157
153
  md = RE2::Regexp.new('(\d+) (\d+)').match("1234 56")
158
154
  m1, m2, m3 = *md
159
- m1.must_equal("1234 56")
160
- m2.must_equal("1234")
161
- m3.must_equal("56")
155
+ expect(m1).to eq("1234 56")
156
+ expect(m2).to eq("1234")
157
+ expect(m3).to eq("56")
162
158
  end
163
159
  end
164
160
 
165
161
  describe "#begin" do
166
162
  it "returns the offset of the start of a match by index" do
167
163
  md = RE2::Regexp.new('(wo{2})').match('a woohoo')
168
- md.string[md.begin(0)..-1].must_equal('woohoo')
164
+ expect(md.string[md.begin(0)..-1]).to eq('woohoo')
169
165
  end
170
166
 
171
167
  it "returns the offset of the start of a match by string name" do
172
168
  md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
173
- md.string[md.begin('foo')..-1].must_equal('foobar')
169
+ expect(md.string[md.begin('foo')..-1]).to eq('foobar')
174
170
  end
175
171
 
176
172
  it "returns the offset of the start of a match by symbol name" do
177
173
  md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
178
- md.string[md.begin(:foo)..-1].must_equal('foobar')
174
+ expect(md.string[md.begin(:foo)..-1]).to eq('foobar')
179
175
  end
180
176
 
181
177
  it "returns the offset despite multibyte characters" do
182
178
  md = RE2::Regexp.new('(Ruby)').match('I ♥ Ruby')
183
- md.string[md.begin(0)..-1].must_equal('Ruby')
179
+ expect(md.string[md.begin(0)..-1]).to eq('Ruby')
180
+ end
181
+
182
+ it "returns nil for non-existent numerical matches" do
183
+ md = RE2::Regexp.new('(\d)').match('123')
184
+ expect(md.begin(10)).to be_nil
185
+ end
186
+
187
+ it "returns nil for negative numerical matches" do
188
+ md = RE2::Regexp.new('(\d)').match('123')
189
+ expect(md.begin(-4)).to be_nil
190
+ end
191
+
192
+ it "returns nil for non-existent named matches" do
193
+ md = RE2::Regexp.new('(\d)').match('123')
194
+ expect(md.begin('foo')).to be_nil
195
+ end
196
+
197
+ it "returns nil for non-existent symbol named matches" do
198
+ md = RE2::Regexp.new('(\d)').match('123')
199
+ expect(md.begin(:foo)).to be_nil
184
200
  end
185
201
  end
186
202
 
187
203
  describe "#end" do
188
204
  it "returns the offset of the character following the end of a match" do
189
205
  md = RE2::Regexp.new('(wo{2})').match('a woohoo')
190
- md.string[0...md.end(0)].must_equal('a woo')
206
+ expect(md.string[0...md.end(0)]).to eq('a woo')
191
207
  end
192
208
 
193
209
  it "returns the offset of a match by string name" do
194
210
  md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
195
- md.string[0...md.end('foo')].must_equal('a foo')
211
+ expect(md.string[0...md.end('foo')]).to eq('a foo')
196
212
  end
197
213
 
198
214
  it "returns the offset of a match by symbol name" do
199
215
  md = RE2::Regexp.new('(?P<foo>fo{2})').match('a foobar')
200
- md.string[0...md.end(:foo)].must_equal('a foo')
216
+ expect(md.string[0...md.end(:foo)]).to eq('a foo')
201
217
  end
202
218
 
203
219
  it "returns the offset despite multibyte characters" do
204
220
  md = RE2::Regexp.new('(Ruby)').match('I ♥ Ruby')
205
- md.string[0...md.end(0)].must_equal('I ♥ Ruby')
221
+ expect(md.string[0...md.end(0)]).to eq('I ♥ Ruby')
222
+ end
223
+
224
+ it "returns nil for non-existent numerical matches" do
225
+ md = RE2::Regexp.new('(\d)').match('123')
226
+ expect(md.end(10)).to be_nil
227
+ end
228
+
229
+ it "returns nil for negative numerical matches" do
230
+ md = RE2::Regexp.new('(\d)').match('123')
231
+ expect(md.end(-4)).to be_nil
232
+ end
233
+
234
+ it "returns nil for non-existent named matches" do
235
+ md = RE2::Regexp.new('(\d)').match('123')
236
+ expect(md.end('foo')).to be_nil
237
+ end
238
+
239
+ it "returns nil for non-existent symbol named matches" do
240
+ md = RE2::Regexp.new('(\d)').match('123')
241
+ expect(md.end(:foo)).to be_nil
206
242
  end
207
243
  end
208
244
  end