summaryrefslogtreecommitdiff
path: root/spec/ruby/core/regexp
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-20 20:18:52 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-20 20:18:52 +0000
commit1d15d5f08032acf1b7bceacbb450d617ff6e0931 (patch)
treea3785a79899302bc149e4a6e72f624ac27dc1f10 /spec/ruby/core/regexp
parent75bfc6440d595bf339007f4fb280fd4d743e89c1 (diff)
Move spec/rubyspec to spec/ruby for consistency
* Other ruby implementations use the spec/ruby directory. [Misc #13792] [ruby-core:82287] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby/core/regexp')
-rw-r--r--spec/ruby/core/regexp/case_compare_spec.rb25
-rw-r--r--spec/ruby/core/regexp/casefold_spec.rb8
-rw-r--r--spec/ruby/core/regexp/compile_spec.rb18
-rw-r--r--spec/ruby/core/regexp/encoding_spec.rb58
-rw-r--r--spec/ruby/core/regexp/eql_spec.rb6
-rw-r--r--spec/ruby/core/regexp/equal_value_spec.rb6
-rw-r--r--spec/ruby/core/regexp/escape_spec.rb6
-rw-r--r--spec/ruby/core/regexp/fixed_encoding_spec.rb36
-rw-r--r--spec/ruby/core/regexp/hash_spec.rb20
-rw-r--r--spec/ruby/core/regexp/initialize_spec.rb15
-rw-r--r--spec/ruby/core/regexp/inspect_spec.rb44
-rw-r--r--spec/ruby/core/regexp/last_match_spec.rb14
-rw-r--r--spec/ruby/core/regexp/match_spec.rb148
-rw-r--r--spec/ruby/core/regexp/named_captures_spec.rb35
-rw-r--r--spec/ruby/core/regexp/names_spec.rb29
-rw-r--r--spec/ruby/core/regexp/new_spec.rb30
-rw-r--r--spec/ruby/core/regexp/options_spec.rb54
-rw-r--r--spec/ruby/core/regexp/quote_spec.rb6
-rw-r--r--spec/ruby/core/regexp/shared/equal_value.rb31
-rw-r--r--spec/ruby/core/regexp/shared/new_ascii.rb464
-rw-r--r--spec/ruby/core/regexp/shared/new_ascii_8bit.rb553
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb31
-rw-r--r--spec/ruby/core/regexp/source_spec.rb29
-rw-r--r--spec/ruby/core/regexp/to_s_spec.rb62
-rw-r--r--spec/ruby/core/regexp/try_convert_spec.rb21
-rw-r--r--spec/ruby/core/regexp/union_spec.rb149
26 files changed, 1898 insertions, 0 deletions
diff --git a/spec/ruby/core/regexp/case_compare_spec.rb b/spec/ruby/core/regexp/case_compare_spec.rb
new file mode 100644
index 0000000000..84ac957d12
--- /dev/null
+++ b/spec/ruby/core/regexp/case_compare_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#===" do
+ it "is true if there is a match" do
+ (/abc/ === "aabcc").should be_true
+ end
+
+ it "is false if there is no match" do
+ (/abc/ === "xyz").should be_false
+ end
+
+ it "returns true if it matches a Symbol" do
+ (/a/ === :a).should be_true
+ end
+
+ it "returns false if it does not match a Symbol" do
+ (/a/ === :b).should be_false
+ end
+
+ # mirroring https://github.com/ruby/ruby/blob/trunk/test/ruby/test_regexp.rb
+ it "returns false if the other value cannot be coerced to a string" do
+ (/abc/ === nil).should be_false
+ (/abc/ === /abc/).should be_false
+ end
+end
diff --git a/spec/ruby/core/regexp/casefold_spec.rb b/spec/ruby/core/regexp/casefold_spec.rb
new file mode 100644
index 0000000000..55efcaa765
--- /dev/null
+++ b/spec/ruby/core/regexp/casefold_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#casefold?" do
+ it "returns the value of the case-insensitive flag" do
+ /abc/i.casefold?.should == true
+ /xyz/.casefold?.should == false
+ end
+end
diff --git a/spec/ruby/core/regexp/compile_spec.rb b/spec/ruby/core/regexp/compile_spec.rb
new file mode 100644
index 0000000000..530816e07c
--- /dev/null
+++ b/spec/ruby/core/regexp/compile_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new_ascii', __FILE__)
+require File.expand_path('../shared/new_ascii_8bit', __FILE__)
+
+describe "Regexp.compile" do
+ it_behaves_like :regexp_new_ascii, :compile
+ it_behaves_like :regexp_new_ascii_8bit, :compile
+end
+
+describe "Regexp.compile given a String" do
+ it_behaves_like :regexp_new_string_ascii, :compile
+ it_behaves_like :regexp_new_string_ascii_8bit, :compile
+end
+
+describe "Regexp.compile given a Regexp" do
+ it_behaves_like :regexp_new_regexp_ascii, :compile
+ it_behaves_like :regexp_new_regexp_ascii_8bit, :compile
+end
diff --git a/spec/ruby/core/regexp/encoding_spec.rb b/spec/ruby/core/regexp/encoding_spec.rb
new file mode 100644
index 0000000000..c30519c9d7
--- /dev/null
+++ b/spec/ruby/core/regexp/encoding_spec.rb
@@ -0,0 +1,58 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#encoding" do
+ it "returns an Encoding object" do
+ /glar/.encoding.should be_an_instance_of(Encoding)
+ end
+
+ it "defaults to US-ASCII if the Regexp contains only US-ASCII character" do
+ /ASCII/.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns US_ASCII if the 'n' modifier is supplied and only US-ASCII characters are present" do
+ /ASCII/n.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns ASCII-8BIT if the 'n' modifier is supplied and non-US-ASCII characters are present" do
+ /\xc2\xa1/n.encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "defaults to UTF-8 if \\u escapes appear" do
+ /\u{9879}/.encoding.should == Encoding::UTF_8
+ end
+
+ it "defaults to UTF-8 if a literal UTF-8 character appears" do
+ /¥/.encoding.should == Encoding::UTF_8
+ end
+
+ it "returns UTF-8 if the 'u' modifier is supplied" do
+ /ASCII/u.encoding.should == Encoding::UTF_8
+ end
+
+ it "returns Windows-31J if the 's' modifier is supplied" do
+ /ASCII/s.encoding.should == Encoding::Windows_31J
+ end
+
+ it "returns EUC_JP if the 'e' modifier is supplied" do
+ /ASCII/e.encoding.should == Encoding::EUC_JP
+ end
+
+ it "upgrades the encoding to that of an embedded String" do
+ str = "文字化け".encode('euc-jp')
+ /#{str}/.encoding.should == Encoding::EUC_JP
+ end
+
+ it "ignores the encoding and uses US-ASCII if the string has only ASCII characters" do
+ str = "abc".encode('euc-jp')
+ str.encoding.should == Encoding::EUC_JP
+ /#{str}/.encoding.should == Encoding::US_ASCII
+ end
+
+ it "ignores the default_internal encoding" do
+ old_internal = Encoding.default_internal
+ Encoding.default_internal = Encoding::EUC_JP
+ /foo/.encoding.should_not == Encoding::EUC_JP
+ Encoding.default_internal = old_internal
+ end
+end
diff --git a/spec/ruby/core/regexp/eql_spec.rb b/spec/ruby/core/regexp/eql_spec.rb
new file mode 100644
index 0000000000..7288ff45fe
--- /dev/null
+++ b/spec/ruby/core/regexp/eql_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/equal_value', __FILE__)
+
+describe "Regexp#eql?" do
+ it_behaves_like :regexp_eql, :eql?
+end
diff --git a/spec/ruby/core/regexp/equal_value_spec.rb b/spec/ruby/core/regexp/equal_value_spec.rb
new file mode 100644
index 0000000000..4ddaec8e4e
--- /dev/null
+++ b/spec/ruby/core/regexp/equal_value_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/equal_value', __FILE__)
+
+describe "Regexp#==" do
+ it_behaves_like :regexp_eql, :==
+end
diff --git a/spec/ruby/core/regexp/escape_spec.rb b/spec/ruby/core/regexp/escape_spec.rb
new file mode 100644
index 0000000000..56b6cc5059
--- /dev/null
+++ b/spec/ruby/core/regexp/escape_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/quote', __FILE__)
+
+describe "Regexp.escape" do
+ it_behaves_like :regexp_quote, :escape
+end
diff --git a/spec/ruby/core/regexp/fixed_encoding_spec.rb b/spec/ruby/core/regexp/fixed_encoding_spec.rb
new file mode 100644
index 0000000000..8a11de9575
--- /dev/null
+++ b/spec/ruby/core/regexp/fixed_encoding_spec.rb
@@ -0,0 +1,36 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#fixed_encoding?" do
+ it "returns false by default" do
+ /needle/.fixed_encoding?.should be_false
+ end
+
+ it "returns false if the 'n' modifier was supplied to the Regexp" do
+ /needle/n.fixed_encoding?.should be_false
+ end
+
+ it "returns true if the 'u' modifier was supplied to the Regexp" do
+ /needle/u.fixed_encoding?.should be_true
+ end
+
+ it "returns true if the 's' modifier was supplied to the Regexp" do
+ /needle/s.fixed_encoding?.should be_true
+ end
+
+ it "returns true if the 'e' modifier was supplied to the Regexp" do
+ /needle/e.fixed_encoding?.should be_true
+ end
+
+ it "returns true if the Regexp contains a \\u escape" do
+ /needle \u{8768}/.fixed_encoding?.should be_true
+ end
+
+ it "returns true if the Regexp contains a UTF-8 literal" do
+ /文字化け/.fixed_encoding?.should be_true
+ end
+
+ it "returns true if the Regexp was created with the Regexp::FIXEDENCODING option" do
+ Regexp.new("", Regexp::FIXEDENCODING).fixed_encoding?.should be_true
+ end
+end
diff --git a/spec/ruby/core/regexp/hash_spec.rb b/spec/ruby/core/regexp/hash_spec.rb
new file mode 100644
index 0000000000..77b79b1ce5
--- /dev/null
+++ b/spec/ruby/core/regexp/hash_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#hash" do
+ it "is provided" do
+ Regexp.new('').respond_to?(:hash).should == true
+ end
+
+ it "is based on the text and options of Regexp" do
+ (/cat/.hash == /dog/.hash).should == false
+ (/dog/m.hash == /dog/m.hash).should == true
+ not_supported_on :opal do
+ (/cat/ix.hash == /cat/ixn.hash).should == true
+ (/cat/.hash == /cat/ix.hash).should == false
+ end
+ end
+
+ it "returns the same value for two Regexps differing only in the /n option" do
+ (//.hash == //n.hash).should == true
+ end
+end
diff --git a/spec/ruby/core/regexp/initialize_spec.rb b/spec/ruby/core/regexp/initialize_spec.rb
new file mode 100644
index 0000000000..3c32f97a31
--- /dev/null
+++ b/spec/ruby/core/regexp/initialize_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#initialize" do
+ it "is a private method" do
+ Regexp.should have_private_method(:initialize)
+ end
+
+ it "raises a SecurityError on a Regexp literal" do
+ lambda { //.send(:initialize, "") }.should raise_error(SecurityError)
+ end
+
+ it "raises a TypeError on an initialized non-literal Regexp" do
+ lambda { Regexp.new("").send(:initialize, "") }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/core/regexp/inspect_spec.rb b/spec/ruby/core/regexp/inspect_spec.rb
new file mode 100644
index 0000000000..a2855cae5b
--- /dev/null
+++ b/spec/ruby/core/regexp/inspect_spec.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#inspect" do
+ it "returns a formatted string that would eval to the same regexp" do
+ not_supported_on :opal do
+ /ab+c/ix.inspect.should == "/ab+c/ix"
+ /a(.)+s/n.inspect.should =~ %r|/a(.)+s/n?| # Default 'n' may not appear
+ end
+ # 1.9 doesn't round-trip the encoding flags, such as 'u'. This is
+ # seemingly by design.
+ /a(.)+s/m.inspect.should == "/a(.)+s/m" # But a specified one does
+ end
+
+ it "returns options in the order 'mixn'" do
+ //nixm.inspect.should == "//mixn"
+ end
+
+ it "does not include the 'o' option" do
+ //o.inspect.should == "//"
+ end
+
+ it "does not include a character set code" do
+ //u.inspect.should == "//"
+ //s.inspect.should == "//"
+ //e.inspect.should == "//"
+ end
+
+ it "correctly escapes forward slashes /" do
+ Regexp.new("/foo/bar").inspect.should == "/\\/foo\\/bar/"
+ Regexp.new("/foo/bar[/]").inspect.should == "/\\/foo\\/bar[\\/]/"
+ end
+
+ it "doesn't over escape forward slashes" do
+ /\/foo\/bar/.inspect.should == '/\/foo\/bar/'
+ end
+
+ it "escapes 2 slashes in a row properly" do
+ Regexp.new("//").inspect.should == '/\/\//'
+ end
+
+ it "does not over escape" do
+ Regexp.new('\\\/').inspect.should == "/\\\\\\//"
+ end
+end
diff --git a/spec/ruby/core/regexp/last_match_spec.rb b/spec/ruby/core/regexp/last_match_spec.rb
new file mode 100644
index 0000000000..4673554f91
--- /dev/null
+++ b/spec/ruby/core/regexp/last_match_spec.rb
@@ -0,0 +1,14 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp.last_match" do
+ it "returns MatchData instance when not passed arguments" do
+ /c(.)t/ =~ 'cat'
+
+ Regexp.last_match.should be_kind_of(MatchData)
+ end
+
+ it "returns the nth field in this MatchData when passed a Fixnum" do
+ /c(.)t/ =~ 'cat'
+ Regexp.last_match(1).should == 'a'
+ end
+end
diff --git a/spec/ruby/core/regexp/match_spec.rb b/spec/ruby/core/regexp/match_spec.rb
new file mode 100644
index 0000000000..872c3ff59e
--- /dev/null
+++ b/spec/ruby/core/regexp/match_spec.rb
@@ -0,0 +1,148 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe :regexp_match, shared: true do
+ it "returns nil if there is no match" do
+ /xyz/.send(@method,"abxyc").should be_nil
+ end
+
+ it "returns nil if the object is nil" do
+ /\w+/.send(@method, nil).should be_nil
+ end
+end
+
+describe "Regexp#=~" do
+ it_behaves_like(:regexp_match, :=~)
+
+ it "returns the index of the first character of the matching region" do
+ (/(.)(.)(.)/ =~ "abc").should == 0
+ end
+
+ it "returns the index too, when argument is a Symbol" do
+ (/(.)(.)(.)/ =~ :abc).should == 0
+ end
+end
+
+describe "Regexp#match" do
+ it_behaves_like(:regexp_match, :match)
+
+ it "returns a MatchData object" do
+ /(.)(.)(.)/.match("abc").should be_kind_of(MatchData)
+ end
+
+ it "returns a MatchData object, when argument is a Symbol" do
+ /(.)(.)(.)/.match(:abc).should be_kind_of(MatchData)
+ end
+
+ it "raises a TypeError on an uninitialized Regexp" do
+ lambda { Regexp.allocate.match('foo') }.should raise_error(TypeError)
+ end
+
+ describe "with [string, position]" do
+ describe "when given a positive position" do
+ it "matches the input at a given position" do
+ /(.).(.)/.match("01234", 1).captures.should == ["1", "3"]
+ end
+
+ with_feature :encoding do
+ it "uses the start as a character offset" do
+ /(.).(.)/.match("零一二三四", 1).captures.should == ["一", "三"]
+ end
+
+ it "raises an ArgumentError for an invalid encoding" do
+ x96 = ([150].pack('C')).force_encoding('utf-8')
+ lambda { /(.).(.)/.match("Hello, #{x96} world!", 1) }.should raise_error(ArgumentError)
+ end
+ end
+ end
+
+ describe "when given a negative position" do
+ it "matches the input at a given position" do
+ /(.).(.)/.match("01234", -4).captures.should == ["1", "3"]
+ end
+
+ with_feature :encoding do
+ it "uses the start as a character offset" do
+ /(.).(.)/.match("零一二三四", -4).captures.should == ["一", "三"]
+ end
+
+ it "raises an ArgumentError for an invalid encoding" do
+ x96 = ([150].pack('C')).force_encoding('utf-8')
+ lambda { /(.).(.)/.match("Hello, #{x96} world!", -1) }.should raise_error(ArgumentError)
+ end
+ end
+ end
+
+ describe "when passed a block" do
+ it "yields the MatchData" do
+ /./.match("abc") {|m| ScratchPad.record m }
+ ScratchPad.recorded.should be_kind_of(MatchData)
+ end
+
+ it "returns the block result" do
+ /./.match("abc") { :result }.should == :result
+ end
+
+ it "does not yield if there is no match" do
+ ScratchPad.record []
+ /a/.match("b") {|m| ScratchPad << m }
+ ScratchPad.recorded.should == []
+ end
+ end
+ end
+
+ it "resets $~ if passed nil" do
+ # set $~
+ /./.match("a")
+ $~.should be_kind_of(MatchData)
+
+ /1/.match(nil)
+ $~.should be_nil
+ end
+
+ it "raises TypeError when the given argument cannot be coarce to String" do
+ f = 1
+ lambda { /foo/.match(f)[0] }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError when the given argument is an Exception" do
+ f = Exception.new("foo")
+ lambda { /foo/.match(f)[0] }.should raise_error(TypeError)
+ end
+end
+
+ruby_version_is "2.4" do
+ describe "Regexp#match?" do
+ before :each do
+ # Resetting Regexp.last_match
+ /DONTMATCH/.match ''
+ end
+
+ context "when matches the given value" do
+ it "returns true but does not set Regexp.last_match" do
+ /string/i.match?('string').should be_true
+ Regexp.last_match.should be_nil
+ end
+ end
+
+ it "returns false when does not match the given value" do
+ /STRING/.match?('string').should be_false
+ end
+
+ it "takes matching position as the 2nd argument" do
+ /str/i.match?('string', 0).should be_true
+ /str/i.match?('string', 1).should be_false
+ end
+
+ it "returns false when given nil" do
+ /./.match?(nil).should be_false
+ end
+ end
+end
+
+describe "Regexp#~" do
+ it "matches against the contents of $_" do
+ $_ = "input data"
+ (~ /at/).should == 7
+ end
+end
diff --git a/spec/ruby/core/regexp/named_captures_spec.rb b/spec/ruby/core/regexp/named_captures_spec.rb
new file mode 100644
index 0000000000..c495d00a35
--- /dev/null
+++ b/spec/ruby/core/regexp/named_captures_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#named_captures" do
+ it "returns a Hash" do
+ /foo/.named_captures.should be_an_instance_of(Hash)
+ end
+
+ it "returns an empty Hash when there are no capture groups" do
+ /foo/.named_captures.should == {}
+ end
+
+ it "sets the keys of the Hash to the names of the capture groups" do
+ rex = /this (?<is>is) [aA] (?<pat>pate?rn)/
+ rex.named_captures.keys.should == ['is','pat']
+ end
+
+ it "sets the values of the Hash to Arrays" do
+ rex = /this (?<is>is) [aA] (?<pat>pate?rn)/
+ rex.named_captures.values.each do |value|
+ value.should be_an_instance_of(Array)
+ end
+ end
+
+ it "sets each element of the Array to the corresponding group's index" do
+ rex = /this (?<is>is) [aA] (?<pat>pate?rn)/
+ rex.named_captures['is'].should == [1]
+ rex.named_captures['pat'].should == [2]
+ end
+
+ it "works with duplicate capture group names" do
+ rex = /this (?<is>is) [aA] (?<pat>pate?(?<is>rn))/
+ rex.named_captures['is'].should == [1,3]
+ rex.named_captures['pat'].should == [2]
+ end
+end
diff --git a/spec/ruby/core/regexp/names_spec.rb b/spec/ruby/core/regexp/names_spec.rb
new file mode 100644
index 0000000000..bbd994d993
--- /dev/null
+++ b/spec/ruby/core/regexp/names_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#names" do
+ it "returns an Array" do
+ /foo/.names.should be_an_instance_of(Array)
+ end
+
+ it "returns an empty Array if there are no named captures" do
+ /needle/.names.should == []
+ end
+
+ it "returns each named capture as a String" do
+ /n(?<cap>ee)d(?<ture>le)/.names.each do |name|
+ name.should be_an_instance_of(String)
+ end
+ end
+
+ it "returns all of the named captures" do
+ /n(?<cap>ee)d(?<ture>le)/.names.should == ['cap', 'ture']
+ end
+
+ it "works with nested named captures" do
+ /n(?<cap>eed(?<ture>le))/.names.should == ['cap', 'ture']
+ end
+
+ it "returns each capture name only once" do
+ /n(?<cap>ee)d(?<cap>le)/.names.should == ['cap']
+ end
+end
diff --git a/spec/ruby/core/regexp/new_spec.rb b/spec/ruby/core/regexp/new_spec.rb
new file mode 100644
index 0000000000..c9581e661f
--- /dev/null
+++ b/spec/ruby/core/regexp/new_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new_ascii', __FILE__)
+require File.expand_path('../shared/new_ascii_8bit', __FILE__)
+
+describe "Regexp.new" do
+ it_behaves_like :regexp_new_ascii, :new
+ it_behaves_like :regexp_new_ascii_8bit, :new
+end
+
+describe "Regexp.new given a String" do
+ it_behaves_like :regexp_new_string_ascii, :new
+ it_behaves_like :regexp_new_string_ascii_8bit, :new
+end
+
+describe "Regexp.new given a Regexp" do
+ it_behaves_like :regexp_new_regexp_ascii, :new
+ it_behaves_like :regexp_new_regexp_ascii_8bit, :new
+end
+
+describe "Regexp.new given a Fixnum" do
+ it "raises a TypeError" do
+ lambda { Regexp.new(1) }.should raise_error(TypeError)
+ end
+end
+
+describe "Regexp.new given a Float" do
+ it "raises a TypeError" do
+ lambda { Regexp.new(1.0) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/core/regexp/options_spec.rb b/spec/ruby/core/regexp/options_spec.rb
new file mode 100644
index 0000000000..10aeeac919
--- /dev/null
+++ b/spec/ruby/core/regexp/options_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#options" do
+ it "returns a Fixnum bitvector of regexp options for the Regexp object" do
+ /cat/.options.should be_kind_of(Fixnum)
+ not_supported_on :opal do
+ /cat/ix.options.should be_kind_of(Fixnum)
+ end
+ end
+
+ it "allows checking for presence of a certain option with bitwise &" do
+ (/cat/.options & Regexp::IGNORECASE).should == 0
+ (/cat/i.options & Regexp::IGNORECASE).should_not == 0
+ (/cat/.options & Regexp::MULTILINE).should == 0
+ (/cat/m.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (/cat/.options & Regexp::EXTENDED).should == 0
+ (/cat/x.options & Regexp::EXTENDED).should_not == 0
+ (/cat/mx.options & Regexp::MULTILINE).should_not == 0
+ (/cat/mx.options & Regexp::EXTENDED).should_not == 0
+ (/cat/xi.options & Regexp::IGNORECASE).should_not == 0
+ (/cat/xi.options & Regexp::EXTENDED).should_not == 0
+ end
+ end
+
+ it "returns 0 for a Regexp literal without options" do
+ //.options.should == 0
+ /abc/.options.should == 0
+ end
+
+ it "raises a TypeError on an uninitialized Regexp" do
+ lambda { Regexp.allocate.options }.should raise_error(TypeError)
+ end
+
+ it "includes Regexp::FIXEDENCODING for a Regexp literal with the 'u' option" do
+ (//u.options & Regexp::FIXEDENCODING).should_not == 0
+ end
+
+ it "includes Regexp::FIXEDENCODING for a Regexp literal with the 'e' option" do
+ (//e.options & Regexp::FIXEDENCODING).should_not == 0
+ end
+
+ it "includes Regexp::FIXEDENCODING for a Regexp literal with the 's' option" do
+ (//s.options & Regexp::FIXEDENCODING).should_not == 0
+ end
+
+ it "does not include Regexp::FIXEDENCODING for a Regexp literal with the 'n' option" do
+ (//n.options & Regexp::FIXEDENCODING).should == 0
+ end
+
+ it "includes Regexp::NOENCODING for a Regexp literal with the 'n' option" do
+ (//n.options & Regexp::NOENCODING).should_not == 0
+ end
+end
diff --git a/spec/ruby/core/regexp/quote_spec.rb b/spec/ruby/core/regexp/quote_spec.rb
new file mode 100644
index 0000000000..a38903ef15
--- /dev/null
+++ b/spec/ruby/core/regexp/quote_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../shared/quote', __FILE__)
+
+describe "Regexp.quote" do
+ it_behaves_like :regexp_quote, :quote
+end
diff --git a/spec/ruby/core/regexp/shared/equal_value.rb b/spec/ruby/core/regexp/shared/equal_value.rb
new file mode 100644
index 0000000000..803988de9e
--- /dev/null
+++ b/spec/ruby/core/regexp/shared/equal_value.rb
@@ -0,0 +1,31 @@
+describe :regexp_eql, shared: true do
+ it "is true if self and other have the same pattern" do
+ /abc/.send(@method, /abc/).should == true
+ /abc/.send(@method, /abd/).should == false
+ end
+
+ not_supported_on :opal do
+ it "is true if self and other have the same character set code" do
+ /abc/.send(@method, /abc/x).should == false
+ /abc/x.send(@method, /abc/x).should == true
+ /abc/u.send(@method, /abc/n).should == false
+ /abc/u.send(@method, /abc/u).should == true
+ /abc/n.send(@method, /abc/n).should == true
+ end
+ end
+
+ it "is true if other has the same #casefold? values" do
+ /abc/.send(@method, /abc/i).should == false
+ /abc/i.send(@method, /abc/i).should == true
+ end
+
+ not_supported_on :opal do
+ it "is true if self does not specify /n option and other does" do
+ //.send(@method, //n).should == true
+ end
+
+ it "is true if self specifies /n option and other does not" do
+ //n.send(@method, //).should == true
+ end
+ end
+end
diff --git a/spec/ruby/core/regexp/shared/new_ascii.rb b/spec/ruby/core/regexp/shared/new_ascii.rb
new file mode 100644
index 0000000000..98c458312e
--- /dev/null
+++ b/spec/ruby/core/regexp/shared/new_ascii.rb
@@ -0,0 +1,464 @@
+# -*- encoding: binary -*-
+describe :regexp_new_ascii, shared: true do
+ it "requires one argument and creates a new regular expression object" do
+ Regexp.send(@method, '').is_a?(Regexp).should == true
+ end
+
+ it "works by default for subclasses with overridden #initialize" do
+ class RegexpSpecsSubclass < Regexp
+ def initialize(*args)
+ super
+ @args = args
+ end
+
+ attr_accessor :args
+ end
+
+ class RegexpSpecsSubclassTwo < Regexp; end
+
+ RegexpSpecsSubclass.send(@method, "hi").should be_kind_of(RegexpSpecsSubclass)
+ RegexpSpecsSubclass.send(@method, "hi").args.first.should == "hi"
+
+ RegexpSpecsSubclassTwo.send(@method, "hi").should be_kind_of(RegexpSpecsSubclassTwo)
+ end
+end
+
+describe :regexp_new_string_ascii, shared: true do
+ it "uses the String argument as an unescaped literal to construct a Regexp object" do
+ Regexp.send(@method, "^hi{2,3}fo.o$").should == /^hi{2,3}fo.o$/
+ end
+
+ it "raises a RegexpError when passed an incorrect regexp" do
+ lambda { Regexp.send(@method, "^[$", 0) }.should raise_error(RegexpError)
+ end
+
+ it "does not set Regexp options if only given one argument" do
+ r = Regexp.send(@method, 'Hi')
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "does not set Regexp options if second argument is nil or false" do
+ r = Regexp.send(@method, 'Hi', nil)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ r = Regexp.send(@method, 'Hi', false)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "sets options from second argument if it is one of the Fixnum option constants" do
+ r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE)
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ r = Regexp.send(@method, 'Hi', Regexp::MULTILINE)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ not_supported_on :opal do
+ r = Regexp.send(@method, 'Hi', Regexp::EXTENDED)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ (r.options & Regexp::EXTENDED).should_not == 1
+ end
+ end
+
+ it "accepts a Fixnum of two or more options ORed together as the second argument" do
+ r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE | Regexp::EXTENDED)
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ (r.options & Regexp::EXTENDED).should_not == 0
+ end
+
+ it "treats any non-Fixnum, non-nil, non-false second argument as IGNORECASE" do
+ r = Regexp.send(@method, 'Hi', Object.new)
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "ignores the third argument if it is 'e' or 'euc' (case-insensitive)" do
+ lambda {
+ Regexp.send(@method, 'Hi', nil, 'e').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'euc').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'E').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'EUC').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "ignores the third argument if it is 's' or 'sjis' (case-insensitive)" do
+ lambda {
+ Regexp.send(@method, 'Hi', nil, 's').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'sjis').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'S').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'SJIS').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "ignores the third argument if it is 'u' or 'utf8' (case-insensitive)" do
+ lambda {
+ Regexp.send(@method, 'Hi', nil, 'u').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'utf8').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'U').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'UTF8').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "uses US_ASCII encoding if third argument is 'n' or 'none' (case insensitive) and only ascii characters" do
+ Regexp.send(@method, 'Hi', nil, 'n').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'none').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'N').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'NONE').encoding.should == Encoding::US_ASCII
+ end
+
+ it "uses ASCII_8BIT encoding if third argument is 'n' or 'none' (case insensitive) and non-ascii characters" do
+ a = "(?:[\x8E\xA1-\xFE])"
+ str = "\A(?:#{a}|x*)\z"
+
+ Regexp.send(@method, str, nil, 'N').encoding.should == Encoding::ASCII_8BIT
+ Regexp.send(@method, str, nil, 'n').encoding.should == Encoding::ASCII_8BIT
+ Regexp.send(@method, str, nil, 'none').encoding.should == Encoding::ASCII_8BIT
+ Regexp.send(@method, str, nil, 'NONE').encoding.should == Encoding::ASCII_8BIT
+ end
+
+ describe "with escaped characters" do
+ it "raises a Regexp error if there is a trailing backslash" do
+ lambda { Regexp.send(@method, "\\") }.should raise_error(RegexpError)
+ end
+
+ it "does not raise a Regexp error if there is an escaped trailing backslash" do
+ lambda { Regexp.send(@method, "\\\\") }.should_not raise_error(RegexpError)
+ end
+
+ it "accepts a backspace followed by a character" do
+ Regexp.send(@method, "\\N").should == /#{"\x5c"+"N"}/
+ end
+
+ it "accepts a one-digit octal value" do
+ Regexp.send(@method, "\0").should == /#{"\x00"}/
+ end
+
+ it "accepts a two-digit octal value" do
+ Regexp.send(@method, "\11").should == /#{"\x09"}/
+ end
+
+ it "accepts a one-digit hexadecimal value" do
+ Regexp.send(@method, "\x9n").should == /#{"\x09n"}/
+ end
+
+ it "accepts a two-digit hexadecimal value" do
+ Regexp.send(@method, "\x23").should == /#{"\x23"}/
+ end
+
+ it "interprets a digit following a two-digit hexadecimal value as a character" do
+ Regexp.send(@method, "\x420").should == /#{"\x420"}/
+ end
+
+ it "raises a RegexpError if \\x is not followed by any hexadecimal digits" do
+ lambda { Regexp.send(@method, "\\" + "xn") }.should raise_error(RegexpError)
+ end
+
+ it "accepts an escaped string interpolation" do
+ Regexp.send(@method, "\#{abc}").should == /#{"\#{abc}"}/
+ end
+
+ it "accepts '\\n'" do
+ Regexp.send(@method, "\n").should == /#{"\x0a"}/
+ end
+
+ it "accepts '\\t'" do
+ Regexp.send(@method, "\t").should == /#{"\x09"}/
+ end
+
+ it "accepts '\\r'" do
+ Regexp.send(@method, "\r").should == /#{"\x0d"}/
+ end
+
+ it "accepts '\\f'" do
+ Regexp.send(@method, "\f").should == /#{"\x0c"}/
+ end
+
+ it "accepts '\\v'" do
+ Regexp.send(@method, "\v").should == /#{"\x0b"}/
+ end
+
+ it "accepts '\\a'" do
+ Regexp.send(@method, "\a").should == /#{"\x07"}/
+ end
+
+ it "accepts '\\e'" do
+ Regexp.send(@method, "\e").should == /#{"\x1b"}/
+ end
+
+ it "accepts '\\C-\\n'" do
+ Regexp.send(@method, "\C-\n").should == /#{"\x0a"}/
+ end
+
+ it "accepts '\\C-\\t'" do
+ Regexp.send(@method, "\C-\t").should == /#{"\x09"}/
+ end
+
+ it "accepts '\\C-\\r'" do
+ Regexp.send(@method, "\C-\r").should == /#{"\x0d"}/
+ end
+
+ it "accepts '\\C-\\f'" do
+ Regexp.send(@method, "\C-\f").should == /#{"\x0c"}/
+ end
+
+ it "accepts '\\C-\\v'" do
+ Regexp.send(@method, "\C-\v").should == /#{"\x0b"}/
+ end
+
+ it "accepts '\\C-\\a'" do
+ Regexp.send(@method, "\C-\a").should == /#{"\x07"}/
+ end
+
+ it "accepts '\\C-\\e'" do
+ Regexp.send(@method, "\C-\e").should == /#{"\x1b"}/
+ end
+
+ it "accepts '\\c\\n'" do
+ Regexp.send(@method, "\C-\n").should == /#{"\x0a"}/
+ end
+
+ it "accepts '\\c\\t'" do
+ Regexp.send(@method, "\C-\t").should == /#{"\x09"}/
+ end
+
+ it "accepts '\\c\\r'" do
+ Regexp.send(@method, "\C-\r").should == /#{"\x0d"}/
+ end
+
+ it "accepts '\\c\\f'" do
+ Regexp.send(@method, "\C-\f").should == /#{"\x0c"}/
+ end
+
+ it "accepts '\\c\\v'" do
+ Regexp.send(@method, "\C-\v").should == /#{"\x0b"}/
+ end
+
+ it "accepts '\\c\\a'" do
+ Regexp.send(@method, "\C-\a").should == /#{"\x07"}/
+ end
+
+ it "accepts '\\c\\e'" do
+ Regexp.send(@method, "\C-\e").should == /#{"\x1b"}/
+ end
+
+ it "accepts multiple consecutive '\\' characters" do
+ Regexp.send(@method, "\\\\\\N").should == /#{"\\\\\\"+"N"}/
+ end
+
+ it "accepts characters and escaped octal digits" do
+ Regexp.send(@method, "abc\076").should == /#{"abc\x3e"}/
+ end
+
+ it "accepts escaped octal digits and characters" do
+ Regexp.send(@method, "\076abc").should == /#{"\x3eabc"}/
+ end
+
+ it "accepts characters and escaped hexadecimal digits" do
+ Regexp.send(@method, "abc\x42").should == /#{"abc\x42"}/
+ end
+
+ it "accepts escaped hexadecimal digits and characters" do
+ Regexp.send(@method, "\x3eabc").should == /#{"\x3eabc"}/
+ end
+
+ it "accepts escaped hexadecimal and octal digits" do
+ Regexp.send(@method, "\061\x42").should == /#{"\x31\x42"}/
+ end
+
+ it "accepts \\u{H} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{f}").should == /#{"\x0f"}/
+ end
+
+ it "accepts \\u{HH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{7f}").should == /#{"\x7f"}/
+ end
+
+ it "accepts \\u{HHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{07f}").should == /#{"\x7f"}/
+ end
+
+ it "accepts \\u{HHHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{0000}").should == /#{"\x00"}/
+ end
+
+ it "accepts \\u{HHHHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{00001}").should == /#{"\x01"}/
+ end
+
+ it "accepts \\u{HHHHHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{000000}").should == /#{"\x00"}/
+ end
+
+ it "accepts characters followed by \\u{HHHH}" do
+ Regexp.send(@method, "abc\u{3042}").should == /#{"abc\u3042"}/
+ end
+
+ it "accepts \\u{HHHH} followed by characters" do
+ Regexp.send(@method, "\u{3042}abc").should == /#{"\u3042abc"}/
+ end
+
+ it "accepts escaped hexadecimal digits followed by \\u{HHHH}" do
+ Regexp.send(@method, "\x42\u{3042}").should == /#{"\x42\u3042"}/
+ end
+
+ it "accepts escaped octal digits followed by \\u{HHHH}" do
+ Regexp.send(@method, "\056\u{3042}").should == /#{"\x2e\u3042"}/
+ end
+
+ it "accepts a combination of escaped octal and hexadecimal digits and \\u{HHHH}" do
+ Regexp.send(@method, "\056\x42\u{3042}\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
+ end
+
+ it "accepts \\uHHHH for a single Unicode codepoint" do
+ Regexp.send(@method, "\u3042").should == /#{"\u3042"}/
+ end
+
+ it "accepts characters followed by \\uHHHH" do
+ Regexp.send(@method, "abc\u3042").should == /#{"abc\u3042"}/
+ end
+
+ it "accepts \\uHHHH followed by characters" do
+ Regexp.send(@method, "\u3042abc").should == /#{"\u3042abc"}/
+ end
+
+ it "accepts escaped hexadecimal digits followed by \\uHHHH" do
+ Regexp.send(@method, "\x42\u3042").should == /#{"\x42\u3042"}/
+ end
+
+ it "accepts escaped octal digits followed by \\uHHHH" do
+ Regexp.send(@method, "\056\u3042").should == /#{"\x2e\u3042"}/
+ end
+
+ it "accepts a combination of escaped octal and hexadecimal digits and \\uHHHH" do
+ Regexp.send(@method, "\056\x42\u3042\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
+ end
+
+ it "raises a RegexpError if less than four digits are given for \\uHHHH" do
+ lambda { Regexp.send(@method, "\\" + "u304") }.should raise_error(RegexpError)
+ end
+
+ it "raises a RegexpError if the \\u{} escape is empty" do
+ lambda { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError)
+ end
+
+ it "raises a RegexpError if more than six hexadecimal digits are given" do
+ lambda { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError)
+ end
+
+ it "returns a Regexp with US-ASCII encoding if only 7-bit ASCII characters are present regardless of the input String's encoding" do
+ Regexp.send(@method, "abc").encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with source String having US-ASCII encoding if only 7-bit ASCII characters are present regardless of the input String's encoding" do
+ Regexp.send(@method, "abc").source.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with US-ASCII encoding if UTF-8 escape sequences using only 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{61}").encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with source String having US-ASCII encoding if UTF-8 escape sequences using only 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{61}").source.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with UTF-8 encoding if any UTF-8 escape sequences outside 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{ff}").encoding.should == Encoding::UTF_8
+ end
+
+ it "returns a Regexp with source String having UTF-8 encoding if any UTF-8 escape sequences outside 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{ff}").source.encoding.should == Encoding::UTF_8
+ end
+
+ it "returns a Regexp with the input String's encoding" do
+ str = "\x82\xa0".force_encoding(Encoding::Shift_JIS)
+ Regexp.send(@method, str).encoding.should == Encoding::Shift_JIS
+ end
+
+ it "returns a Regexp with source String having the input String's encoding" do
+ str = "\x82\xa0".force_encoding(Encoding::Shift_JIS)
+ Regexp.send(@method, str).source.encoding.should == Encoding::Shift_JIS
+ end
+ end
+end
+
+describe :regexp_new_regexp_ascii, shared: true do
+ it "uses the argument as a literal to construct a Regexp object" do
+ Regexp.send(@method, /^hi{2,3}fo.o$/).should == /^hi{2,3}fo.o$/
+ end
+
+ it "preserves any options given in the Regexp literal" do
+ (Regexp.send(@method, /Hi/i).options & Regexp::IGNORECASE).should_not == 0
+ (Regexp.send(@method, /Hi/m).options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (Regexp.send(@method, /Hi/x).options & Regexp::EXTENDED).should_not == 0
+ end
+
+ not_supported_on :opal do
+ r = Regexp.send @method, /Hi/imx
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ (r.options & Regexp::EXTENDED).should_not == 0
+ end
+
+ r = Regexp.send @method, /Hi/
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "does not honour options given as additional arguments" do
+ r = nil
+ lambda {
+ r = Regexp.send @method, /hi/, Regexp::IGNORECASE
+ }.should complain(/flags ignored/)
+ (r.options & Regexp::IGNORECASE).should == 0
+ end
+
+ not_supported_on :opal do
+ it "sets the encoding to UTF-8 if the Regexp literal has the 'u' option" do
+ Regexp.send(@method, /Hi/u).encoding.should == Encoding::UTF_8
+ end
+
+ it "sets the encoding to EUC-JP if the Regexp literal has the 'e' option" do
+ Regexp.send(@method, /Hi/e).encoding.should == Encoding::EUC_JP
+ end
+
+ it "sets the encoding to Windows-31J if the Regexp literal has the 's' option" do
+ Regexp.send(@method, /Hi/s).encoding.should == Encoding::Windows_31J
+ end
+
+ it "sets the encoding to US-ASCII if the Regexp literal has the 'n' option and the source String is ASCII only" do
+ Regexp.send(@method, /Hi/n).encoding.should == Encoding::US_ASCII
+ end
+
+ it "sets the encoding to source String's encoding if the Regexp literal has the 'n' option and the source String is not ASCII only" do
+ Regexp.send(@method, Regexp.new("\\xff", nil, 'n')).encoding.should == Encoding::ASCII_8BIT
+ end
+ end
+end
diff --git a/spec/ruby/core/regexp/shared/new_ascii_8bit.rb b/spec/ruby/core/regexp/shared/new_ascii_8bit.rb
new file mode 100644
index 0000000000..5110a08380
--- /dev/null
+++ b/spec/ruby/core/regexp/shared/new_ascii_8bit.rb
@@ -0,0 +1,553 @@
+# -*- encoding: ascii-8bit -*-
+
+describe :regexp_new_ascii_8bit, shared: true do
+ it "requires one argument and creates a new regular expression object" do
+ Regexp.send(@method, '').is_a?(Regexp).should == true
+ end
+
+ it "works by default for subclasses with overridden #initialize" do
+ class RegexpSpecsSubclass < Regexp
+ def initialize(*args)
+ super
+ @args = args
+ end
+
+ attr_accessor :args
+ end
+
+ class RegexpSpecsSubclassTwo < Regexp; end
+
+ RegexpSpecsSubclass.send(@method, "hi").should be_kind_of(RegexpSpecsSubclass)
+ RegexpSpecsSubclass.send(@method, "hi").args.first.should == "hi"
+
+ RegexpSpecsSubclassTwo.send(@method, "hi").should be_kind_of(RegexpSpecsSubclassTwo)
+ end
+end
+
+describe :regexp_new_string_ascii_8bit, shared: true do
+ it "uses the String argument as an unescaped literal to construct a Regexp object" do
+ Regexp.send(@method, "^hi{2,3}fo.o$").should == /^hi{2,3}fo.o$/
+ end
+
+ it "raises a RegexpError when passed an incorrect regexp" do
+ lambda { Regexp.send(@method, "^[$", 0) }.should raise_error(RegexpError)
+ end
+
+ it "does not set Regexp options if only given one argument" do
+ r = Regexp.send(@method, 'Hi')
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "does not set Regexp options if second argument is nil or false" do
+ r = Regexp.send(@method, 'Hi', nil)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ r = Regexp.send(@method, 'Hi', false)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "sets options from second argument if it is one of the Fixnum option constants" do
+ r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE)
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ r = Regexp.send(@method, 'Hi', Regexp::MULTILINE)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+
+ not_supported_on :opal do
+ r = Regexp.send(@method, 'Hi', Regexp::EXTENDED)
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ (r.options & Regexp::EXTENDED).should_not == 1
+ end
+ end
+
+ it "accepts a Fixnum of two or more options ORed together as the second argument" do
+ r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE | Regexp::EXTENDED)
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ (r.options & Regexp::EXTENDED).should_not == 0
+ end
+
+ it "treats any non-Fixnum, non-nil, non-false second argument as IGNORECASE" do
+ r = Regexp.send(@method, 'Hi', Object.new)
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "ignores the third argument if it is 'e' or 'euc' (case-insensitive)" do
+ lambda {
+ Regexp.send(@method, 'Hi', nil, 'e').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'euc').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'E').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'EUC').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "ignores the third argument if it is 's' or 'sjis' (case-insensitive)" do
+ lambda {
+ Regexp.send(@method, 'Hi', nil, 's').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'sjis').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'S').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'SJIS').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "ignores the third argument if it is 'u' or 'utf8' (case-insensitive)" do
+ lambda {
+ Regexp.send(@method, 'Hi', nil, 'u').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'utf8').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'U').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'UTF8').encoding.should == Encoding::US_ASCII
+ }.should complain(/encoding option is ignored/)
+ end
+
+ it "uses US_ASCII encoding if third argument is 'n' or 'none' (case insensitive) and only ascii characters" do
+ Regexp.send(@method, 'Hi', nil, 'n').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'none').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'N').encoding.should == Encoding::US_ASCII
+ Regexp.send(@method, 'Hi', nil, 'NONE').encoding.should == Encoding::US_ASCII
+ end
+
+ it "uses ASCII_8BIT encoding if third argument is 'n' or 'none' (case insensitive) and non-ascii characters" do
+ a = "(?:[\x8E\xA1-\xFE])"
+ str = "\A(?:#{a}|x*)\z"
+
+ Regexp.send(@method, str, nil, 'N').encoding.should == Encoding::ASCII_8BIT
+ Regexp.send(@method, str, nil, 'n').encoding.should == Encoding::ASCII_8BIT
+ Regexp.send(@method, str, nil, 'none').encoding.should == Encoding::ASCII_8BIT
+ Regexp.send(@method, str, nil, 'NONE').encoding.should == Encoding::ASCII_8BIT
+ end
+
+ describe "with escaped characters" do
+ it "raises a Regexp error if there is a trailing backslash" do
+ lambda { Regexp.send(@method, "\\") }.should raise_error(RegexpError)
+ end
+
+ it "accepts a backspace followed by a character" do
+ Regexp.send(@method, "\\N").should == /#{"\x5c"+"N"}/
+ end
+
+ it "accepts a one-digit octal value" do
+ Regexp.send(@method, "\0").should == /#{"\x00"}/
+ end
+
+ it "accepts a two-digit octal value" do
+ Regexp.send(@method, "\11").should == /#{"\x09"}/
+ end
+
+ it "accepts a three-digit octal value" do
+ Regexp.send(@method, "\315").should == /#{"\xcd"}/
+ end
+
+ it "interprets a digit following a three-digit octal value as a character" do
+ Regexp.send(@method, "\3762").should == /#{"\xfe2"}/
+ end
+
+ it "accepts a one-digit hexadecimal value" do
+ Regexp.send(@method, "\x9n").should == /#{"\x09n"}/
+ end
+
+ it "accepts a two-digit hexadecimal value" do
+ Regexp.send(@method, "\x23").should == /#{"\x23"}/
+ end
+
+ it "interprets a digit following a two-digit hexadecimal value as a character" do
+ Regexp.send(@method, "\x420").should == /#{"\x420"}/
+ end
+
+ it "raises a RegexpError if \\x is not followed by any hexadecimal digits" do
+ lambda { Regexp.send(@method, "\\" + "xn") }.should raise_error(RegexpError)
+ end
+
+ it "accepts an escaped string interpolation" do
+ Regexp.send(@method, "\#{abc}").should == /#{"\#{abc}"}/
+ end
+
+ it "accepts '\\n'" do
+ Regexp.send(@method, "\n").should == /#{"\x0a"}/
+ end
+
+ it "accepts '\\t'" do
+ Regexp.send(@method, "\t").should == /#{"\x09"}/
+ end
+
+ it "accepts '\\r'" do
+ Regexp.send(@method, "\r").should == /#{"\x0d"}/
+ end
+
+ it "accepts '\\f'" do
+ Regexp.send(@method, "\f").should == /#{"\x0c"}/
+ end
+
+ it "accepts '\\v'" do
+ Regexp.send(@method, "\v").should == /#{"\x0b"}/
+ end
+
+ it "accepts '\\a'" do
+ Regexp.send(@method, "\a").should == /#{"\x07"}/
+ end
+
+ it "accepts '\\e'" do
+ Regexp.send(@method, "\e").should == /#{"\x1b"}/
+ end
+
+ it "accepts '\\C-\\n'" do
+ Regexp.send(@method, "\C-\n").should == /#{"\x0a"}/
+ end
+
+ it "accepts '\\C-\\t'" do
+ Regexp.send(@method, "\C-\t").should == /#{"\x09"}/
+ end
+
+ it "accepts '\\C-\\r'" do
+ Regexp.send(@method, "\C-\r").should == /#{"\x0d"}/
+ end
+
+ it "accepts '\\C-\\f'" do
+ Regexp.send(@method, "\C-\f").should == /#{"\x0c"}/
+ end
+
+ it "accepts '\\C-\\v'" do
+ Regexp.send(@method, "\C-\v").should == /#{"\x0b"}/
+ end
+
+ it "accepts '\\C-\\a'" do
+ Regexp.send(@method, "\C-\a").should == /#{"\x07"}/
+ end
+
+ it "accepts '\\C-\\e'" do
+ Regexp.send(@method, "\C-\e").should == /#{"\x1b"}/
+ end
+
+ it "accepts '\\c\\n'" do
+ Regexp.send(@method, "\C-\n").should == /#{"\x0a"}/
+ end
+
+ it "accepts '\\c\\t'" do
+ Regexp.send(@method, "\C-\t").should == /#{"\x09"}/
+ end
+
+ it "accepts '\\c\\r'" do
+ Regexp.send(@method, "\C-\r").should == /#{"\x0d"}/
+ end
+
+ it "accepts '\\c\\f'" do
+ Regexp.send(@method, "\C-\f").should == /#{"\x0c"}/
+ end
+
+ it "accepts '\\c\\v'" do
+ Regexp.send(@method, "\C-\v").should == /#{"\x0b"}/
+ end
+
+ it "accepts '\\c\\a'" do
+ Regexp.send(@method, "\C-\a").should == /#{"\x07"}/
+ end
+
+ it "accepts '\\c\\e'" do
+ Regexp.send(@method, "\C-\e").should == /#{"\x1b"}/
+ end
+
+ it "accepts '\\M-\\n'" do
+ Regexp.send(@method, "\M-\n").should == /#{"\x8a"}/
+ end
+
+ it "accepts '\\M-\\t'" do
+ Regexp.send(@method, "\M-\t").should == /#{"\x89"}/
+ end
+
+ it "accepts '\\M-\\r'" do
+ Regexp.send(@method, "\M-\r").should == /#{"\x8d"}/
+ end
+
+ it "accepts '\\M-\\f'" do
+ Regexp.send(@method, "\M-\f").should == /#{"\x8c"}/
+ end
+
+ it "accepts '\\M-\\v'" do
+ Regexp.send(@method, "\M-\v").should == /#{"\x8b"}/
+ end
+
+ it "accepts '\\M-\\a'" do
+ Regexp.send(@method, "\M-\a").should == /#{"\x87"}/
+ end
+
+ it "accepts '\\M-\\e'" do
+ Regexp.send(@method, "\M-\e").should == /#{"\x9b"}/
+ end
+
+ it "accepts '\\M-\\C-\\n'" do
+ Regexp.send(@method, "\M-\n").should == /#{"\x8a"}/
+ end
+
+ it "accepts '\\M-\\C-\\t'" do
+ Regexp.send(@method, "\M-\t").should == /#{"\x89"}/
+ end
+
+ it "accepts '\\M-\\C-\\r'" do
+ Regexp.send(@method, "\M-\r").should == /#{"\x8d"}/
+ end
+
+ it "accepts '\\M-\\C-\\f'" do
+ Regexp.send(@method, "\M-\f").should == /#{"\x8c"}/
+ end
+
+ it "accepts '\\M-\\C-\\v'" do
+ Regexp.send(@method, "\M-\v").should == /#{"\x8b"}/
+ end
+
+ it "accepts '\\M-\\C-\\a'" do
+ Regexp.send(@method, "\M-\a").should == /#{"\x87"}/
+ end
+
+ it "accepts '\\M-\\C-\\e'" do
+ Regexp.send(@method, "\M-\e").should == /#{"\x9b"}/
+ end
+
+ it "accepts '\\M-\\c\\n'" do
+ Regexp.send(@method, "\M-\n").should == /#{"\x8a"}/
+ end
+
+ it "accepts '\\M-\\c\\t'" do
+ Regexp.send(@method, "\M-\t").should == /#{"\x89"}/
+ end
+
+ it "accepts '\\M-\\c\\r'" do
+ Regexp.send(@method, "\M-\r").should == /#{"\x8d"}/
+ end
+
+ it "accepts '\\M-\\c\\f'" do
+ Regexp.send(@method, "\M-\f").should == /#{"\x8c"}/
+ end
+
+ it "accepts '\\M-\\c\\v'" do
+ Regexp.send(@method, "\M-\v").should == /#{"\x8b"}/
+ end
+
+ it "accepts '\\M-\\c\\a'" do
+ Regexp.send(@method, "\M-\a").should == /#{"\x87"}/
+ end
+
+ it "accepts '\\M-\\c\\e'" do
+ Regexp.send(@method, "\M-\e").should == /#{"\x9b"}/
+ end
+
+ it "accepts multiple consecutive '\\' characters" do
+ Regexp.send(@method, "\\\\\\N").should == /#{"\\\\\\"+"N"}/
+ end
+
+ it "accepts characters and escaped octal digits" do
+ Regexp.send(@method, "abc\076").should == /#{"abc\x3e"}/
+ end
+
+ it "accepts escaped octal digits and characters" do
+ Regexp.send(@method, "\076abc").should == /#{"\x3eabc"}/
+ end
+
+ it "accepts characters and escaped hexadecimal digits" do
+ Regexp.send(@method, "abc\x42").should == /#{"abc\x42"}/
+ end
+
+ it "accepts escaped hexadecimal digits and characters" do
+ Regexp.send(@method, "\x3eabc").should == /#{"\x3eabc"}/
+ end
+
+ it "accepts escaped hexadecimal and octal digits" do
+ Regexp.send(@method, "\061\x42").should == /#{"\x31\x42"}/
+ end
+
+ it "accepts \\u{H} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{f}").should == /#{"\x0f"}/
+ end
+
+ it "accepts \\u{HH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{7f}").should == /#{"\x7f"}/
+ end
+
+ it "accepts \\u{HHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{07f}").should == /#{"\x7f"}/
+ end
+
+ it "accepts \\u{HHHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{0000}").should == /#{"\x00"}/
+ end
+
+ it "accepts \\u{HHHHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{00001}").should == /#{"\x01"}/
+ end
+
+ it "accepts \\u{HHHHHH} for a single Unicode codepoint" do
+ Regexp.send(@method, "\u{000000}").should == /#{"\x00"}/
+ end
+
+ it "accepts characters followed by \\u{HHHH}" do
+ Regexp.send(@method, "abc\u{3042}").should == /#{"abc\u3042"}/
+ end
+
+ it "accepts \\u{HHHH} followed by characters" do
+ Regexp.send(@method, "\u{3042}abc").should == /#{"\u3042abc"}/
+ end
+
+ it "accepts escaped hexadecimal digits followed by \\u{HHHH}" do
+ Regexp.send(@method, "\x42\u{3042}").should == /#{"\x42\u3042"}/
+ end
+
+ it "accepts escaped octal digits followed by \\u{HHHH}" do
+ Regexp.send(@method, "\056\u{3042}").should == /#{"\x2e\u3042"}/
+ end
+
+ it "accepts a combination of escaped octal and hexadecimal digits and \\u{HHHH}" do
+ Regexp.send(@method, "\056\x42\u{3042}\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
+ end
+
+ it "accepts \\uHHHH for a single Unicode codepoint" do
+ Regexp.send(@method, "\u3042").should == /#{"\u3042"}/
+ end
+
+ it "accepts characters followed by \\uHHHH" do
+ Regexp.send(@method, "abc\u3042").should == /#{"abc\u3042"}/
+ end
+
+ it "accepts \\uHHHH followed by characters" do
+ Regexp.send(@method, "\u3042abc").should == /#{"\u3042abc"}/
+ end
+
+ it "accepts escaped hexadecimal digits followed by \\uHHHH" do
+ Regexp.send(@method, "\x42\u3042").should == /#{"\x42\u3042"}/
+ end
+
+ it "accepts escaped octal digits followed by \\uHHHH" do
+ Regexp.send(@method, "\056\u3042").should == /#{"\x2e\u3042"}/
+ end
+
+ it "accepts a combination of escaped octal and hexadecimal digits and \\uHHHH" do
+ Regexp.send(@method, "\056\x42\u3042\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
+ end
+
+ it "raises a RegexpError if less than four digits are given for \\uHHHH" do
+ lambda { Regexp.send(@method, "\\" + "u304") }.should raise_error(RegexpError)
+ end
+
+ it "raises a RegexpError if the \\u{} escape is empty" do
+ lambda { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError)
+ end
+
+ it "raises a RegexpError if more than six hexadecimal digits are given" do
+ lambda { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError)
+ end
+
+ it "returns a Regexp with US-ASCII encoding if only 7-bit ASCII characters are present regardless of the input String's encoding" do
+ Regexp.send(@method, "abc").encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with source String having US-ASCII encoding if only 7-bit ASCII characters are present regardless of the input String's encoding" do
+ Regexp.send(@method, "abc").source.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with US-ASCII encoding if UTF-8 escape sequences using only 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{61}").encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with source String having US-ASCII encoding if UTF-8 escape sequences using only 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{61}").source.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with UTF-8 encoding if any UTF-8 escape sequences outside 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{ff}").encoding.should == Encoding::UTF_8
+ end
+
+ it "returns a Regexp with source String having UTF-8 encoding if any UTF-8 escape sequences outside 7-bit ASCII are present" do
+ Regexp.send(@method, "\u{ff}").source.encoding.should == Encoding::UTF_8
+ end
+
+ it "returns a Regexp with the input String's encoding" do
+ str = "\x82\xa0".force_encoding(Encoding::Shift_JIS)
+ Regexp.send(@method, str).encoding.should == Encoding::Shift_JIS
+ end
+
+ it "returns a Regexp with source String having the input String's encoding" do
+ str = "\x82\xa0".force_encoding(Encoding::Shift_JIS)
+ Regexp.send(@method, str).source.encoding.should == Encoding::Shift_JIS
+ end
+ end
+end
+
+describe :regexp_new_regexp_ascii_8bit, shared: true do
+ it "uses the argument as a literal to construct a Regexp object" do
+ Regexp.send(@method, /^hi{2,3}fo.o$/).should == /^hi{2,3}fo.o$/
+ end
+
+ it "preserves any options given in the Regexp literal" do
+ (Regexp.send(@method, /Hi/i).options & Regexp::IGNORECASE).should_not == 0
+ (Regexp.send(@method, /Hi/m).options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (Regexp.send(@method, /Hi/x).options & Regexp::EXTENDED).should_not == 0
+ end
+
+ not_supported_on :opal do
+ r = Regexp.send @method, /Hi/imx
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ (r.options & Regexp::EXTENDED).should_not == 0
+ end
+
+ r = Regexp.send @method, /Hi/
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
+ end
+ end
+
+ it "does not honour options given as additional arguments" do
+ r = nil
+ lambda {
+ r = Regexp.send @method, /hi/, Regexp::IGNORECASE
+ }.should complain(/flags ignored/)
+ (r.options & Regexp::IGNORECASE).should == 0
+ end
+
+ not_supported_on :opal do
+ it "sets the encoding to UTF-8 if the Regexp literal has the 'u' option" do
+ Regexp.send(@method, /Hi/u).encoding.should == Encoding::UTF_8
+ end
+
+ it "sets the encoding to EUC-JP if the Regexp literal has the 'e' option" do
+ Regexp.send(@method, /Hi/e).encoding.should == Encoding::EUC_JP
+ end
+
+ it "sets the encoding to Windows-31J if the Regexp literal has the 's' option" do
+ Regexp.send(@method, /Hi/s).encoding.should == Encoding::Windows_31J
+ end
+
+ it "sets the encoding to US-ASCII if the Regexp literal has the 'n' option and the source String is ASCII only" do
+ Regexp.send(@method, /Hi/n).encoding.should == Encoding::US_ASCII
+ end
+
+ it "sets the encoding to source String's encoding if the Regexp literal has the 'n' option and the source String is not ASCII only" do
+ Regexp.send(@method, Regexp.new("\\xff", nil, 'n')).encoding.should == Encoding::ASCII_8BIT
+ end
+ end
+end
diff --git a/spec/ruby/core/regexp/shared/quote.rb b/spec/ruby/core/regexp/shared/quote.rb
new file mode 100644
index 0000000000..016cb0b164
--- /dev/null
+++ b/spec/ruby/core/regexp/shared/quote.rb
@@ -0,0 +1,31 @@
+# -*- encoding: ascii-8bit -*-
+
+describe :regexp_quote, shared: true do
+ it "escapes any characters with special meaning in a regular expression" do
+ Regexp.send(@method, '\*?{}.+^[]()- ').should == '\\\\\*\?\{\}\.\+\^\[\]\(\)\-\\ '
+ Regexp.send(@method, "\*?{}.+^[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\[\\]\\(\\)\\-\\ '
+ Regexp.send(@method, '\n\r\f\t').should == '\\\\n\\\\r\\\\f\\\\t'
+ Regexp.send(@method, "\n\r\f\t").should == '\\n\\r\\f\\t'
+ end
+
+ it "works with symbols" do
+ Regexp.send(@method, :symbol).should == 'symbol'
+ end
+
+ it "sets the encoding of the result to US-ASCII if there are only US-ASCII characters present in the input String" do
+ str = "abc".force_encoding("euc-jp")
+ Regexp.send(@method, str).encoding.should == Encoding::US_ASCII
+ end
+
+ it "sets the encoding of the result to the encoding of the String if any non-US-ASCII characters are present in an input String with valid encoding" do
+ str = "ありがとう".force_encoding("utf-8")
+ str.valid_encoding?.should be_true
+ Regexp.send(@method, str).encoding.should == Encoding::UTF_8
+ end
+
+ it "sets the encoding of the result to ASCII-8BIT if any non-US-ASCII characters are present in an input String with invalid encoding" do
+ str = "\xff".force_encoding "us-ascii"
+ str.valid_encoding?.should be_false
+ Regexp.send(@method, "\xff").encoding.should == Encoding::ASCII_8BIT
+ end
+end
diff --git a/spec/ruby/core/regexp/source_spec.rb b/spec/ruby/core/regexp/source_spec.rb
new file mode 100644
index 0000000000..3960a09395
--- /dev/null
+++ b/spec/ruby/core/regexp/source_spec.rb
@@ -0,0 +1,29 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#source" do
+ it "returns the original string of the pattern" do
+ not_supported_on :opal do
+ /ab+c/ix.source.should == "ab+c"
+ end
+ /x(.)xz/.source.should == "x(.)xz"
+ end
+
+ it "will remove escape characters" do
+ /foo\/bar/.source.should == "foo/bar"
+ end
+
+ not_supported_on :opal do
+ it "has US-ASCII encoding when created from an ASCII-only \\u{} literal" do
+ re = /[\u{20}-\u{7E}]/
+ re.source.encoding.should equal(Encoding::US_ASCII)
+ end
+ end
+
+ not_supported_on :opal do
+ it "has UTF-8 encoding when created from a non-ASCII-only \\u{} literal" do
+ re = /[\u{20}-\u{7EE}]/
+ re.source.encoding.should equal(Encoding::UTF_8)
+ end
+ end
+end
diff --git a/spec/ruby/core/regexp/to_s_spec.rb b/spec/ruby/core/regexp/to_s_spec.rb
new file mode 100644
index 0000000000..a23fd78975
--- /dev/null
+++ b/spec/ruby/core/regexp/to_s_spec.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp#to_s" do
+ not_supported_on :opal do
+ it "displays options if included" do
+ /abc/mxi.to_s.should == "(?mix:abc)"
+ end
+ end
+
+ it "shows non-included options after a - sign" do
+ /abc/i.to_s.should == "(?i-mx:abc)"
+ end
+
+ it "shows all options as excluded if none are selected" do
+ /abc/.to_s.should == "(?-mix:abc)"
+ end
+
+ it "shows the pattern after the options" do
+ not_supported_on :opal do
+ /ab+c/mix.to_s.should == "(?mix:ab+c)"
+ end
+ /xyz/.to_s.should == "(?-mix:xyz)"
+ end
+
+ not_supported_on :opal do
+ it "displays groups with options" do
+ /(?ix:foo)(?m:bar)/.to_s.should == "(?-mix:(?ix:foo)(?m:bar))"
+ /(?ix:foo)bar/m.to_s.should == "(?m-ix:(?ix:foo)bar)"
+ end
+
+ it "displays single group with same options as main regex as the main regex" do
+ /(?i:nothing outside this group)/.to_s.should == "(?i-mx:nothing outside this group)"
+ end
+ end
+
+ not_supported_on :opal do
+ it "deals properly with uncaptured groups" do
+ /whatever(?:0d)/ix.to_s.should == "(?ix-m:whatever(?:0d))"
+ end
+ end
+
+ it "deals properly with the two types of lookahead groups" do
+ /(?=5)/.to_s.should == "(?-mix:(?=5))"
+ /(?!5)/.to_s.should == "(?-mix:(?!5))"
+ end
+
+ it "returns a string in (?xxx:yyy) notation" do
+ not_supported_on :opal do
+ /ab+c/ix.to_s.should == "(?ix-m:ab+c)"
+ /jis/s.to_s.should == "(?-mix:jis)"
+ /(?i:.)/.to_s.should == "(?i-mx:.)"
+ end
+ /(?:.)/.to_s.should == "(?-mix:.)"
+ end
+
+ not_supported_on :opal do
+ it "handles abusive option groups" do
+ /(?mmmmix-miiiix:)/.to_s.should == '(?-mix:)'
+ end
+ end
+
+end
diff --git a/spec/ruby/core/regexp/try_convert_spec.rb b/spec/ruby/core/regexp/try_convert_spec.rb
new file mode 100644
index 0000000000..e782fc07fb
--- /dev/null
+++ b/spec/ruby/core/regexp/try_convert_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp.try_convert" do
+ not_supported_on :opal do
+ it "returns the argument if given a Regexp" do
+ Regexp.try_convert(/foo/s).should == /foo/s
+ end
+ end
+
+ it "returns nil if given an argument that can't be converted to a Regexp" do
+ ['', 'glark', [], Object.new, :pat].each do |arg|
+ Regexp.try_convert(arg).should be_nil
+ end
+ end
+
+ it "tries to coerce the argument by calling #to_regexp" do
+ rex = mock('regexp')
+ rex.should_receive(:to_regexp).and_return(/(p(a)t[e]rn)/)
+ Regexp.try_convert(rex).should == /(p(a)t[e]rn)/
+ end
+end
diff --git a/spec/ruby/core/regexp/union_spec.rb b/spec/ruby/core/regexp/union_spec.rb
new file mode 100644
index 0000000000..0f62747753
--- /dev/null
+++ b/spec/ruby/core/regexp/union_spec.rb
@@ -0,0 +1,149 @@
+# encoding: utf-8
+
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "Regexp.union" do
+ it "returns /(?!)/ when passed no arguments" do
+ Regexp.union.should == /(?!)/
+ end
+
+ it "returns a regular expression that will match passed arguments" do
+ Regexp.union("penzance").should == /penzance/
+ Regexp.union("skiing", "sledding").should == /skiing|sledding/
+ not_supported_on :opal do
+ Regexp.union(/dogs/, /cats/i).should == /(?-mix:dogs)|(?i-mx:cats)/
+ end
+ end
+
+ it "quotes any string arguments" do
+ Regexp.union("n", ".").should == /n|\./
+ end
+
+ it "returns a Regexp with the encoding of an ASCII-incompatible String argument" do
+ Regexp.union("a".encode("UTF-16LE")).encoding.should == Encoding::UTF_16LE
+ end
+
+ it "returns a Regexp with the encoding of a String containing non-ASCII-compatible characters" do
+ Regexp.union("\u00A9".encode("ISO-8859-1")).encoding.should == Encoding::ISO_8859_1
+ end
+
+ it "returns a Regexp with US-ASCII encoding if all arguments are ASCII-only" do
+ Regexp.union("a".encode("UTF-8"), "b".encode("SJIS")).encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns a Regexp with the encoding of multiple non-conflicting ASCII-incompatible String arguments" do
+ Regexp.union("a".encode("UTF-16LE"), "b".encode("UTF-16LE")).encoding.should == Encoding::UTF_16LE
+ end
+
+ it "returns a Regexp with the encoding of multiple non-conflicting Strings containing non-ASCII-compatible characters" do
+ Regexp.union("\u00A9".encode("ISO-8859-1"), "\u00B0".encode("ISO-8859-1")).encoding.should == Encoding::ISO_8859_1
+ end
+
+ it "returns a Regexp with the encoding of a String containing non-ASCII-compatible characters and another ASCII-only String" do
+ Regexp.union("\u00A9".encode("ISO-8859-1"), "a".encode("UTF-8")).encoding.should == Encoding::ISO_8859_1
+ end
+
+ it "returns a Regexp with UTF-8 if one part is UTF-8" do
+ Regexp.union(/probl[éeè]me/i, /help/i).encoding.should == Encoding::UTF_8
+ end
+
+ it "returns a Regexp if an array of string with special characters is passed" do
+ Regexp.union(["+","-"]).should == /\+|\-/
+ end
+
+ it "raises ArgumentError if the arguments include conflicting ASCII-incompatible Strings" do
+ lambda {
+ Regexp.union("a".encode("UTF-16LE"), "b".encode("UTF-16BE"))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include conflicting ASCII-incompatible Regexps" do
+ lambda {
+ Regexp.union(Regexp.new("a".encode("UTF-16LE")),
+ Regexp.new("b".encode("UTF-16BE")))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include conflicting fixed encoding Regexps" do
+ lambda {
+ Regexp.union(Regexp.new("a".encode("UTF-8"), Regexp::FIXEDENCODING),
+ Regexp.new("b".encode("US-ASCII"), Regexp::FIXEDENCODING))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include a fixed encoding Regexp and a String containing non-ASCII-compatible characters in a different encoding" do
+ lambda {
+ Regexp.union(Regexp.new("a".encode("UTF-8"), Regexp::FIXEDENCODING),
+ "\u00A9".encode("ISO-8859-1"))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include a String containing non-ASCII-compatible characters and a fixed encoding Regexp in a different encoding" do
+ lambda {
+ Regexp.union("\u00A9".encode("ISO-8859-1"),
+ Regexp.new("a".encode("UTF-8"), Regexp::FIXEDENCODING))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible String and an ASCII-only String" do
+ lambda {
+ Regexp.union("a".encode("UTF-16LE"), "b".encode("UTF-8"))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and an ASCII-only String" do
+ lambda {
+ Regexp.union(Regexp.new("a".encode("UTF-16LE")), "b".encode("UTF-8"))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible String and an ASCII-only Regexp" do
+ lambda {
+ Regexp.union("a".encode("UTF-16LE"), Regexp.new("b".encode("UTF-8")))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and an ASCII-only Regexp" do
+ lambda {
+ Regexp.union(Regexp.new("a".encode("UTF-16LE")), Regexp.new("b".encode("UTF-8")))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible String and a String containing non-ASCII-compatible characters in a different encoding" do
+ lambda {
+ Regexp.union("a".encode("UTF-16LE"), "\u00A9".encode("ISO-8859-1"))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and a String containing non-ASCII-compatible characters in a different encoding" do
+ lambda {
+ Regexp.union(Regexp.new("a".encode("UTF-16LE")), "\u00A9".encode("ISO-8859-1"))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible String and a Regexp containing non-ASCII-compatible characters in a different encoding" do
+ lambda {
+ Regexp.union("a".encode("UTF-16LE"), Regexp.new("\u00A9".encode("ISO-8859-1")))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if the arguments include an ASCII-incompatible Regexp and a Regexp containing non-ASCII-compatible characters in a different encoding" do
+ lambda {
+ Regexp.union(Regexp.new("a".encode("UTF-16LE")), Regexp.new("\u00A9".encode("ISO-8859-1")))
+ }.should raise_error(ArgumentError)
+ end
+
+ it "uses to_str to convert arguments (if not Regexp)" do
+ obj = mock('pattern')
+ obj.should_receive(:to_str).and_return('foo')
+ Regexp.union(obj, "bar").should == /foo|bar/
+ end
+
+ it "accepts a single array of patterns as arguments" do
+ Regexp.union(["skiing", "sledding"]).should == /skiing|sledding/
+ not_supported_on :opal do
+ Regexp.union([/dogs/, /cats/i]).should == /(?-mix:dogs)|(?i-mx:cats)/
+ end
+ lambda{Regexp.union(["skiing", "sledding"], [/dogs/, /cats/i])}.should raise_error(TypeError)
+ end
+end