1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66622 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2018-12-29 00:22:52 +00:00
parent 548defb608
commit 2076c2c3c4
34 changed files with 759 additions and 328 deletions

View file

@ -10,13 +10,16 @@ matrix:
env: MSPEC_OPTS="-R2 -ff"
- rvm: 2.3.8
- rvm: 2.4.5
env: CHECK_LEAKS=true
- rvm: 2.5.3
env: CHECK_LEAKS=true
- rvm: 2.6.0
env: CHECK_LEAKS=true
- rvm: ruby-head
- env: RUBOCOP=true
rvm: 2.4.5
script:
- gem install rubocop -v 0.54.0
- gem install rubocop:0.61.0
- rubocop
allow_failures:
- rvm: ruby-head

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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_behaves_like :array_binary_union, :|
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
ruby_version_is "2.6" do
describe "Array#union" do
it_behaves_like :array_binary_union, :union
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
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
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]
it "does not return subclass instances for Array subclasses" do
ArraySpecs::MyArray[1, 2, 3].union.should be_an_instance_of(Array)
end
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.
([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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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,32 +533,11 @@ 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)
new_obj = Marshal.send(@method, "\004\bU:\020UserMarshal\"\nstuff")
new_obj.should == obj
new_obj_metaclass_ancestors = class << new_obj; ancestors; end
new_obj_metaclass_ancestors[@num_self_class].should == UserMarshal
end
it "loads a user_object" do
UserObject.new
Marshal.send(@method, "\004\bo:\017UserObject\000").should be_kind_of(UserObject)
end
describe "for an Object" do
it "loads an object" do
Marshal.send(@method, "\004\bo:\vObject\000").should be_kind_of(Object)
end
it "raises ArgumentError if the object from an 'o' stream is not dumpable as 'o' type user class" do
lambda do
Marshal.send(@method, "\x04\bo:\tFile\001\001:\001\005@path\"\x10/etc/passwd")
end.should raise_error(ArgumentError)
end
it "loads an extended Object" do
obj = Object.new.extend(Meths)
@ -521,6 +548,48 @@ describe :marshal_load, shared: true do
new_obj_metaclass_ancestors[@num_self_class, 2].should == [Meths, Object]
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
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
lambda do
Marshal.send(@method, "\x04\bo:\tFile\001\001:\001\005@path\"\x10/etc/passwd")
end.should raise_error(ArgumentError)
end
end
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\bU:\020UserMarshal\"\nstuff")
new_obj.should == obj
new_obj_metaclass_ancestors = class << new_obj; ancestors; end
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
after :each do
MarshalSpec.reset_swapped_class
@ -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

View file

@ -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
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 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 offset for multi byte strings with unicode regexp" do
match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
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
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
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
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

View file

@ -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
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 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 offset for multi byte strings with unicode regexp" do
match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
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
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
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
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

View file

@ -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

View file

@ -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

View file

@ -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|

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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_'

View file

@ -442,6 +442,21 @@ describe "The return keyword" do
end
end
describe "within a block within a class" do
it "is allowed" do
File.write(@filename, <<-END_OF_CODE)
class A
ScratchPad << "before return"
1.times { return }
ScratchPad << "after return"
end
END_OF_CODE
load @filename
ScratchPad.recorded.should == ["before return"]
end
end
describe "file loading" do
it "stops file loading and execution" do
File.write(@filename, <<-END_OF_CODE)

View file

@ -4,6 +4,6 @@ require 'date'
describe "DateTime#+" do
it "is able to add sub-millisecond precision values" do
datetime = DateTime.new(2017)
(datetime + 0.00001).to_time.usec.should == 864000
(datetime + 0.00001001).to_time.usec.should == 864864
end
end

View file

@ -4,6 +4,16 @@ require 'date'
describe "DateTime#-" do
it "is able to subtract sub-millisecond precision values" do
date = DateTime.new(2017)
((date + 0.00001) - date).should == Rational(1, 100000)
diff = Rational(123456789, 24*60*60*1000*1000)
((date + diff) - date).should == diff
(date - (date + diff)).should == -diff
(date - (date - diff)).should == diff
((date - diff) - date).should == -diff
end
it "correctly calculates sub-millisecond time differences" do #5493
dt1 = DateTime.new(2018, 1, 1, 0, 0, 30)
dt2 = DateTime.new(2018, 1, 1, 0, 1, 29.000001)
((dt2 - dt1) * 24 * 60 * 60).should == 59.000001
end
end

View file

@ -2,9 +2,19 @@ require 'stringio'
require_relative '../../spec_helper'
describe "StringIO#set_encoding" do
it "sets the encoding of the underlying String" do
io = StringIO.new
it "sets the encoding of the underlying String if the String is not frozen" do
str = "".encode(Encoding::US_ASCII)
io = StringIO.new(str)
io.set_encoding Encoding::UTF_8
io.string.encoding.should == Encoding::UTF_8
end
it "does not set the encoding of the underlying String if the String is frozen" do
str = "".encode(Encoding::US_ASCII).freeze
io = StringIO.new(str)
io.set_encoding Encoding::UTF_8
io.string.encoding.should == Encoding::US_ASCII
end
end

View file

@ -42,6 +42,8 @@ describe :rb_enc_set_index, shared: true do
end
describe "C-API Encoding function" do
@n = 0
before :each do
@s = CApiEncodingSpecs.new
end
@ -49,8 +51,9 @@ describe "C-API Encoding function" do
ruby_version_is "2.6" do
describe "rb_enc_alias" do
it "creates an alias for an existing Encoding" do
@s.rb_enc_alias("ZOMGWTFBBQ", "UTF-8").should >= 0
Encoding.find("ZOMGWTFBBQ").name.should == "UTF-8"
name = "ZOMGWTFBBQ#{@n += 1}"
@s.rb_enc_alias(name, "UTF-8").should >= 0
Encoding.find(name).name.should == "UTF-8"
end
end
end

View file

@ -165,7 +165,7 @@ describe "CApiTimeSpecs" do
usec.should == 500000
end
platform_is_not :mingw32 do
guard -> { platform_is_not :mingw or ruby_version_is '2.5' } do
it "creates a timeval for a negative Fixnum" do
sec, usec = @s.rb_time_timeval(-1232141421)
sec.should be_kind_of(Integer)
@ -224,7 +224,7 @@ describe "CApiTimeSpecs" do
nsec.should == 500000000
end
platform_is_not :mingw32 do
guard -> { platform_is_not :mingw or ruby_version_is '2.5' } do
it "creates a timespec for a negative Fixnum" do
sec, nsec = @s.rb_time_timespec(-1232141421)
sec.should be_kind_of(Integer)