summaryrefslogtreecommitdiff
path: root/spec/ruby/core
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-29 00:22:52 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-29 00:22:52 +0000
commit2076c2c3c401d9ab9324468818bbc46d4e4b870a (patch)
tree1697bf7d3f434e49cafd8a8c1579f2d065a7de56 /spec/ruby/core
parent548defb608847973e78462a38c8418f90dce9911 (diff)
Update to ruby/spec@944ea57
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66622 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby/core')
-rw-r--r--spec/ruby/core/array/difference_spec.rb24
-rw-r--r--spec/ruby/core/array/minus_spec.rb84
-rw-r--r--spec/ruby/core/array/pack/l_spec.rb16
-rw-r--r--spec/ruby/core/array/shared/difference.rb78
-rw-r--r--spec/ruby/core/array/shared/union.rb79
-rw-r--r--spec/ruby/core/array/union_spec.rb87
-rw-r--r--spec/ruby/core/dir/shared/open.rb9
-rw-r--r--spec/ruby/core/file/atime_spec.rb2
-rw-r--r--spec/ruby/core/file/ctime_spec.rb2
-rw-r--r--spec/ruby/core/file/mtime_spec.rb2
-rw-r--r--spec/ruby/core/file/reopen_spec.rb2
-rw-r--r--spec/ruby/core/file/utime_spec.rb54
-rw-r--r--spec/ruby/core/float/round_spec.rb8
-rw-r--r--spec/ruby/core/io/dup_spec.rb20
-rw-r--r--spec/ruby/core/io/reopen_spec.rb24
-rw-r--r--spec/ruby/core/kernel/match_spec.rb22
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb25
-rw-r--r--spec/ruby/core/marshal/shared/load.rb113
-rw-r--r--spec/ruby/core/matchdata/begin_spec.rb108
-rw-r--r--spec/ruby/core/matchdata/end_spec.rb108
-rw-r--r--spec/ruby/core/matchdata/named_captures_spec.rb4
-rw-r--r--spec/ruby/core/module/name_spec.rb10
-rw-r--r--spec/ruby/core/process/clock_gettime_spec.rb8
-rw-r--r--spec/ruby/core/process/kill_spec.rb6
-rw-r--r--spec/ruby/core/process/spawn_spec.rb88
-rw-r--r--spec/ruby/core/string/scan_spec.rb5
-rw-r--r--spec/ruby/core/string/unpack/l_spec.rb16
27 files changed, 697 insertions, 307 deletions
diff --git a/spec/ruby/core/array/difference_spec.rb b/spec/ruby/core/array/difference_spec.rb
new file mode 100644
index 0000000000..33ea8e1f3c
--- /dev/null
+++ b/spec/ruby/core/array/difference_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative 'shared/difference'
+
+ruby_version_is "2.6" do
+ describe "Array#difference" do
+ it_behaves_like :array_binary_difference, :-
+
+ it "returns a copy when called without any parameter" do
+ x = [1, 2, 3, 2]
+ x.difference.should == x
+ x.difference.should_not equal x
+ end
+
+ it "does not return subclass instances for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].difference.should be_an_instance_of(Array)
+ end
+
+ it "accepts multiple arguments" do
+ x = [1, 2, 3, 1]
+ x.difference([], [0, 1], [3, 4], [3]).should == [2]
+ end
+ end
+end
diff --git a/spec/ruby/core/array/minus_spec.rb b/spec/ruby/core/array/minus_spec.rb
index 8cb6bb323c..cb1bf56d76 100644
--- a/spec/ruby/core/array/minus_spec.rb
+++ b/spec/ruby/core/array/minus_spec.rb
@@ -1,87 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/difference'
describe "Array#-" do
- it "creates an array minus any items from other array" do
- ([] - [ 1, 2, 4 ]).should == []
- ([1, 2, 4] - []).should == [1, 2, 4]
- ([ 1, 2, 3, 4, 5 ] - [ 1, 2, 4 ]).should == [3, 5]
- end
-
- it "removes multiple items on the lhs equal to one on the rhs" do
- ([1, 1, 2, 2, 3, 3, 4, 5] - [1, 2, 4]).should == [3, 3, 5]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- (empty - empty).should == []
-
- ([] - ArraySpecs.recursive_array).should == []
-
- array = ArraySpecs.recursive_array
- (array - array).should == []
- end
-
- it "tries to convert the passed arguments to Arrays using #to_ary" do
- obj = mock('[2,3,3,4]')
- obj.should_receive(:to_ary).and_return([2, 3, 3, 4])
- ([1, 1, 2, 2, 3, 4] - obj).should == [1, 1]
- end
-
- it "raises a TypeError if the argument cannot be coerced to an Array by calling #to_ary" do
- obj = mock('not an array')
- lambda { [1, 2, 3] - obj }.should raise_error(TypeError)
- end
-
- it "does not return subclass instance for Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] - []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] - ArraySpecs::MyArray[]).should be_an_instance_of(Array)
- ([1, 2, 3] - ArraySpecs::MyArray[]).should be_an_instance_of(Array)
- end
-
- it "does not call to_ary on array subclasses" do
- ([5, 6, 7] - ArraySpecs::ToAryArray[7]).should == [5, 6]
- end
-
- it "removes an item identified as equivalent via #hash and #eql?" do
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(true)
-
- ([obj1] - [obj2]).should == []
- ([obj1, obj1, obj2, obj2] - [obj2]).should == []
- end
-
- it "doesn't remove an item with the same hash but not #eql?" do
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(false)
-
- ([obj1] - [obj2]).should == [obj1]
- ([obj1, obj1, obj2, obj2] - [obj2]).should == [obj1, obj1]
- end
-
- it "removes an identical item even when its #eql? isn't reflexive" do
- x = mock('x')
- x.stub!(:hash).and_return(42)
- x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
-
- ([x] - [x]).should == []
- end
-
- it "is not destructive" do
- a = [1, 2, 3]
- a - []
- a.should == [1, 2, 3]
- a - [1]
- a.should == [1, 2, 3]
- a - [1,2,3]
- a.should == [1, 2, 3]
- a - [:a, :b, :c]
- a.should == [1, 2, 3]
- end
+ it_behaves_like :array_binary_difference, :-
end
diff --git a/spec/ruby/core/array/pack/l_spec.rb b/spec/ruby/core/array/pack/l_spec.rb
index 0a5552b984..b446a7a36a 100644
--- a/spec/ruby/core/array/pack/l_spec.rb
+++ b/spec/ruby/core/array/pack/l_spec.rb
@@ -29,7 +29,7 @@ describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_32bit_be, 'L>'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'L<_'
it_behaves_like :array_pack_32bit_le, 'L_<'
@@ -51,7 +51,7 @@ describe "Array#pack with format 'L'" do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'L<_'
it_behaves_like :array_pack_64bit_le, 'L_<'
@@ -83,7 +83,7 @@ describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_32bit_be, 'l>'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'l<_'
it_behaves_like :array_pack_32bit_le, 'l_<'
@@ -105,7 +105,7 @@ describe "Array#pack with format 'l'" do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'l<_'
it_behaves_like :array_pack_64bit_le, 'l_<'
@@ -137,7 +137,7 @@ little_endian do
it_behaves_like :array_pack_32bit_le, 'l'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'L_'
end
@@ -155,7 +155,7 @@ little_endian do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'L_'
end
@@ -183,7 +183,7 @@ big_endian do
it_behaves_like :array_pack_32bit_be, 'l'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'L_'
end
@@ -201,7 +201,7 @@ big_endian do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'L_'
end
diff --git a/spec/ruby/core/array/shared/difference.rb b/spec/ruby/core/array/shared/difference.rb
new file mode 100644
index 0000000000..c43a6375e0
--- /dev/null
+++ b/spec/ruby/core/array/shared/difference.rb
@@ -0,0 +1,78 @@
+describe :array_binary_difference, shared: true do
+ it "creates an array minus any items from other array" do
+ [].send(@method, [ 1, 2, 4 ]).should == []
+ [1, 2, 4].send(@method, []).should == [1, 2, 4]
+ [ 1, 2, 3, 4, 5 ].send(@method, [ 1, 2, 4 ]).should == [3, 5]
+ end
+
+ it "removes multiple items on the lhs equal to one on the rhs" do
+ [1, 1, 2, 2, 3, 3, 4, 5].send(@method, [1, 2, 4]).should == [3, 3, 5]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.send(@method, empty).should == []
+
+ [].send(@method, ArraySpecs.recursive_array).should == []
+
+ array = ArraySpecs.recursive_array
+ array.send(@method, array).should == []
+ end
+
+ it "tries to convert the passed arguments to Arrays using #to_ary" do
+ obj = mock('[2,3,3,4]')
+ obj.should_receive(:to_ary).and_return([2, 3, 3, 4])
+ [1, 1, 2, 2, 3, 4].send(@method, obj).should == [1, 1]
+ end
+
+ it "raises a TypeError if the argument cannot be coerced to an Array by calling #to_ary" do
+ obj = mock('not an array')
+ lambda { [1, 2, 3].send(@method, obj) }.should raise_error(TypeError)
+ end
+
+ it "does not return subclass instance for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[]).should be_an_instance_of(Array)
+ [1, 2, 3].send(@method, ArraySpecs::MyArray[]).should be_an_instance_of(Array)
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [5, 6, 7].send(@method, ArraySpecs::ToAryArray[7]).should == [5, 6]
+ end
+
+ it "removes an item identified as equivalent via #hash and #eql?" do
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(true)
+
+ [obj1].send(@method, [obj2]).should == []
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == []
+ end
+
+ it "doesn't remove an item with the same hash but not #eql?" do
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(false)
+
+ [obj1].send(@method, [obj2]).should == [obj1]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1, obj1]
+ end
+
+ it "removes an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].send(@method, [x]).should == []
+ end
+
+ it "is not destructive" do
+ a = [1, 2, 3]
+ a.send(@method, [1])
+ a.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/array/shared/union.rb b/spec/ruby/core/array/shared/union.rb
new file mode 100644
index 0000000000..12a98cc9fe
--- /dev/null
+++ b/spec/ruby/core/array/shared/union.rb
@@ -0,0 +1,79 @@
+describe :array_binary_union, shared: true do
+ it "returns an array of elements that appear in either array (union)" do
+ [].send(@method, []).should == []
+ [1, 2].send(@method, []).should == [1, 2]
+ [].send(@method, [1, 2]).should == [1, 2]
+ [ 1, 2, 3, 4 ].send(@method, [ 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
+ end
+
+ it "creates an array with no duplicates" do
+ [ 1, 2, 3, 1, 4, 5 ].send(@method, [ 1, 3, 4, 5, 3, 6 ]).should == [1, 2, 3, 4, 5, 6]
+ end
+
+ it "creates an array with elements in order they are first encountered" do
+ [ 1, 2, 3, 1 ].send(@method, [ 1, 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.send(@method, empty).should == empty
+
+ array = ArraySpecs.recursive_array
+ array.send(@method, []).should == [1, 'two', 3.0, array]
+ [].send(@method, array).should == [1, 'two', 3.0, array]
+ array.send(@method, array).should == [1, 'two', 3.0, array]
+ array.send(@method, empty).should == [1, 'two', 3.0, array, empty]
+ end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('[1,2,3]')
+ obj.should_receive(:to_ary).and_return([1, 2, 3])
+ [0].send(@method, obj).should == ([0] | [1, 2, 3])
+ end
+
+ # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Fixnum/Symbol
+ it "acts as if using an intermediate hash to collect values" do
+ not_supported_on :opal do
+ [5.0, 4.0].send(@method, [5, 4]).should == [5.0, 4.0, 5, 4]
+ end
+
+ str = "x"
+ [str].send(@method, [str.dup]).should == [str]
+
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj2.should_receive(:eql?).at_least(1).and_return(true)
+
+ [obj1].send(@method, [obj2]).should == [obj1]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1]
+
+ obj1 = mock('3')
+ obj2 = mock('4')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj2.should_receive(:eql?).at_least(1).and_return(false)
+
+ [obj1].send(@method, [obj2]).should == [obj1, obj2]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1, obj2]
+ end
+
+ it "does not return subclass instances for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
+ [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [1, 2].send(@method, ArraySpecs::ToAryArray[5, 6]).should == [1, 2, 5, 6]
+ end
+
+ it "properly handles an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].send(@method, [x]).should == [x]
+ end
+end
diff --git a/spec/ruby/core/array/union_spec.rb b/spec/ruby/core/array/union_spec.rb
index 0e177715e5..1dca47696d 100644
--- a/spec/ruby/core/array/union_spec.rb
+++ b/spec/ruby/core/array/union_spec.rb
@@ -1,82 +1,27 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/union'
describe "Array#|" do
- it "returns an array of elements that appear in either array (union)" do
- ([] | []).should == []
- ([1, 2] | []).should == [1, 2]
- ([] | [1, 2]).should == [1, 2]
- ([ 1, 2, 3, 4 ] | [ 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
- end
-
- it "creates an array with no duplicates" do
- ([ 1, 2, 3, 1, 4, 5 ] | [ 1, 3, 4, 5, 3, 6 ]).should == [1, 2, 3, 4, 5, 6]
- end
-
- it "creates an array with elements in order they are first encountered" do
- ([ 1, 2, 3, 1 ] | [ 1, 3, 4, 5 ]).should == [1, 2, 3, 4, 5]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- (empty | empty).should == empty
+ it_behaves_like :array_binary_union, :|
+end
- array = ArraySpecs.recursive_array
- (array | []).should == [1, 'two', 3.0, array]
- ([] | array).should == [1, 'two', 3.0, array]
- (array | array).should == [1, 'two', 3.0, array]
- (array | empty).should == [1, 'two', 3.0, array, empty]
- end
+ruby_version_is "2.6" do
+ describe "Array#union" do
+ it_behaves_like :array_binary_union, :union
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('[1,2,3]')
- obj.should_receive(:to_ary).and_return([1, 2, 3])
- ([0] | obj).should == ([0] | [1, 2, 3])
- end
-
- # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Fixnum/Symbol
- it "acts as if using an intermediate hash to collect values" do
- not_supported_on :opal do
- ([5.0, 4.0] | [5, 4]).should == [5.0, 4.0, 5, 4]
+ it "returns unique elements when given no argument" do
+ x = [1, 2, 3, 2]
+ x.union.should == [1, 2, 3]
end
- str = "x"
- ([str] | [str.dup]).should == [str]
-
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj2.should_receive(:eql?).at_least(1).and_return(true)
-
- ([obj1] | [obj2]).should == [obj1]
- ([obj1, obj1, obj2, obj2] | [obj2]).should == [obj1]
-
- obj1 = mock('3')
- obj2 = mock('4')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj2.should_receive(:eql?).at_least(1).and_return(false)
-
- ([obj1] | [obj2]).should == [obj1, obj2]
- ([obj1, obj1, obj2, obj2] | [obj2]).should == [obj1, obj2]
- end
-
- it "does not return subclass instances for Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] | []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] | ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- ([] | ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- end
-
- it "does not call to_ary on array subclasses" do
- ([1, 2] | ArraySpecs::ToAryArray[5, 6]).should == [1, 2, 5, 6]
- end
-
- it "properly handles an identical item even when its #eql? isn't reflexive" do
- x = mock('x')
- x.stub!(:hash).and_return(42)
- x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+ it "does not return subclass instances for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].union.should be_an_instance_of(Array)
+ end
- ([x] | [x]).should == [x]
+ it "accepts multiple arguments" do
+ x = [1, 2, 3]
+ x.union(x, x, x, x, [3, 4], x).should == [1, 2, 3, 4]
+ end
end
end
diff --git a/spec/ruby/core/dir/shared/open.rb b/spec/ruby/core/dir/shared/open.rb
index 7f4fe5c2a6..6df361e452 100644
--- a/spec/ruby/core/dir/shared/open.rb
+++ b/spec/ruby/core/dir/shared/open.rb
@@ -60,4 +60,13 @@ describe :dir_open, shared: true do
dir = Dir.send(@method, DirSpecs.mock_dir, encoding: nil) {|d| d }
dir.should be_kind_of(Dir)
end
+
+ platform_is_not :windows do
+ it 'sets the close-on-exec flag for the directory file descriptor' do
+ Dir.send(@method, DirSpecs.mock_dir) do |dir|
+ io = IO.for_fd(dir.fileno)
+ io.close_on_exec?.should == true
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/file/atime_spec.rb b/spec/ruby/core/file/atime_spec.rb
index d4106c0411..c791aa6d74 100644
--- a/spec/ruby/core/file/atime_spec.rb
+++ b/spec/ruby/core/file/atime_spec.rb
@@ -15,7 +15,7 @@ describe "File.atime" do
File.atime(@file).should be_kind_of(Time)
end
- platform_is :linux do
+ guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do
## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed.
it "returns the last access time for the named file with microseconds" do
supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d+)/, 1], 10)
diff --git a/spec/ruby/core/file/ctime_spec.rb b/spec/ruby/core/file/ctime_spec.rb
index 50ffbe6a79..5753e0d90e 100644
--- a/spec/ruby/core/file/ctime_spec.rb
+++ b/spec/ruby/core/file/ctime_spec.rb
@@ -14,7 +14,7 @@ describe "File.ctime" do
File.ctime(@file).should be_kind_of(Time)
end
- platform_is :linux do
+ guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do
it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself) with microseconds." do
supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d+)/, 1], 10)
if supports_subseconds != 0
diff --git a/spec/ruby/core/file/mtime_spec.rb b/spec/ruby/core/file/mtime_spec.rb
index 4c26cb5dac..d5769c0584 100644
--- a/spec/ruby/core/file/mtime_spec.rb
+++ b/spec/ruby/core/file/mtime_spec.rb
@@ -15,7 +15,7 @@ describe "File.mtime" do
File.mtime(@filename).should be_close(@mtime, 2.0)
end
- platform_is :linux do
+ guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do
it "returns the modification Time of the file with microseconds" do
supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d+)/, 1], 10)
if supports_subseconds != 0
diff --git a/spec/ruby/core/file/reopen_spec.rb b/spec/ruby/core/file/reopen_spec.rb
index 2d79129320..858d424c67 100644
--- a/spec/ruby/core/file/reopen_spec.rb
+++ b/spec/ruby/core/file/reopen_spec.rb
@@ -25,7 +25,7 @@ describe "File#reopen" do
@file.read.should == @content_b
end
- it "calls #to_path to convern an Object" do
+ it "calls #to_path to convert an Object" do
@file = File.new(@name_a).reopen(mock_to_path(@name_b), "r")
@file.read.should == @content_b
end
diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb
index 542681ea93..64af82ef19 100644
--- a/spec/ruby/core/file/utime_spec.rb
+++ b/spec/ruby/core/file/utime_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
describe "File.utime" do
+
+ before :all do
+ @time_is_float = /mswin|mingw/ =~ RUBY_PLATFORM && RUBY_VERSION >= '2.5'
+ end
+
before :each do
@atime = Time.now
@mtime = Time.now
@@ -16,18 +21,33 @@ describe "File.utime" do
it "sets the access and modification time of each file" do
File.utime(@atime, @mtime, @file1, @file2)
- File.atime(@file1).to_i.should be_close(@atime.to_i, 2)
- File.mtime(@file1).to_i.should be_close(@mtime.to_i, 2)
- File.atime(@file2).to_i.should be_close(@atime.to_i, 2)
- File.mtime(@file2).to_i.should be_close(@mtime.to_i, 2)
+ if @time_is_float
+ File.atime(@file1).should be_close(@atime, 0.0001)
+ File.mtime(@file1).should be_close(@mtime, 0.0001)
+ File.atime(@file2).should be_close(@atime, 0.0001)
+ File.mtime(@file2).should be_close(@mtime, 0.0001)
+ else
+ File.atime(@file1).to_i.should be_close(@atime.to_i, 2)
+ File.mtime(@file1).to_i.should be_close(@mtime.to_i, 2)
+ File.atime(@file2).to_i.should be_close(@atime.to_i, 2)
+ File.mtime(@file2).to_i.should be_close(@mtime.to_i, 2)
+ end
end
it "uses the current times if two nil values are passed" do
+ tn = Time.now
File.utime(nil, nil, @file1, @file2)
- File.atime(@file1).to_i.should be_close(Time.now.to_i, 2)
- File.mtime(@file1).to_i.should be_close(Time.now.to_i, 2)
- File.atime(@file2).to_i.should be_close(Time.now.to_i, 2)
- File.mtime(@file2).to_i.should be_close(Time.now.to_i, 2)
+ if @time_is_float
+ File.atime(@file1).should be_close(tn, 0.050)
+ File.mtime(@file1).should be_close(tn, 0.050)
+ File.atime(@file2).should be_close(tn, 0.050)
+ File.mtime(@file2).should be_close(tn, 0.050)
+ else
+ File.atime(@file1).to_i.should be_close(Time.now.to_i, 2)
+ File.mtime(@file1).to_i.should be_close(Time.now.to_i, 2)
+ File.atime(@file2).to_i.should be_close(Time.now.to_i, 2)
+ File.mtime(@file2).to_i.should be_close(Time.now.to_i, 2)
+ end
end
it "accepts an object that has a #to_path method" do
@@ -35,11 +55,19 @@ describe "File.utime" do
end
it "accepts numeric atime and mtime arguments" do
- File.utime(@atime.to_i, @mtime.to_i, @file1, @file2)
- File.atime(@file1).to_i.should be_close(@atime.to_i, 2)
- File.mtime(@file1).to_i.should be_close(@mtime.to_i, 2)
- File.atime(@file2).to_i.should be_close(@atime.to_i, 2)
- File.mtime(@file2).to_i.should be_close(@mtime.to_i, 2)
+ if @time_is_float
+ File.utime(@atime.to_f, @mtime.to_f, @file1, @file2)
+ File.atime(@file1).should be_close(@atime, 0.0001)
+ File.mtime(@file1).should be_close(@mtime, 0.0001)
+ File.atime(@file2).should be_close(@atime, 0.0001)
+ File.mtime(@file2).should be_close(@mtime, 0.0001)
+ else
+ File.utime(@atime.to_i, @mtime.to_i, @file1, @file2)
+ File.atime(@file1).to_i.should be_close(@atime.to_i, 2)
+ File.mtime(@file1).to_i.should be_close(@mtime.to_i, 2)
+ File.atime(@file2).to_i.should be_close(@atime.to_i, 2)
+ File.mtime(@file2).to_i.should be_close(@mtime.to_i, 2)
+ end
end
platform_is :linux do
diff --git a/spec/ruby/core/float/round_spec.rb b/spec/ruby/core/float/round_spec.rb
index e04b376c36..df113f97b1 100644
--- a/spec/ruby/core/float/round_spec.rb
+++ b/spec/ruby/core/float/round_spec.rb
@@ -10,11 +10,9 @@ describe "Float#round" do
0.0.round.should == 0
end
- platform_is_not :mingw32 do
- it "returns the nearest Integer for Float near the limit" do
- 0.49999999999999994.round.should == 0
- -0.49999999999999994.round.should == 0
- end
+ it "returns the nearest Integer for Float near the limit" do
+ 0.49999999999999994.round.should == 0
+ -0.49999999999999994.round.should == 0
end
it "raises FloatDomainError for exceptional values" do
diff --git a/spec/ruby/core/io/dup_spec.rb b/spec/ruby/core/io/dup_spec.rb
index 421ae27f24..c88d109ec9 100644
--- a/spec/ruby/core/io/dup_spec.rb
+++ b/spec/ruby/core/io/dup_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "IO#dup" do
before :each do
- @file = tmp("rubinius_spec_io_dup_#{$$}_#{Time.now.to_f}")
+ @file = tmp("spec_io_dup")
@f = File.open @file, 'w+'
@i = @f.dup
@@ -66,4 +66,22 @@ end
it "raises IOError on closed stream" do
lambda { IOSpecs.closed_io.dup }.should raise_error(IOError)
end
+
+ it "always sets the close-on-exec flag for the new IO object" do
+ @f.close_on_exec = true
+ dup = @f.dup
+ begin
+ dup.close_on_exec?.should == true
+ ensure
+ dup.close
+ end
+
+ @f.close_on_exec = false
+ dup = @f.dup
+ begin
+ dup.close_on_exec?.should == true
+ ensure
+ dup.close
+ end
+ end
end
diff --git a/spec/ruby/core/io/reopen_spec.rb b/spec/ruby/core/io/reopen_spec.rb
index e769991554..53fcc9dede 100644
--- a/spec/ruby/core/io/reopen_spec.rb
+++ b/spec/ruby/core/io/reopen_spec.rb
@@ -162,6 +162,18 @@ describe "IO#reopen with a String" do
end
end
+ it "always resets the close-on-exec flag to true on non-STDIO objects" do
+ @io = new_io @name, "w"
+
+ @io.close_on_exec = true
+ @io.reopen @other_name
+ @io.close_on_exec?.should == true
+
+ @io.close_on_exec = false
+ @io.reopen @other_name
+ @io.close_on_exec?.should == true
+ end
+
it "creates the file if it doesn't exist if the IO is opened in write mode" do
@io = new_io @name, "w"
@@ -294,6 +306,18 @@ describe "IO#reopen with an IO" do
File.read(@other_name).should == "io data"
end
+ it "always resets the close-on-exec flag to true on non-STDIO objects" do
+ @other_io.close_on_exec = true
+ @io.close_on_exec = true
+ @io.reopen @other_io
+ @io.close_on_exec?.should == true
+
+ @other_io.close_on_exec = false
+ @io.close_on_exec = false
+ @io.reopen @other_io
+ @io.close_on_exec?.should == true
+ end
+
it "may change the class of the instance" do
@io.reopen @other_io
@io.should be_an_instance_of(File)
diff --git a/spec/ruby/core/kernel/match_spec.rb b/spec/ruby/core/kernel/match_spec.rb
index bc6cb3d9dd..d5808b6ede 100644
--- a/spec/ruby/core/kernel/match_spec.rb
+++ b/spec/ruby/core/kernel/match_spec.rb
@@ -1,22 +1,16 @@
require_relative '../../spec_helper'
describe "Kernel#=~" do
- verbose = $VERBOSE
- before :each do
- verbose, $VERBOSE = $VERBOSE, nil
- end
- after :each do
- $VERBOSE = verbose
- end
-
it "returns nil matching any object" do
o = Object.new
- (o =~ /Object/).should be_nil
- (o =~ 'Object').should be_nil
- (o =~ Object).should be_nil
- (o =~ Object.new).should be_nil
- (o =~ nil).should be_nil
- (o =~ true).should be_nil
+ suppress_warning do
+ (o =~ /Object/).should be_nil
+ (o =~ 'Object').should be_nil
+ (o =~ Object).should be_nil
+ (o =~ Object.new).should be_nil
+ (o =~ nil).should be_nil
+ (o =~ true).should be_nil
+ end
end
end
diff --git a/spec/ruby/core/marshal/dump_spec.rb b/spec/ruby/core/marshal/dump_spec.rb
index 644a88b4a3..c53840962c 100644
--- a/spec/ruby/core/marshal/dump_spec.rb
+++ b/spec/ruby/core/marshal/dump_spec.rb
@@ -63,6 +63,10 @@ describe "Marshal.dump" do
"\x04\bI:\b\xE2\x86\x92\x06:\x06ET"],
[Marshal, s.encode("utf-16").to_sym,
"\x04\bI:\t\xFE\xFF!\x92\x06:\rencoding\"\vUTF-16"],
+ [Marshal, s.encode("utf-16le").to_sym,
+ "\x04\bI:\a\x92!\x06:\rencoding\"\rUTF-16LE"],
+ [Marshal, s.encode("utf-16be").to_sym,
+ "\x04\bI:\a!\x92\x06:\rencoding\"\rUTF-16BE"],
[Marshal, s.encode("euc-jp").to_sym,
"\x04\bI:\a\xA2\xAA\x06:\rencoding\"\vEUC-JP"],
[Marshal, s.encode("sjis").to_sym,
@@ -74,20 +78,6 @@ describe "Marshal.dump" do
s = "\u2192".force_encoding("binary").to_sym
Marshal.dump(s).should == "\x04\b:\b\xE2\x86\x92"
end
-
- end
-
- it "dumps an extended_object" do
- Marshal.dump(Object.new.extend(Meths)).should == "\x04\be:\nMethso:\vObject\x00"
- end
-
- it "dumps an object that has had an ivar added and removed as though the ivar never was set" do
- obj = Object.new
- initial = Marshal.dump(obj)
- obj.instance_variable_set(:@ivar, 1)
- Marshal.dump(obj).should == "\004\bo:\vObject\006:\n@ivari\006"
- obj.send :remove_instance_variable, :@ivar
- Marshal.dump(obj).should == initial
end
describe "with an object responding to #marshal_dump" do
@@ -376,6 +366,13 @@ describe "Marshal.dump" do
Marshal.dump(obj).should == "\004\bo:\vObject\006:\n@ivari\006"
end
+ it "dumps an Object with a non-US-ASCII instance variable" do
+ obj = Object.new
+ ivar = "@é".force_encoding(Encoding::UTF_8).to_sym
+ obj.instance_variable_set(ivar, 1)
+ Marshal.dump(obj).should == "\x04\bo:\vObject\x06I:\b@\xC3\xA9\x06:\x06ETi\x06"
+ end
+
it "dumps an Object that has had an instance variable added and removed as though it was never set" do
obj = Object.new
obj.instance_variable_set(:@ivar, 1)
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index 8b68384738..0f1d49b115 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -352,6 +352,54 @@ describe :marshal_load, shared: true do
end
end
+ describe "for a Symbol" do
+ it "loads a Symbol" do
+ sym = Marshal.send(@method, "\004\b:\vsymbol")
+ sym.should == :symbol
+ sym.encoding.should == Encoding::US_ASCII
+ end
+
+ it "loads a big Symbol" do
+ sym = ('big' * 100).to_sym
+ Marshal.send(@method, "\004\b:\002,\001#{'big' * 100}").should == sym
+ end
+
+ it "loads an encoded Symbol" do
+ s = "\u2192"
+
+ sym = Marshal.send(@method, "\x04\bI:\b\xE2\x86\x92\x06:\x06ET")
+ sym.should == s.encode("utf-8").to_sym
+ sym.encoding.should == Encoding::UTF_8
+
+ sym = Marshal.send(@method, "\x04\bI:\t\xFE\xFF!\x92\x06:\rencoding\"\vUTF-16")
+ sym.should == s.encode("utf-16").to_sym
+ sym.encoding.should == Encoding::UTF_16
+
+ sym = Marshal.send(@method, "\x04\bI:\a\x92!\x06:\rencoding\"\rUTF-16LE")
+ sym.should == s.encode("utf-16le").to_sym
+ sym.encoding.should == Encoding::UTF_16LE
+
+ sym = Marshal.send(@method, "\x04\bI:\a!\x92\x06:\rencoding\"\rUTF-16BE")
+ sym.should == s.encode("utf-16be").to_sym
+ sym.encoding.should == Encoding::UTF_16BE
+
+ sym = Marshal.send(@method, "\x04\bI:\a\xA2\xAA\x06:\rencoding\"\vEUC-JP")
+ sym.should == s.encode("euc-jp").to_sym
+ sym.encoding.should == Encoding::EUC_JP
+
+ sym = Marshal.send(@method, "\x04\bI:\a\x81\xA8\x06:\rencoding\"\x10Windows-31J")
+ sym.should == s.encode("sjis").to_sym
+ sym.encoding.should == Encoding::SJIS
+ end
+
+ it "loads a binary encoded Symbol" do
+ s = "\u2192".force_encoding("binary").to_sym
+ sym = Marshal.send(@method, "\x04\b:\b\xE2\x86\x92")
+ sym.should == s
+ sym.encoding.should == Encoding::BINARY
+ end
+ end
+
describe "for a String" do
it "loads a string having ivar with ref to self" do
obj = 'hi'
@@ -485,24 +533,39 @@ describe :marshal_load, shared: true do
end
end
- describe "for a user Class" do
- it "loads a user-marshaled extended object" do
- obj = UserMarshal.new.extend(Meths)
+ describe "for an Object" do
+ it "loads an object" do
+ Marshal.send(@method, "\004\bo:\vObject\000").should be_kind_of(Object)
+ end
- new_obj = Marshal.send(@method, "\004\bU:\020UserMarshal\"\nstuff")
+ it "loads an extended Object" do
+ obj = Object.new.extend(Meths)
- new_obj.should == obj
+ new_obj = Marshal.send(@method, "\004\be:\nMethso:\vObject\000")
+
+ new_obj.class.should == obj.class
new_obj_metaclass_ancestors = class << new_obj; ancestors; end
- new_obj_metaclass_ancestors[@num_self_class].should == UserMarshal
+ new_obj_metaclass_ancestors[@num_self_class, 2].should == [Meths, Object]
end
- it "loads a user_object" do
- UserObject.new
- Marshal.send(@method, "\004\bo:\017UserObject\000").should be_kind_of(UserObject)
+ it "loads an object having ivar" do
+ s = 'hi'
+ arr = [:so, :so, s, s]
+ obj = Object.new
+ obj.instance_variable_set :@str, arr
+
+ new_obj = Marshal.send(@method, "\004\bo:\vObject\006:\t@str[\t:\aso;\a\"\ahi@\a")
+ new_str = new_obj.instance_variable_get :@str
+
+ new_str.should == arr
end
- it "loads an object" do
- Marshal.send(@method, "\004\bo:\vObject\000").should be_kind_of(Object)
+ it "loads an Object with a non-US-ASCII instance variable" do
+ ivar = "@é".force_encoding(Encoding::UTF_8).to_sym
+ obj = Marshal.send(@method, "\x04\bo:\vObject\x06I:\b@\xC3\xA9\x06:\x06ETi\x06")
+ obj.instance_variables.should == [ivar]
+ obj.instance_variables[0].encoding.should == Encoding::UTF_8
+ obj.instance_variable_get(ivar).should == 1
end
it "raises ArgumentError if the object from an 'o' stream is not dumpable as 'o' type user class" do
@@ -510,15 +573,21 @@ describe :marshal_load, shared: true do
Marshal.send(@method, "\x04\bo:\tFile\001\001:\001\005@path\"\x10/etc/passwd")
end.should raise_error(ArgumentError)
end
+ end
- it "loads an extended Object" do
- obj = Object.new.extend(Meths)
+ describe "for a user object" do
+ it "loads a user-marshaled extended object" do
+ obj = UserMarshal.new.extend(Meths)
- new_obj = Marshal.send(@method, "\004\be:\nMethso:\vObject\000")
+ new_obj = Marshal.send(@method, "\004\bU:\020UserMarshal\"\nstuff")
- new_obj.class.should == obj.class
+ new_obj.should == obj
new_obj_metaclass_ancestors = class << new_obj; ancestors; end
- new_obj_metaclass_ancestors[@num_self_class, 2].should == [Meths, Object]
+ new_obj_metaclass_ancestors[@num_self_class].should == UserMarshal
+ end
+
+ it "loads a UserObject" do
+ Marshal.send(@method, "\004\bo:\017UserObject\000").should be_kind_of(UserObject)
end
describe "that extends a core type other than Object or BasicObject" do
@@ -537,18 +606,6 @@ describe :marshal_load, shared: true do
lambda { Marshal.send(@method, data) }.should raise_error(ArgumentError)
end
end
-
- it "loads an object having ivar" do
- s = 'hi'
- arr = [:so, :so, s, s]
- obj = Object.new
- obj.instance_variable_set :@str, arr
-
- new_obj = Marshal.send(@method, "\004\bo:\vObject\006:\t@str[\t:\aso;\a\"\ahi@\a")
- new_str = new_obj.instance_variable_get :@str
-
- new_str.should == arr
- end
end
describe "for a Regexp" do
diff --git a/spec/ruby/core/matchdata/begin_spec.rb b/spec/ruby/core/matchdata/begin_spec.rb
index b791018633..85c454da56 100644
--- a/spec/ruby/core/matchdata/begin_spec.rb
+++ b/spec/ruby/core/matchdata/begin_spec.rb
@@ -3,28 +3,102 @@
require_relative '../../spec_helper'
describe "MatchData#begin" do
- it "returns the offset of the start of the nth element" do
- match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
- match_data.begin(0).should == 1
- match_data.begin(2).should == 2
- end
+ context "when passed an integer argument" do
+ it "returns the character offset of the start of the nth element" do
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.begin(0).should == 1
+ match_data.begin(2).should == 2
+ end
- it "returns nil when the nth match isn't found" do
- match_data = /something is( not)? (right)/.match("something is right")
- match_data.begin(1).should be_nil
+ it "returns nil when the nth match isn't found" do
+ match_data = /something is( not)? (right)/.match("something is right")
+ match_data.begin(1).should be_nil
+ end
+
+ it "returns the character offset for multi-byte strings" do
+ match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
+ match_data.begin(0).should == 1
+ match_data.begin(2).should == 2
+ end
+
+ not_supported_on :opal do
+ it "returns the character offset for multi-byte strings with unicode regexp" do
+ match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
+ match_data.begin(0).should == 1
+ match_data.begin(2).should == 2
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.begin(obj).should == 2
+ end
end
- it "returns the offset for multi byte strings" do
- match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
- match_data.begin(0).should == 1
- match_data.begin(2).should == 2
+ context "when passed a String argument" do
+ it "return the character offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.begin("a").should == 1
+ match_data.begin("b").should == 3
+ end
+
+ it "returns the character offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.begin("a").should == 1
+ match_data.begin("b").should == 3
+ end
+
+ not_supported_on :opal do
+ it "returns the character offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.begin("a").should == 1
+ match_data.begin("b").should == 3
+ end
+ end
+
+ it "returns the character offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.begin("a").should == 3
+ end
+
+ it "returns the character offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.begin("æ").should == 1
+ end
end
- not_supported_on :opal do
- it "returns the offset for multi byte strings with unicode regexp" do
- match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
- match_data.begin(0).should == 1
- match_data.begin(2).should == 2
+ context "when passed a Symbol argument" do
+ it "return the character offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.begin(:a).should == 1
+ match_data.begin(:b).should == 3
+ end
+
+ it "returns the character offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.begin(:a).should == 1
+ match_data.begin(:b).should == 3
+ end
+
+ not_supported_on :opal do
+ it "returns the character offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.begin(:a).should == 1
+ match_data.begin(:b).should == 3
+ end
+ end
+
+ it "returns the character offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.begin(:a).should == 3
+ end
+
+ it "returns the character offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.begin(:æ).should == 1
end
end
end
diff --git a/spec/ruby/core/matchdata/end_spec.rb b/spec/ruby/core/matchdata/end_spec.rb
index f6f3e1a281..d01b0a8b30 100644
--- a/spec/ruby/core/matchdata/end_spec.rb
+++ b/spec/ruby/core/matchdata/end_spec.rb
@@ -3,28 +3,102 @@
require_relative '../../spec_helper'
describe "MatchData#end" do
- it "returns the offset of the end of the nth element" do
- match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
- match_data.end(0).should == 7
- match_data.end(2).should == 3
- end
+ context "when passed an integer argument" do
+ it "returns the character offset of the end of the nth element" do
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.end(0).should == 7
+ match_data.end(2).should == 3
+ end
- it "returns nil when the nth match isn't found" do
- match_data = /something is( not)? (right)/.match("something is right")
- match_data.end(1).should be_nil
+ it "returns nil when the nth match isn't found" do
+ match_data = /something is( not)? (right)/.match("something is right")
+ match_data.end(1).should be_nil
+ end
+
+ it "returns the character offset for multi-byte strings" do
+ match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
+ match_data.end(0).should == 7
+ match_data.end(2).should == 3
+ end
+
+ not_supported_on :opal do
+ it "returns the character offset for multi-byte strings with unicode regexp" do
+ match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
+ match_data.end(0).should == 7
+ match_data.end(2).should == 3
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.end(obj).should == 3
+ end
end
- it "returns the offset for multi byte strings" do
- match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
- match_data.end(0).should == 7
- match_data.end(2).should == 3
+ context "when passed a String argument" do
+ it "return the character offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.end("a").should == 2
+ match_data.end("b").should == 6
+ end
+
+ it "returns the character offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.end("a").should == 2
+ match_data.end("b").should == 6
+ end
+
+ not_supported_on :opal do
+ it "returns the character offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.end("a").should == 2
+ match_data.end("b").should == 6
+ end
+ end
+
+ it "returns the character offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.end("a").should == 6
+ end
+
+ it "returns the character offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.end("æ").should == 2
+ end
end
- not_supported_on :opal do
- it "returns the offset for multi byte strings with unicode regexp" do
- match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
- match_data.end(0).should == 7
- match_data.end(2).should == 3
+ context "when passed a Symbol argument" do
+ it "return the character offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.end(:a).should == 2
+ match_data.end(:b).should == 6
+ end
+
+ it "returns the character offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.end(:a).should == 2
+ match_data.end(:b).should == 6
+ end
+
+ not_supported_on :opal do
+ it "returns the character offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.end(:a).should == 2
+ match_data.end(:b).should == 6
+ end
+ end
+
+ it "returns the character offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.end(:a).should == 6
+ end
+
+ it "returns the character offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.end(:æ).should == 2
end
end
end
diff --git a/spec/ruby/core/matchdata/named_captures_spec.rb b/spec/ruby/core/matchdata/named_captures_spec.rb
index 588b607a44..0b0771355f 100644
--- a/spec/ruby/core/matchdata/named_captures_spec.rb
+++ b/spec/ruby/core/matchdata/named_captures_spec.rb
@@ -9,5 +9,9 @@ ruby_version_is '2.4' do
it 'prefers later captures' do
/\A(?<a>.)(?<b>.)(?<b>.)(?<a>.)\z/.match('0123').named_captures.should == { 'a' => '3', 'b' => '2' }
end
+
+ it 'returns the latest matched capture, even if a later one that does not match exists' do
+ /\A(?<a>.)(?<b>.)(?<b>.)(?<a>.)?\z/.match('012').named_captures.should == { 'a' => '0', 'b' => '2' }
+ end
end
end
diff --git a/spec/ruby/core/module/name_spec.rb b/spec/ruby/core/module/name_spec.rb
index 5b59b6adaa..f56e35f204 100644
--- a/spec/ruby/core/module/name_spec.rb
+++ b/spec/ruby/core/module/name_spec.rb
@@ -65,4 +65,14 @@ describe "Module#name" do
ModuleSpecs::Anonymous::E = m
m::N.name.should == "ModuleSpecs::Anonymous::E::N"
end
+
+ it "returns a mutable string" do
+ ModuleSpecs.name.frozen?.should be_false
+ end
+
+ it "returns a mutable string that when mutated does not modify the original module name" do
+ ModuleSpecs.name << "foo"
+
+ ModuleSpecs.name.should == "ModuleSpecs"
+ end
end
diff --git a/spec/ruby/core/process/clock_gettime_spec.rb b/spec/ruby/core/process/clock_gettime_spec.rb
index 165f0db730..558e4fe717 100644
--- a/spec/ruby/core/process/clock_gettime_spec.rb
+++ b/spec/ruby/core/process/clock_gettime_spec.rb
@@ -1,6 +1,14 @@
require_relative '../../spec_helper'
describe "Process.clock_gettime" do
+ platform_is_not :windows do
+ it 'can be called with all declared clocks' do
+ Process.constants.select { |c| c.to_s.start_with?('CLOCK_') }.each do |c|
+ Process.clock_gettime(Process.const_get(c)).should be_an_instance_of(Float)
+ end
+ end
+ end
+
describe 'time units' do
it 'handles a fixed set of time units' do
[:nanosecond, :microsecond, :millisecond, :second].each do |unit|
diff --git a/spec/ruby/core/process/kill_spec.rb b/spec/ruby/core/process/kill_spec.rb
index f7665ba087..14deba2451 100644
--- a/spec/ruby/core/process/kill_spec.rb
+++ b/spec/ruby/core/process/kill_spec.rb
@@ -31,6 +31,10 @@ describe "Process.kill" do
Process.kill("SIGKILL", pid)
}.should raise_error(Errno::ESRCH)
end
+
+ it "checks for existence and permissions to signal a process, but does not actually signal it, when using signal 0" do
+ Process.kill(0, @pid).should == 1
+ end
end
platform_is_not :windows do
@@ -65,7 +69,7 @@ platform_is_not :windows do
@sp.result.should == "signaled"
end
- it "acceps an Integer as a signal value" do
+ it "accepts an Integer as a signal value" do
Process.kill(15, @sp.pid)
@sp.result.should == "signaled"
end
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index 1bd1dfac83..43e389ad7f 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -11,22 +11,22 @@ describe :process_spawn_does_not_close_std_streams, shared: true do
it "does not close STDIN" do
code = "STDOUT.puts STDIN.read(0).inspect"
cmd = "Process.wait Process.spawn(#{ruby_cmd(code).inspect}, #{@options.inspect})"
- ruby_exe(cmd, args: "> #{@output}")
- File.binread(@output).should == %[""#{newline}]
+ ruby_exe(cmd, args: "> #{@name}")
+ File.binread(@name).should == %[""#{newline}]
end
it "does not close STDOUT" do
code = "STDOUT.puts 'hello'"
cmd = "Process.wait Process.spawn(#{ruby_cmd(code).inspect}, #{@options.inspect})"
- ruby_exe(cmd, args: "> #{@output}")
- File.binread(@output).should == "hello#{newline}"
+ ruby_exe(cmd, args: "> #{@name}")
+ File.binread(@name).should == "hello#{newline}"
end
it "does not close STDERR" do
code = "STDERR.puts 'hello'"
cmd = "Process.wait Process.spawn(#{ruby_cmd(code).inspect}, #{@options.inspect})"
- ruby_exe(cmd, args: "2> #{@output}")
- File.binread(@output).should =~ /hello#{newline}/
+ ruby_exe(cmd, args: "2> #{@name}")
+ File.binread(@name).should =~ /hello#{newline}/
end
end
end
@@ -391,6 +391,50 @@ describe "Process.spawn" do
end
end
+ # chdir
+
+ platform_is :linux do
+ describe "inside Dir.chdir" do
+ def child_pids(pid)
+ `pgrep -P #{pid}`.lines.map { |child| Integer(child) }
+ end
+
+ it "does not create extra process without chdir" do
+ pid = Process.spawn("sleep 10")
+ begin
+ child_pids(pid).size.should == 0
+ ensure
+ Process.kill("TERM", pid)
+ Process.wait(pid)
+ end
+ end
+
+ it "kills extra chdir processes" do
+ pid = nil
+ Dir.chdir("/tmp") do
+ pid = Process.spawn("sleep 10")
+ end
+
+ children = child_pids(pid)
+ children.size.should <= 1
+
+ Process.kill("TERM", pid)
+ Process.wait(pid)
+
+ if children.size > 0
+ # wait a bit for children to die
+ sleep(1)
+
+ children.each do |child|
+ lambda do
+ Process.kill("TERM", child)
+ end.should raise_error(Errno::ESRCH)
+ end
+ end
+ end
+ end
+ end
+
# :umask
it "uses the current umask by default" do
@@ -490,20 +534,19 @@ describe "Process.spawn" do
context "when passed close_others: true" do
before :each do
- @output = tmp("spawn_close_others_true")
@options = { close_others: true }
end
- after :each do
- rm_r @output
- end
-
- it "closes file descriptors >= 3 in the child process" do
+ it "closes file descriptors >= 3 in the child process even if fds are set close_on_exec=false" do
+ touch @name
IO.pipe do |r, w|
+ r.close_on_exec = false
+ w.close_on_exec = false
+
begin
pid = Process.spawn(ruby_cmd("while File.exist? '#{@name}'; sleep 0.1; end"), @options)
w.close
- lambda { r.read_nonblock(1) }.should raise_error(EOFError)
+ r.read(1).should == nil
ensure
rm_r @name
Process.wait(pid) if pid
@@ -516,20 +559,16 @@ describe "Process.spawn" do
context "when passed close_others: false" do
before :each do
- @output = tmp("spawn_close_others_false")
@options = { close_others: false }
end
- after :each do
- rm_r @output
- end
-
it "closes file descriptors >= 3 in the child process because they are set close_on_exec by default" do
+ touch @name
IO.pipe do |r, w|
begin
pid = Process.spawn(ruby_cmd("while File.exist? '#{@name}'; sleep 0.1; end"), @options)
w.close
- lambda { r.read_nonblock(1) }.should raise_error(EOFError)
+ r.read(1).should == nil
ensure
rm_r @name
Process.wait(pid) if pid
@@ -542,13 +581,14 @@ describe "Process.spawn" do
IO.pipe do |r, w|
r.close_on_exec = false
w.close_on_exec = false
+
+ code = "fd = IO.for_fd(#{w.fileno}); fd.write 'abc'; fd.close"
+ pid = Process.spawn(ruby_cmd(code), @options)
begin
- pid = Process.spawn(ruby_cmd("while File.exist? '#{@name}'; sleep 0.1; end"), @options)
w.close
- lambda { r.read_nonblock(1) }.should raise_error(Errno::EAGAIN)
+ r.read.should == 'abc'
ensure
- rm_r @name
- Process.wait(pid) if pid
+ Process.wait(pid)
end
end
end
@@ -623,7 +663,7 @@ describe "Process.spawn" do
end
it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do
- child_fd = @io.fileno + 1
+ child_fd = find_unused_fd
args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s])
pid = Process.spawn(*args, { child_fd => @io })
Process.waitpid pid
diff --git a/spec/ruby/core/string/scan_spec.rb b/spec/ruby/core/string/scan_spec.rb
index 64a1c31443..ac82f5e236 100644
--- a/spec/ruby/core/string/scan_spec.rb
+++ b/spec/ruby/core/string/scan_spec.rb
@@ -84,6 +84,11 @@ describe "String#scan" do
a = "hello".taint.scan(/./)
a.each { |m| m.tainted?.should be_true }
end
+
+ # jruby/jruby#5513
+ it "does not raise any errors when passed a multi-byte string" do
+ "あああaaaあああ".scan("あああ").should == ["あああ", "あああ"]
+ end
end
describe "String#scan with pattern and block" do
diff --git a/spec/ruby/core/string/unpack/l_spec.rb b/spec/ruby/core/string/unpack/l_spec.rb
index 6f9fcd4fd0..18bb68b8d0 100644
--- a/spec/ruby/core/string/unpack/l_spec.rb
+++ b/spec/ruby/core/string/unpack/l_spec.rb
@@ -14,7 +14,7 @@ describe "String#unpack with format 'L'" do
it_behaves_like :string_unpack_32bit_be_unsigned, 'L>'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'L<_'
it_behaves_like :string_unpack_32bit_le, 'L_<'
@@ -44,7 +44,7 @@ describe "String#unpack with format 'L'" do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'L<_'
it_behaves_like :string_unpack_64bit_le, 'L_<'
@@ -86,7 +86,7 @@ describe "String#unpack with format 'l'" do
it_behaves_like :string_unpack_32bit_be_signed, 'l>'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'l<_'
it_behaves_like :string_unpack_32bit_le, 'l_<'
@@ -116,7 +116,7 @@ describe "String#unpack with format 'l'" do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'l<_'
it_behaves_like :string_unpack_64bit_le, 'l_<'
@@ -160,7 +160,7 @@ little_endian do
it_behaves_like :string_unpack_32bit_le_signed, 'l'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'L_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'L_'
@@ -182,7 +182,7 @@ little_endian do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'L_'
it_behaves_like :string_unpack_64bit_le_unsigned, 'L_'
@@ -218,7 +218,7 @@ big_endian do
it_behaves_like :string_unpack_32bit_be_signed, 'l'
end
- guard -> { platform_is wordsize: 32 or platform_is :mingw32 } do
+ platform_is wordsize: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'L_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'L_'
@@ -240,7 +240,7 @@ big_endian do
end
end
- guard -> { platform_is wordsize: 64 and platform_is_not :mingw32 } do
+ platform_is wordsize: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_be, 'L_'
it_behaves_like :string_unpack_64bit_be_unsigned, 'L_'