1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
This commit is contained in:
Benoit Daloze 2021-07-29 22:11:21 +02:00
parent 15d05f8120
commit 6998d75824
186 changed files with 3956 additions and 3339 deletions

View file

@ -1,7 +1,7 @@
inherit_from: .rubocop_todo.yml inherit_from: .rubocop_todo.yml
AllCops: AllCops:
TargetRubyVersion: 2.5 TargetRubyVersion: 2.6
DisplayCopNames: true DisplayCopNames: true
Exclude: Exclude:
- command_line/fixtures/bad_syntax.rb - command_line/fixtures/bad_syntax.rb

View file

@ -178,7 +178,7 @@ First, file a bug at https://bugs.ruby-lang.org/.
It is better to use a `ruby_version_is` guard if there was a release with the fix. It is better to use a `ruby_version_is` guard if there was a release with the fix.
```ruby ```ruby
ruby_bug '#13669', ''...'2.5' do ruby_bug '#13669', ''...'2.7' do
it "works like this" do it "works like this" do
# Specify the expected behavior here, not the bug # Specify the expected behavior here, not the bug
end end

View file

@ -29,8 +29,8 @@ ruby/spec is known to be tested in these implementations for every commit:
* [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby) * [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby)
* [Opal](https://github.com/opal/opal/tree/master/spec) * [Opal](https://github.com/opal/opal/tree/master/spec)
ruby/spec describes the behavior of Ruby 2.5 and more recent Ruby versions. ruby/spec describes the behavior of Ruby 2.6 and more recent Ruby versions.
More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (2.5.x, 2.6.x, 2.7.x, etc), and those are tested in CI. More precisely, every latest stable MRI release should [pass](https://github.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (2.6.x, 2.7.x, 3.0.x, etc), and those are tested in CI.
### Synchronization with Ruby Implementations ### Synchronization with Ruby Implementations
@ -57,6 +57,7 @@ For older specs try these commits:
* Ruby 2.2.10 - [Suite](https://github.com/ruby/spec/commit/cbaa0e412270c944df0c2532fc500c920dba0e92) using [MSpec](https://github.com/ruby/mspec/commit/d84d7668449e96856c5f6bac8cb1526b6d357ce3) * Ruby 2.2.10 - [Suite](https://github.com/ruby/spec/commit/cbaa0e412270c944df0c2532fc500c920dba0e92) using [MSpec](https://github.com/ruby/mspec/commit/d84d7668449e96856c5f6bac8cb1526b6d357ce3)
* Ruby 2.3.8 - [Suite](https://github.com/ruby/spec/commit/dc733114d8ae66a3368ba3a98422c50147a76ba5) using [MSpec](https://github.com/ruby/mspec/commit/4599bc195fb109f2a482a01c32a7d659518369ea) * Ruby 2.3.8 - [Suite](https://github.com/ruby/spec/commit/dc733114d8ae66a3368ba3a98422c50147a76ba5) using [MSpec](https://github.com/ruby/mspec/commit/4599bc195fb109f2a482a01c32a7d659518369ea)
* Ruby 2.4.10 - [Suite](https://github.com/ruby/spec/commit/bce4f2b81d6c31db67cf4d023a0625ceadde59bd) using [MSpec](https://github.com/ruby/mspec/commit/e7eb8aa4c26495b7b461e687d950b96eb08b3ff2) * Ruby 2.4.10 - [Suite](https://github.com/ruby/spec/commit/bce4f2b81d6c31db67cf4d023a0625ceadde59bd) using [MSpec](https://github.com/ruby/mspec/commit/e7eb8aa4c26495b7b461e687d950b96eb08b3ff2)
* Ruby 2.5.9 - [Suite](https://github.com/ruby/spec/commit/c503335d3d9f6ec6ef24de60a0716c34af69b64f) using [MSpec](https://github.com/ruby/mspec/commit/0091e8a62e954717cd54641f935eaf1403692041)
### Running the specs ### Running the specs

View file

@ -1,6 +1,12 @@
require_relative '../spec_helper' require_relative '../spec_helper'
describe "The --enable and --disable flags" do describe "The --enable and --disable flags" do
before :all do
# Since some specs disable reading RUBYOPT, we instead pass its contents as :options for those specs
rubyopt = [ENV["RUBYOPT"]]
rubyopt << ENV["#{RUBY_ENGINE.upcase}OPT"] unless RUBY_ENGINE == 'ruby'
@rubyopt = RUBY_ENGINE == "ruby" ? "" : rubyopt.compact.join(" ")
end
it "can be used with gems" do it "can be used with gems" do
ruby_exe("p defined?(Gem)", options: "--enable=gems").chomp.should == "\"constant\"" ruby_exe("p defined?(Gem)", options: "--enable=gems").chomp.should == "\"constant\""
@ -25,9 +31,9 @@ describe "The --enable and --disable flags" do
it "can be used with rubyopt" do it "can be used with rubyopt" do
ruby_exe("p $VERBOSE", options: "--enable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true" ruby_exe("p $VERBOSE", options: "--enable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true"
ruby_exe("p $VERBOSE", options: "--disable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false" ruby_exe("p $VERBOSE", options: "#{@rubyopt} --disable=rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false"
ruby_exe("p $VERBOSE", options: "--enable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true" ruby_exe("p $VERBOSE", options: "--enable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "true"
ruby_exe("p $VERBOSE", options: "--disable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false" ruby_exe("p $VERBOSE", options: "#{@rubyopt} --disable-rubyopt", env: {'RUBYOPT' => '-w'}).chomp.should == "false"
end end
it "can be used with frozen-string-literal" do it "can be used with frozen-string-literal" do
@ -49,8 +55,8 @@ describe "The --enable and --disable flags" do
it "can be used with all for disable" do it "can be used with all for disable" do
e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]" e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
env = {'RUBYOPT' => '-w'} env = {'RUBYOPT' => '-w'}
ruby_exe(e, options: "--disable=all", env: env).chomp.should == "[nil, nil, false, false]" ruby_exe(e, options: "#{@rubyopt} --disable=all", env: env).chomp.should == "[nil, nil, false, false]"
ruby_exe(e, options: "--disable-all", env: env).chomp.should == "[nil, nil, false, false]" ruby_exe(e, options: "#{@rubyopt} --disable-all", env: env).chomp.should == "[nil, nil, false, false]"
end end
it "prints a warning for unknown features" do it "prints a warning for unknown features" do

View file

@ -2,23 +2,21 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
require_relative 'shared/difference' require_relative 'shared/difference'
ruby_version_is "2.6" do describe "Array#difference" do
describe "Array#difference" do it_behaves_like :array_binary_difference, :difference
it_behaves_like :array_binary_difference, :difference
it "returns a copy when called without any parameter" do it "returns a copy when called without any parameter" do
x = [1, 2, 3, 2] x = [1, 2, 3, 2]
x.difference.should == x x.difference.should == x
x.difference.should_not equal x x.difference.should_not equal x
end end
it "does not return subclass instances for Array subclasses" do it "does not return subclass instances for Array subclasses" do
ArraySpecs::MyArray[1, 2, 3].difference.should be_an_instance_of(Array) ArraySpecs::MyArray[1, 2, 3].difference.should be_an_instance_of(Array)
end end
it "accepts multiple arguments" do it "accepts multiple arguments" do
x = [1, 2, 3, 1] x = [1, 2, 3, 1]
x.difference([], [0, 1], [3, 4], [3]).should == [2] x.difference([], [0, 1], [3, 4], [3]).should == [2]
end
end end
end end

View file

@ -445,41 +445,39 @@ describe "Array#[]= with [m..n]" do
end end
end end
ruby_version_is "2.6" do describe "Array#[]= with [m..]" do
describe "Array#[]= with [m..]" do it "just sets the section defined by range to nil even if the rhs is nil" do
it "just sets the section defined by range to nil even if the rhs is nil" do a = [1, 2, 3, 4, 5]
a = [1, 2, 3, 4, 5] a[eval("(2..)")] = nil
a[eval("(2..)")] = nil a.should == [1, 2, nil]
a.should == [1, 2, nil] end
end
it "just sets the section defined by range to nil if m and n < 0 and the rhs is nil" do it "just sets the section defined by range to nil if m and n < 0 and the rhs is nil" do
a = [1, 2, 3, 4, 5] a = [1, 2, 3, 4, 5]
a[eval("(-3..)")] = nil a[eval("(-3..)")] = nil
a.should == [1, 2, nil] a.should == [1, 2, nil]
end end
it "replaces the section defined by range" do it "replaces the section defined by range" do
a = [6, 5, 4, 3, 2, 1] a = [6, 5, 4, 3, 2, 1]
a[eval("(3...)")] = 9 a[eval("(3...)")] = 9
a.should == [6, 5, 4, 9] a.should == [6, 5, 4, 9]
a[eval("(2..)")] = [7, 7, 7] a[eval("(2..)")] = [7, 7, 7]
a.should == [6, 5, 7, 7, 7] a.should == [6, 5, 7, 7, 7]
end end
it "replaces the section if m and n < 0" do it "replaces the section if m and n < 0" do
a = [1, 2, 3, 4, 5] a = [1, 2, 3, 4, 5]
a[eval("(-3..)")] = [7, 8, 9] a[eval("(-3..)")] = [7, 8, 9]
a.should == [1, 2, 7, 8, 9] a.should == [1, 2, 7, 8, 9]
end end
it "inserts at the end if m > the array size" do it "inserts at the end if m > the array size" do
a = [1, 2, 3] a = [1, 2, 3]
a[eval("(3..)")] = [4] a[eval("(3..)")] = [4]
a.should == [1, 2, 3, 4] a.should == [1, 2, 3, 4]
a[eval("(5..)")] = [6] a[eval("(5..)")] = [6]
a.should == [1, 2, 3, 4, nil, 6] a.should == [1, 2, 3, 4, nil, 6]
end
end end
end end

View file

@ -316,13 +316,11 @@ describe "Array#fill with (filler, range)" do
-> { [].fill('a', obj..obj) }.should raise_error(TypeError) -> { [].fill('a', obj..obj) }.should raise_error(TypeError)
end end
ruby_version_is "2.6" do it "works with endless ranges" do
it "works with endless ranges" do [1, 2, 3, 4].fill('x', eval("(1..)")).should == [1, 'x', 'x', 'x']
[1, 2, 3, 4].fill('x', eval("(1..)")).should == [1, 'x', 'x', 'x'] [1, 2, 3, 4].fill('x', eval("(3...)")).should == [1, 2, 3, 'x']
[1, 2, 3, 4].fill('x', eval("(3...)")).should == [1, 2, 3, 'x'] [1, 2, 3, 4].fill(eval("(1..)")) { |x| x + 2 }.should == [1, 3, 4, 5]
[1, 2, 3, 4].fill(eval("(1..)")) { |x| x + 2 }.should == [1, 3, 4, 5] [1, 2, 3, 4].fill(eval("(3...)")) { |x| x + 2 }.should == [1, 2, 3, 5]
[1, 2, 3, 4].fill(eval("(3...)")) { |x| x + 2 }.should == [1, 2, 3, 5]
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -1,16 +1,14 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'shared/select' require_relative 'shared/select'
ruby_version_is "2.6" do describe "Array#filter" do
describe "Array#filter" do it_behaves_like :array_select, :filter
it_behaves_like :array_select, :filter end
end
describe "Array#filter!" do
describe "Array#filter!" do it "returns nil if no changes were made in the array" do
it "returns nil if no changes were made in the array" do [1, 2, 3].filter! { true }.should be_nil
[1, 2, 3].filter! { true }.should be_nil end
end
it_behaves_like :keep_if, :filter!
it_behaves_like :keep_if, :filter!
end
end end

View file

@ -521,18 +521,16 @@ describe :array_slice, shared: true do
-> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError) -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError)
end end
ruby_version_is "2.6" do it "can accept endless ranges" do
it "can accept endless ranges" do a = [0, 1, 2, 3, 4, 5]
a = [0, 1, 2, 3, 4, 5] a.send(@method, eval("(2..)")).should == [2, 3, 4, 5]
a.send(@method, eval("(2..)")).should == [2, 3, 4, 5] a.send(@method, eval("(2...)")).should == [2, 3, 4, 5]
a.send(@method, eval("(2...)")).should == [2, 3, 4, 5] a.send(@method, eval("(-2..)")).should == [4, 5]
a.send(@method, eval("(-2..)")).should == [4, 5] a.send(@method, eval("(-2...)")).should == [4, 5]
a.send(@method, eval("(-2...)")).should == [4, 5] a.send(@method, eval("(9..)")).should == nil
a.send(@method, eval("(9..)")).should == nil a.send(@method, eval("(9...)")).should == nil
a.send(@method, eval("(9...)")).should == nil a.send(@method, eval("(-9..)")).should == nil
a.send(@method, eval("(-9..)")).should == nil a.send(@method, eval("(-9...)")).should == nil
a.send(@method, eval("(-9...)")).should == nil
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -154,24 +154,22 @@ describe "Array#slice!" do
-> { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(FrozenError) -> { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(FrozenError)
end end
ruby_version_is "2.6" do it "works with endless ranges" do
it "works with endless ranges" do a = [1, 2, 3]
a = [1, 2, 3] a.slice!(eval("(1..)")).should == [2, 3]
a.slice!(eval("(1..)")).should == [2, 3] a.should == [1]
a.should == [1]
a = [1, 2, 3] a = [1, 2, 3]
a.slice!(eval("(2...)")).should == [3] a.slice!(eval("(2...)")).should == [3]
a.should == [1, 2] a.should == [1, 2]
a = [1, 2, 3] a = [1, 2, 3]
a.slice!(eval("(-2..)")).should == [2, 3] a.slice!(eval("(-2..)")).should == [2, 3]
a.should == [1] a.should == [1]
a = [1, 2, 3] a = [1, 2, 3]
a.slice!(eval("(-1...)")).should == [3] a.slice!(eval("(-1...)")).should == [3]
a.should == [1, 2] a.should == [1, 2]
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -39,43 +39,41 @@ describe "Array#to_h" do
[[:a, 1], [:b, 2]].to_h[:c].should be_nil [[:a, 1], [:b, 2]].to_h[:c].should be_nil
end end
ruby_version_is "2.6" do context "with block" do
context "with block" do it "converts [key, value] pairs returned by the block to a Hash" do
it "converts [key, value] pairs returned by the block to a Hash" do [:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
[:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' } end
end
it "raises ArgumentError if block returns longer or shorter array" do it "raises ArgumentError if block returns longer or shorter array" do
-> do -> do
[:a, :b].to_h { |k| [k, k.to_s, 1] } [:a, :b].to_h { |k| [k, k.to_s, 1] }
end.should raise_error(ArgumentError, /wrong array length at 0/) end.should raise_error(ArgumentError, /wrong array length at 0/)
-> do -> do
[:a, :b].to_h { |k| [k] } [:a, :b].to_h { |k| [k] }
end.should raise_error(ArgumentError, /wrong array length at 0/) end.should raise_error(ArgumentError, /wrong array length at 0/)
end end
it "raises TypeError if block returns something other than Array" do it "raises TypeError if block returns something other than Array" do
-> do -> do
[:a, :b].to_h { |k| "not-array" } [:a, :b].to_h { |k| "not-array" }
end.should raise_error(TypeError, /wrong element type String at 0/) end.should raise_error(TypeError, /wrong element type String at 0/)
end end
it "coerces returned pair to Array with #to_ary" do it "coerces returned pair to Array with #to_ary" do
x = mock('x') x = mock('x')
x.stub!(:to_ary).and_return([:b, 'b']) x.stub!(:to_ary).and_return([:b, 'b'])
[:a].to_h { |k| x }.should == { :b => 'b' } [:a].to_h { |k| x }.should == { :b => 'b' }
end end
it "does not coerce returned pair to Array with #to_a" do it "does not coerce returned pair to Array with #to_a" do
x = mock('x') x = mock('x')
x.stub!(:to_a).and_return([:b, 'b']) x.stub!(:to_a).and_return([:b, 'b'])
-> do -> do
[:a].to_h { |k| x } [:a].to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject at 0/) end.should raise_error(TypeError, /wrong element type MockObject at 0/)
end
end end
end end
end end

View file

@ -6,22 +6,20 @@ describe "Array#|" do
it_behaves_like :array_binary_union, :| it_behaves_like :array_binary_union, :|
end end
ruby_version_is "2.6" do describe "Array#union" do
describe "Array#union" do it_behaves_like :array_binary_union, :union
it_behaves_like :array_binary_union, :union
it "returns unique elements when given no argument" do it "returns unique elements when given no argument" do
x = [1, 2, 3, 2] x = [1, 2, 3, 2]
x.union.should == [1, 2, 3] x.union.should == [1, 2, 3]
end end
it "does not return subclass instances for Array subclasses" do it "does not return subclass instances for Array subclasses" do
ArraySpecs::MyArray[1, 2, 3].union.should be_an_instance_of(Array) ArraySpecs::MyArray[1, 2, 3].union.should be_an_instance_of(Array)
end end
it "accepts multiple arguments" do it "accepts multiple arguments" do
x = [1, 2, 3] x = [1, 2, 3]
x.union(x, x, x, x, [3, 4], x).should == [1, 2, 3, 4] x.union(x, x, x, x, [3, 4], x).should == [1, 2, 3, 4]
end
end end
end end

View file

@ -61,11 +61,9 @@ describe "Array#values_at" do
ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should be_an_instance_of(Array) ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should be_an_instance_of(Array)
end end
ruby_version_is "2.6" do it "works when given endless ranges" do
it "works when given endless ranges" do [1, 2, 3, 4].values_at(eval("(1..)")).should == [2, 3, 4]
[1, 2, 3, 4].values_at(eval("(1..)")).should == [2, 3, 4] [1, 2, 3, 4].values_at(eval("(3...)")).should == [4]
[1, 2, 3, 4].values_at(eval("(3...)")).should == [4]
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -1,11 +1,9 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/location' require_relative 'fixtures/location'
ruby_version_is "2.6" do describe "Binding#source_location" do
describe "Binding#source_location" do it "returns an [file, line] pair" do
it "returns an [file, line] pair" do b = BindingSpecs::LocationMethod::TEST_BINDING
b = BindingSpecs::LocationMethod::TEST_BINDING b.source_location.should == [BindingSpecs::LocationMethod::FILE_PATH, 4]
b.source_location.should == [BindingSpecs::LocationMethod::FILE_PATH, 4]
end
end end
end end

View file

@ -69,76 +69,74 @@ describe "Dir.children" do
end end
end end
ruby_version_is "2.6" do describe "Dir#children" do
describe "Dir#children" do before :all do
before :all do DirSpecs.create_mock_dirs
DirSpecs.create_mock_dirs end
end
before :each do before :each do
@internal = Encoding.default_internal @internal = Encoding.default_internal
end end
after :all do after :all do
DirSpecs.delete_mock_dirs DirSpecs.delete_mock_dirs
end end
after :each do after :each do
Encoding.default_internal = @internal Encoding.default_internal = @internal
@dir.close if @dir @dir.close if @dir
end end
it "returns an Array of filenames in an existing directory including dotfiles" do it "returns an Array of filenames in an existing directory including dotfiles" do
@dir = Dir.new(DirSpecs.mock_dir) @dir = Dir.new(DirSpecs.mock_dir)
a = @dir.children.sort a = @dir.children.sort
@dir.close @dir.close
a.should == DirSpecs.expected_paths - %w[. ..] a.should == DirSpecs.expected_paths - %w[. ..]
@dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested") @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested")
a = @dir.children.sort a = @dir.children.sort
a.should == %w|.dotfile.ext directory| a.should == %w|.dotfile.ext directory|
end end
it "accepts an encoding keyword for the encoding of the entries" do it "accepts an encoding keyword for the encoding of the entries" do
@dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8") @dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8")
dirs = @dir.to_a.sort
dirs.each { |d| d.encoding.should == Encoding::UTF_8 }
end
ruby_version_is ""..."2.7" do
it "accepts nil options" do
@dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", nil)
dirs = @dir.to_a.sort dirs = @dir.to_a.sort
dirs.each { |d| d.encoding.should == Encoding::UTF_8 } dirs.each { |d| d.encoding.should == Encoding.find("filesystem") }
end
ruby_version_is ""..."2.7" do
it "accepts nil options" do
@dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", nil)
dirs = @dir.to_a.sort
dirs.each { |d| d.encoding.should == Encoding.find("filesystem") }
end
end
it "returns children encoded with the filesystem encoding by default" do
# This spec depends on the locale not being US-ASCII because if it is, the
# children that are not ascii_only? will be BINARY encoded.
@dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
children = @dir.children.sort
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
children.should include("こんにちは.txt".force_encoding(encoding))
end
children.first.encoding.should equal(Encoding.find("filesystem"))
end
it "returns children encoded with the specified encoding" do
path = File.join(DirSpecs.mock_dir, 'special')
@dir = Dir.new(path, encoding: "euc-jp")
children = @dir.children.sort
children.first.encoding.should equal(Encoding::EUC_JP)
end
it "returns children transcoded to the default internal encoding" do
Encoding.default_internal = Encoding::EUC_KR
@dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
children = @dir.children.sort
children.first.encoding.should equal(Encoding::EUC_KR)
end end
end end
it "returns children encoded with the filesystem encoding by default" do
# This spec depends on the locale not being US-ASCII because if it is, the
# children that are not ascii_only? will be BINARY encoded.
@dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
children = @dir.children.sort
encoding = Encoding.find("filesystem")
encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
platform_is_not :windows do
children.should include("こんにちは.txt".force_encoding(encoding))
end
children.first.encoding.should equal(Encoding.find("filesystem"))
end
it "returns children encoded with the specified encoding" do
path = File.join(DirSpecs.mock_dir, 'special')
@dir = Dir.new(path, encoding: "euc-jp")
children = @dir.children.sort
children.first.encoding.should equal(Encoding::EUC_JP)
end
it "returns children transcoded to the default internal encoding" do
Encoding.default_internal = Encoding::EUC_KR
@dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
children = @dir.children.sort
children.first.encoding.should equal(Encoding::EUC_KR)
end
end end

View file

@ -62,52 +62,50 @@ describe "Dir.each_child" do
end end
end end
ruby_version_is "2.6" do describe "Dir#each_child" do
describe "Dir#each_child" do before :all do
before :all do DirSpecs.create_mock_dirs
DirSpecs.create_mock_dirs end
end
after :all do after :all do
DirSpecs.delete_mock_dirs DirSpecs.delete_mock_dirs
end end
after :each do after :each do
@dir.close if @dir @dir.close if @dir
end end
it "yields all names in an existing directory to the provided block" do it "yields all names in an existing directory to the provided block" do
a, b = [], [] a, b = [], []
@dir = Dir.new(DirSpecs.mock_dir)
@dir2 = Dir.new("#{DirSpecs.mock_dir}/deeply/nested")
@dir.each_child { |f| a << f }
@dir2.each_child { |f| b << f }
@dir2.close
a.sort.should == DirSpecs.expected_paths - %w|. ..|
b.sort.should == %w|.dotfile.ext directory|
end
it "returns self when successful" do
@dir = Dir.new(DirSpecs.mock_dir)
@dir.each_child { |f| f }.should == @dir
end
describe "when no block is given" do
it "returns an Enumerator" do
@dir = Dir.new(DirSpecs.mock_dir) @dir = Dir.new(DirSpecs.mock_dir)
@dir2 = Dir.new("#{DirSpecs.mock_dir}/deeply/nested")
@dir.each_child { |f| a << f } @dir.each_child.should be_an_instance_of(Enumerator)
@dir2.each_child { |f| b << f } @dir.each_child.to_a.sort.should == DirSpecs.expected_paths - %w|. ..|
@dir2.close
a.sort.should == DirSpecs.expected_paths - %w|. ..|
b.sort.should == %w|.dotfile.ext directory|
end end
it "returns self when successful" do describe "returned Enumerator" do
@dir = Dir.new(DirSpecs.mock_dir) describe "size" do
@dir.each_child { |f| f }.should == @dir it "should return nil" do
end @dir = Dir.new(DirSpecs.mock_dir)
@dir.each_child.size.should == nil
describe "when no block is given" do
it "returns an Enumerator" do
@dir = Dir.new(DirSpecs.mock_dir)
@dir.each_child.should be_an_instance_of(Enumerator)
@dir.each_child.to_a.sort.should == DirSpecs.expected_paths - %w|. ..|
end
describe "returned Enumerator" do
describe "size" do
it "should return nil" do
@dir = Dir.new(DirSpecs.mock_dir)
@dir.each_child.size.should == nil
end
end end
end end
end end

View file

@ -29,6 +29,23 @@ describe "Dir.glob" do
%w!file_one.ext file_two.ext! %w!file_one.ext file_two.ext!
end end
it 'returns matching file paths when supplied :base keyword argument' do
dir = tmp('dir_glob_base')
file_1 = "#{dir}/lib/bloop.rb"
file_2 = "#{dir}/lib/soup.rb"
file_3 = "#{dir}/lib/mismatched_file_type.txt"
file_4 = "#{dir}/mismatched_directory.rb"
touch file_1
touch file_2
touch file_3
touch file_4
Dir.glob('**/*.rb', base: "#{dir}/lib").sort.should == ["bloop.rb", "soup.rb"].sort
ensure
rm_r dir
end
it "calls #to_path to convert multiple patterns" do it "calls #to_path to convert multiple patterns" do
pat1 = mock('file_one.ext') pat1 = mock('file_one.ext')
pat1.should_receive(:to_path).and_return('file_one.ext') pat1.should_receive(:to_path).and_return('file_one.ext')
@ -133,6 +150,14 @@ describe "Dir.glob" do
Dir.glob('{deeply/**/,subdir_two/*}').sort.should == expected Dir.glob('{deeply/**/,subdir_two/*}').sort.should == expected
end end
it "preserves multiple /s before a **" do
expected = %w[
deeply//nested/directory/structure
]
Dir.glob('{deeply//**/structure}').sort.should == expected
end
it "accepts a block and yields it with each elements" do it "accepts a block and yields it with each elements" do
ary = [] ary = []
ret = Dir.glob(["file_o*", "file_t*"]) { |t| ary << t } ret = Dir.glob(["file_o*", "file_t*"]) { |t| ary << t }

View file

@ -23,14 +23,7 @@ describe :dir_glob, shared: true do
Dir.send(@method, obj).should == %w[file_one.ext] Dir.send(@method, obj).should == %w[file_one.ext]
end end
ruby_version_is ""..."2.6" do ruby_version_is ""..."2.7" do
it "splits the string on \\0 if there is only one string given" do
Dir.send(@method, "file_o*\0file_t*").should ==
%w!file_one.ext file_two.ext!
end
end
ruby_version_is "2.6"..."2.7" do
it "splits the string on \\0 if there is only one string given and warns" do it "splits the string on \\0 if there is only one string given and warns" do
-> { -> {
Dir.send(@method, "file_o*\0file_t*").should == Dir.send(@method, "file_o*\0file_t*").should ==
@ -205,6 +198,14 @@ describe :dir_glob, shared: true do
Dir.send(@method, '**/').sort.should == expected Dir.send(@method, '**/').sort.should == expected
end end
it "recursively matches any subdirectories except './' or '../' with '**/' from the base directory if that is specified" do
expected = %w[
nested/directory
]
Dir.send(@method, '**/*ory', base: 'deeply').sort.should == expected
end
ruby_version_is ''...'3.1' do ruby_version_is ''...'3.1' do
it "recursively matches any subdirectories including ./ and ../ with '.**/'" do it "recursively matches any subdirectories including ./ and ../ with '.**/'" do
Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do

View file

@ -132,14 +132,6 @@ describe "Enumerable#all?" do
end end
# may raise an exception in future versions # may raise an exception in future versions
ruby_version_is ""..."2.6" do
it "ignores block" do
@enum2.all?(NilClass) { raise }.should == false
[1, 2, nil].all?(NilClass) { raise }.should == false
{a: 1}.all?(Array) { raise }.should == true
end
end
it "always returns true on empty enumeration" do it "always returns true on empty enumeration" do
@empty.all?(Integer).should == true @empty.all?(Integer).should == true
[].all?(Integer).should == true [].all?(Integer).should == true

View file

@ -146,14 +146,6 @@ describe "Enumerable#any?" do
end end
# may raise an exception in future versions # may raise an exception in future versions
ruby_version_is ""..."2.6" do
it "ignores block" do
@enum2.any?(NilClass) { raise }.should == true
[1, 2, nil].any?(NilClass) { raise }.should == true
{a: 1}.any?(Array) { raise }.should == true
end
end
it "always returns false on empty enumeration" do it "always returns false on empty enumeration" do
@empty.any?(Integer).should == false @empty.any?(Integer).should == false
[].any?(Integer).should == false [].any?(Integer).should == false

View file

@ -1,25 +1,23 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
ruby_version_is "2.6" do describe "Enumerable#chain" do
describe "Enumerable#chain" do before :each do
before :each do ScratchPad.record []
ScratchPad.record [] end
end
it "returns a chain of self and provided enumerables" do it "returns a chain of self and provided enumerables" do
one = EnumerableSpecs::Numerous.new(1) one = EnumerableSpecs::Numerous.new(1)
two = EnumerableSpecs::Numerous.new(2, 3) two = EnumerableSpecs::Numerous.new(2, 3)
three = EnumerableSpecs::Numerous.new(4, 5, 6) three = EnumerableSpecs::Numerous.new(4, 5, 6)
chain = one.chain(two, three) chain = one.chain(two, three)
chain.each { |item| ScratchPad << item } chain.each { |item| ScratchPad << item }
ScratchPad.recorded.should == [1, 2, 3, 4, 5, 6] ScratchPad.recorded.should == [1, 2, 3, 4, 5, 6]
end end
it "returns an Enumerator::Chain if given a block" do it "returns an Enumerator::Chain if given a block" do
EnumerableSpecs::Numerous.new.chain.should be_an_instance_of(Enumerator::Chain) EnumerableSpecs::Numerous.new.chain.should be_an_instance_of(Enumerator::Chain)
end
end end
end end

View file

@ -2,8 +2,6 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
require_relative 'shared/find_all' require_relative 'shared/find_all'
ruby_version_is "2.6" do describe "Enumerable#filter" do
describe "Enumerable#filter" do it_behaves_like(:enumerable_find_all , :filter)
it_behaves_like(:enumerable_find_all , :filter)
end
end end

View file

@ -101,14 +101,6 @@ describe "Enumerable#none?" do
end end
# may raise an exception in future versions # may raise an exception in future versions
ruby_version_is ""..."2.6" do
it "ignores block" do
@enum2.none?(Integer) { raise }.should == true
[1, 2, nil].none?(TrueClass) { raise }.should == true
{a: 1}.none?(Hash) { raise }.should == true
end
end
it "always returns true on empty enumeration" do it "always returns true on empty enumeration" do
@empty.none?(Integer).should == true @empty.none?(Integer).should == true
[].none?(Integer).should == true [].none?(Integer).should == true

View file

@ -92,14 +92,6 @@ describe "Enumerable#one?" do
end end
# may raise an exception in future versions # may raise an exception in future versions
ruby_version_is ""..."2.6" do
it "ignores block" do
@enum2.one?(NilClass) { raise }.should == true
[1, 2, nil].one?(NilClass) { raise }.should == true
{a: 1}.one?(Array) { raise }.should == true
end
end
it "always returns false on empty enumeration" do it "always returns false on empty enumeration" do
@empty.one?(Integer).should == false @empty.one?(Integer).should == false
[].one?(Integer).should == false [].one?(Integer).should == false

View file

@ -44,47 +44,45 @@ describe "Enumerable#to_h" do
-> { enum.to_h }.should raise_error(ArgumentError) -> { enum.to_h }.should raise_error(ArgumentError)
end end
ruby_version_is "2.6" do context "with block" do
context "with block" do before do
before do @enum = EnumerableSpecs::EachDefiner.new(:a, :b)
@enum = EnumerableSpecs::EachDefiner.new(:a, :b) end
end
it "converts [key, value] pairs returned by the block to a hash" do it "converts [key, value] pairs returned by the block to a hash" do
@enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' } @enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
end end
it "raises ArgumentError if block returns longer or shorter array" do it "raises ArgumentError if block returns longer or shorter array" do
-> do -> do
@enum.to_h { |k| [k, k.to_s, 1] } @enum.to_h { |k| [k, k.to_s, 1] }
end.should raise_error(ArgumentError, /element has wrong array length/) end.should raise_error(ArgumentError, /element has wrong array length/)
-> do -> do
@enum.to_h { |k| [k] } @enum.to_h { |k| [k] }
end.should raise_error(ArgumentError, /element has wrong array length/) end.should raise_error(ArgumentError, /element has wrong array length/)
end end
it "raises TypeError if block returns something other than Array" do it "raises TypeError if block returns something other than Array" do
-> do -> do
@enum.to_h { |k| "not-array" } @enum.to_h { |k| "not-array" }
end.should raise_error(TypeError, /wrong element type String/) end.should raise_error(TypeError, /wrong element type String/)
end end
it "coerces returned pair to Array with #to_ary" do it "coerces returned pair to Array with #to_ary" do
x = mock('x') x = mock('x')
x.stub!(:to_ary).and_return([:b, 'b']) x.stub!(:to_ary).and_return([:b, 'b'])
@enum.to_h { |k| x }.should == { :b => 'b' } @enum.to_h { |k| x }.should == { :b => 'b' }
end end
it "does not coerce returned pair to Array with #to_a" do it "does not coerce returned pair to Array with #to_a" do
x = mock('x') x = mock('x')
x.stub!(:to_a).and_return([:b, 'b']) x.stub!(:to_a).and_return([:b, 'b'])
-> do -> do
@enum.to_h { |k| x } @enum.to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject/) end.should raise_error(TypeError, /wrong element type MockObject/)
end
end end
end end
end end

View file

@ -1,11 +1,9 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#begin" do
describe "Enumerator::ArithmeticSequence#begin" do it "returns the begin of the sequence" do
it "returns the begin of the sequence" do 1.step(10).begin.should == 1
1.step(10).begin.should == 1 (1..10).step.begin.should == 1
(1..10).step.begin.should == 1 (1...10).step.begin.should == 1
(1...10).step.begin.should == 1
end
end end
end end

View file

@ -1,19 +1,17 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#each" do
describe "Enumerator::ArithmeticSequence#each" do before :each do
before :each do ScratchPad.record []
ScratchPad.record [] @seq = 1.step(10, 4)
@seq = 1.step(10, 4) end
end
it "calls given block on each item of the sequence" do it "calls given block on each item of the sequence" do
@seq.each { |item| ScratchPad << item } @seq.each { |item| ScratchPad << item }
ScratchPad.recorded.should == [1, 5, 9] ScratchPad.recorded.should == [1, 5, 9]
end end
it "returns self" do it "returns self" do
@seq.each { |item| }.should equal(@seq) @seq.each { |item| }.should equal(@seq)
end
end end
end end

View file

@ -1,11 +1,9 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#end" do
describe "Enumerator::ArithmeticSequence#end" do it "returns the end of the sequence" do
it "returns the end of the sequence" do 1.step(10).end.should == 10
1.step(10).end.should == 10 (1..10).step.end.should == 10
(1..10).step.end.should == 10 (1...10).step(17).end.should == 10
(1...10).step(17).end.should == 10
end
end end
end end

View file

@ -1,20 +1,18 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#==" do
describe "Enumerator::ArithmeticSequence#==" do it "returns true if begin, end, step and exclude_end? are equal" do
it "returns true if begin, end, step and exclude_end? are equal" do 1.step(10).should == 1.step(10)
1.step(10).should == 1.step(10) 1.step(10, 5).should == 1.step(10, 5)
1.step(10, 5).should == 1.step(10, 5)
(1..10).step.should == (1..10).step (1..10).step.should == (1..10).step
(1...10).step(8).should == (1...10).step(8) (1...10).step(8).should == (1...10).step(8)
# both have exclude_end? == false # both have exclude_end? == false
(1..10).step(100).should == 1.step(10, 100) (1..10).step(100).should == 1.step(10, 100)
((1..10).step == (1..11).step).should == false ((1..10).step == (1..11).step).should == false
((1..10).step == (1...10).step).should == false ((1..10).step == (1...10).step).should == false
((1..10).step == (1..10).step(2)).should == false ((1..10).step == (1..10).step(2)).should == false
end
end end
end end

View file

@ -1,19 +1,17 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#exclude_end?" do
describe "Enumerator::ArithmeticSequence#exclude_end?" do context "when created using Numeric#step" do
context "when created using Numeric#step" do it "always returns false" do
it "always returns false" do 1.step(10).should_not.exclude_end?
1.step(10).should_not.exclude_end? 10.step(1).should_not.exclude_end?
10.step(1).should_not.exclude_end?
end
end end
end
context "when created using Range#step" do context "when created using Range#step" do
it "mirrors range.exclude_end?" do it "mirrors range.exclude_end?" do
(1...10).step.should.exclude_end? (1...10).step.should.exclude_end?
(1..10).step.should_not.exclude_end? (1..10).step.should_not.exclude_end?
end
end end
end end
end end

View file

@ -1,11 +1,9 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#first" do
describe "Enumerator::ArithmeticSequence#first" do it "returns the first element of the sequence" do
it "returns the first element of the sequence" do 1.step(10).first.should == 1
1.step(10).first.should == 1 (1..10).step.first.should == 1
(1..10).step.first.should == 1 (1...10).step.first.should == 1
(1...10).step.first.should == 1
end
end end
end end

View file

@ -1,22 +1,20 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#hash" do
describe "Enumerator::ArithmeticSequence#hash" do it "is based on begin, end, step and exclude_end?" do
it "is based on begin, end, step and exclude_end?" do 1.step(10).hash.should be_an_instance_of(Integer)
1.step(10).hash.should be_an_instance_of(Integer)
1.step(10).hash.should == 1.step(10).hash 1.step(10).hash.should == 1.step(10).hash
1.step(10, 5).hash.should == 1.step(10, 5).hash 1.step(10, 5).hash.should == 1.step(10, 5).hash
(1..10).step.hash.should == (1..10).step.hash (1..10).step.hash.should == (1..10).step.hash
(1...10).step(8).hash.should == (1...10).step(8).hash (1...10).step(8).hash.should == (1...10).step(8).hash
# both have exclude_end? == false # both have exclude_end? == false
(1..10).step(100).hash.should == 1.step(10, 100).hash (1..10).step(100).hash.should == 1.step(10, 100).hash
((1..10).step.hash == (1..11).step.hash).should == false ((1..10).step.hash == (1..11).step.hash).should == false
((1..10).step.hash == (1...10).step.hash).should == false ((1..10).step.hash == (1...10).step.hash).should == false
((1..10).step.hash == (1..10).step(2).hash).should == false ((1..10).step.hash == (1..10).step(2).hash).should == false
end
end end
end end

View file

@ -1,22 +1,20 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#inspect" do
describe "Enumerator::ArithmeticSequence#inspect" do context 'when Numeric#step is used' do
context 'when Numeric#step is used' do it "returns '(begin.step(end{, step}))'" do
it "returns '(begin.step(end{, step}))'" do 1.step(10).inspect.should == "(1.step(10))"
1.step(10).inspect.should == "(1.step(10))" 1.step(10, 3).inspect.should == "(1.step(10, 3))"
1.step(10, 3).inspect.should == "(1.step(10, 3))"
end
end end
end
context 'when Range#step is used' do context 'when Range#step is used' do
it "returns '((range).step{(step)})'" do it "returns '((range).step{(step)})'" do
(1..10).step.inspect.should == "((1..10).step)" (1..10).step.inspect.should == "((1..10).step)"
(1..10).step(3).inspect.should == "((1..10).step(3))" (1..10).step(3).inspect.should == "((1..10).step(3))"
(1...10).step.inspect.should == "((1...10).step)" (1...10).step.inspect.should == "((1...10).step)"
(1...10).step(3).inspect.should == "((1...10).step(3))" (1...10).step(3).inspect.should == "((1...10).step(3))"
end
end end
end end
end end

View file

@ -1,11 +1,9 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#last" do
describe "Enumerator::ArithmeticSequence#last" do it "returns the last element of the sequence" do
it "returns the last element of the sequence" do 1.step(10).last.should == 10
1.step(10).last.should == 10 (1..10).step.last.should == 10
(1..10).step.last.should == 10 (1...10).step(4).last.should == 9
(1...10).step(4).last.should == 9
end
end end
end end

View file

@ -1,19 +1,17 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence.new" do
describe "Enumerator::ArithmeticSequence.new" do it "is not defined" do
it "is not defined" do -> {
-> { Enumerator::ArithmeticSequence.new
Enumerator::ArithmeticSequence.new }.should raise_error(NoMethodError)
}.should raise_error(NoMethodError) end
end end
end
describe "Enumerator::ArithmeticSequence.allocate" do
describe "Enumerator::ArithmeticSequence.allocate" do it "is not defined" do
it "is not defined" do -> {
-> { Enumerator::ArithmeticSequence.allocate
Enumerator::ArithmeticSequence.allocate }.should raise_error(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence')
}.should raise_error(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence')
end
end end
end end

View file

@ -1,19 +1,17 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#size" do
describe "Enumerator::ArithmeticSequence#size" do context "for finite sequence" do
context "for finite sequence" do it "returns the number of elements in this arithmetic sequence" do
it "returns the number of elements in this arithmetic sequence" do 1.step(10).size.should == 10
1.step(10).size.should == 10 (1...10).step.size.should == 9
(1...10).step.size.should == 9
end
end end
end
context "for infinite sequence" do context "for infinite sequence" do
it "returns Infinity" do it "returns Infinity" do
1.step(Float::INFINITY).size.should == Float::INFINITY 1.step(Float::INFINITY).size.should == Float::INFINITY
(1..Float::INFINITY).step.size.should == Float::INFINITY (1..Float::INFINITY).step.size.should == Float::INFINITY
end
end end
end end
end end

View file

@ -1,13 +1,11 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::ArithmeticSequence#step" do
describe "Enumerator::ArithmeticSequence#step" do it "returns the original value given to step method" do
it "returns the original value given to step method" do (1..10).step.step.should == 1
(1..10).step.step.should == 1 (1..10).step(3).step.should == 3
(1..10).step(3).step.should == 3
1.step(10).step.should == 1 1.step(10).step.should == 1
1.step(10, 3).step.should == 3 1.step(10, 3).step.should == 3
end
end end
end end

View file

@ -1,17 +1,15 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
require_relative '../../enumerable/fixtures/classes' require_relative '../../enumerable/fixtures/classes'
ruby_version_is "2.6" do describe "Enumerator::Chain#each" do
describe "Enumerator::Chain#each" do it "calls each on its constituents as needed" do
it "calls each on its constituents as needed" do a = EnumerableSpecs::EachCounter.new(:a, :b)
a = EnumerableSpecs::EachCounter.new(:a, :b) b = EnumerableSpecs::EachCounter.new(:c, :d)
b = EnumerableSpecs::EachCounter.new(:c, :d)
ScratchPad.record [] ScratchPad.record []
Enumerator::Chain.new(a, b).each do |elem| Enumerator::Chain.new(a, b).each do |elem|
ScratchPad << elem << b.times_yielded ScratchPad << elem << b.times_yielded
end
ScratchPad.recorded.should == [:a, 0, :b, 0, :c, 1, :d, 2]
end end
ScratchPad.recorded.should == [:a, 0, :b, 0, :c, 1, :d, 2]
end end
end end

View file

@ -1,33 +1,31 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::Chain#initialize" do
describe "Enumerator::Chain#initialize" do before :each do
before :each do @uninitialized = Enumerator::Chain.allocate
@uninitialized = Enumerator::Chain.allocate end
end
it "is a private method" do it "is a private method" do
Enumerator::Chain.should have_private_instance_method(:initialize, false) Enumerator::Chain.should have_private_instance_method(:initialize, false)
end end
it "returns self" do it "returns self" do
@uninitialized.send(:initialize).should equal(@uninitialized) @uninitialized.send(:initialize).should equal(@uninitialized)
end end
it "accepts many arguments" do it "accepts many arguments" do
@uninitialized.send(:initialize, 0..1, 2..3, 4..5).should equal(@uninitialized) @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should equal(@uninitialized)
end end
it "accepts arguments that are not Enumerable nor responding to :each" do it "accepts arguments that are not Enumerable nor responding to :each" do
@uninitialized.send(:initialize, Object.new).should equal(@uninitialized) @uninitialized.send(:initialize, Object.new).should equal(@uninitialized)
end end
describe "on frozen instance" do describe "on frozen instance" do
it "raises a RuntimeError" do it "raises a RuntimeError" do
-> { -> {
@uninitialized.freeze.send(:initialize) @uninitialized.freeze.send(:initialize)
}.should raise_error(RuntimeError) }.should raise_error(RuntimeError)
end
end end
end end
end end

View file

@ -1,16 +1,14 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::Chain#inspect" do
describe "Enumerator::Chain#inspect" do it "shows a representation of the Enumerator" do
it "shows a representation of the Enumerator" do Enumerator::Chain.new.inspect.should == "#<Enumerator::Chain: []>"
Enumerator::Chain.new.inspect.should == "#<Enumerator::Chain: []>" Enumerator::Chain.new(1..2, 3..4).inspect.should == "#<Enumerator::Chain: [1..2, 3..4]>"
Enumerator::Chain.new(1..2, 3..4).inspect.should == "#<Enumerator::Chain: [1..2, 3..4]>" end
end
it "calls inspect on its chain elements" do it "calls inspect on its chain elements" do
obj = mock('inspect') obj = mock('inspect')
obj.should_receive(:inspect).and_return('some desc') obj.should_receive(:inspect).and_return('some desc')
Enumerator::Chain.new(obj).inspect.should == "#<Enumerator::Chain: [some desc]>" Enumerator::Chain.new(obj).inspect.should == "#<Enumerator::Chain: [some desc]>"
end
end end
end end

View file

@ -1,53 +1,51 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator::Chain#rewind" do
describe "Enumerator::Chain#rewind" do before(:each) do
before(:each) do @obj = mock('obj')
@obj = mock('obj') @obj.should_receive(:each).any_number_of_times.and_yield
@obj.should_receive(:each).any_number_of_times.and_yield @second = mock('obj')
@second = mock('obj') @second.should_receive(:each).any_number_of_times.and_yield
@second.should_receive(:each).any_number_of_times.and_yield @enum = Enumerator::Chain.new(@obj, @second)
@enum = Enumerator::Chain.new(@obj, @second) end
end
it "returns self" do it "returns self" do
@enum.rewind.should equal @enum @enum.rewind.should equal @enum
end end
it "does nothing if receiver has not been iterated" do it "does nothing if receiver has not been iterated" do
@obj.should_not_receive(:rewind) @obj.should_not_receive(:rewind)
@obj.respond_to?(:rewind).should == true # sanity check @obj.respond_to?(:rewind).should == true # sanity check
@enum.rewind @enum.rewind
end end
it "does nothing on objects that don't respond_to rewind" do it "does nothing on objects that don't respond_to rewind" do
@obj.respond_to?(:rewind).should == false # sanity check @obj.respond_to?(:rewind).should == false # sanity check
@enum.each {} @enum.each {}
@enum.rewind @enum.rewind
end end
it "calls_rewind its objects" do it "calls_rewind its objects" do
@obj.should_receive(:rewind) @obj.should_receive(:rewind)
@enum.each {} @enum.each {}
@enum.rewind @enum.rewind
end end
it "calls_rewind in reverse order" do it "calls_rewind in reverse order" do
@obj.should_not_receive(:rewind) @obj.should_not_receive(:rewind)
@second.should_receive(:rewind).and_raise(RuntimeError) @second.should_receive(:rewind).and_raise(RuntimeError)
@enum.each {} @enum.each {}
-> { @enum.rewind }.should raise_error(RuntimeError) -> { @enum.rewind }.should raise_error(RuntimeError)
end end
it "calls rewind only for objects that have actually been iterated on" do it "calls rewind only for objects that have actually been iterated on" do
@obj = mock('obj') @obj = mock('obj')
@obj.should_receive(:each).any_number_of_times.and_raise(RuntimeError) @obj.should_receive(:each).any_number_of_times.and_raise(RuntimeError)
@enum = Enumerator::Chain.new(@obj, @second) @enum = Enumerator::Chain.new(@obj, @second)
@obj.should_receive(:rewind) @obj.should_receive(:rewind)
@second.should_not_receive(:rewind) @second.should_not_receive(:rewind)
-> { @enum.each {} }.should raise_error(RuntimeError) -> { @enum.each {} }.should raise_error(RuntimeError)
@enum.rewind @enum.rewind
end
end end
end end

View file

@ -1,24 +1,22 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
require_relative '../../enumerable/fixtures/classes' require_relative '../../enumerable/fixtures/classes'
ruby_version_is "2.6" do describe "Enumerator::Chain#size" do
describe "Enumerator::Chain#size" do it "returns the sum of the sizes of the elements" do
it "returns the sum of the sizes of the elements" do a = mock('size')
a.should_receive(:size).and_return(40)
Enumerator::Chain.new(a, [:a, :b]).size.should == 42
end
it "returns nil or Infinity for the first element of such a size" do
[nil, Float::INFINITY].each do |special|
a = mock('size') a = mock('size')
a.should_receive(:size).and_return(40) a.should_receive(:size).and_return(40)
Enumerator::Chain.new(a, [:a, :b]).size.should == 42 b = mock('special')
end b.should_receive(:size).and_return(special)
c = mock('not called')
it "returns nil or Infinity for the first element of such a size" do c.should_not_receive(:size)
[nil, Float::INFINITY].each do |special| Enumerator::Chain.new(a, b, c).size.should == special
a = mock('size')
a.should_receive(:size).and_return(40)
b = mock('special')
b.should_receive(:size).and_return(special)
c = mock('not called')
c.should_not_receive(:size)
Enumerator::Chain.new(a, b, c).size.should == special
end
end end
end end
end end

View file

@ -1,8 +1,6 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
require_relative 'shared/select' require_relative 'shared/select'
ruby_version_is "2.6" do describe "Enumerator::Lazy#filter" do
describe "Enumerator::Lazy#filter" do it_behaves_like :enumerator_lazy_select, :filter
it_behaves_like :enumerator_lazy_select, :filter
end
end end

View file

@ -0,0 +1,30 @@
# -*- encoding: us-ascii -*-
require_relative '../../../spec_helper'
require_relative 'fixtures/classes'
ruby_version_is "2.7" do
describe "Enumerator::Lazy#with_index" do
it "enumerates with an index" do
(0..Float::INFINITY).lazy.with_index.map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
end
it "enumerates with an index starting at a given offset" do
(0..Float::INFINITY).lazy.with_index(3).map { |i, idx| [i, idx] }.first(3).should == [[0, 3], [1, 4], [2, 5]]
end
it "enumerates with an index starting at 0 when offset is nil" do
(0..Float::INFINITY).lazy.with_index(nil).map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
end
it "raises TypeError when offset does not convert to Integer" do
-> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should raise_error(TypeError)
end
it "enumerates with a given block" do
result = []
(0..Float::INFINITY).lazy.with_index { |i, idx| result << [i * 2, idx] }.first(3)
result.should == [[0,0],[2,1],[4,2]]
end
end
end

View file

@ -1,35 +1,33 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.6" do describe "Enumerator#+" do
describe "Enumerator#+" do before :each do
before :each do ScratchPad.record []
ScratchPad.record [] end
end
it "returns a chain of self and provided enumerators" do it "returns a chain of self and provided enumerators" do
one = Enumerator.new { |y| y << 1 } one = Enumerator.new { |y| y << 1 }
two = Enumerator.new { |y| y << 2 } two = Enumerator.new { |y| y << 2 }
three = Enumerator.new { |y| y << 3 } three = Enumerator.new { |y| y << 3 }
chain = one + two + three chain = one + two + three
chain.should be_an_instance_of(Enumerator::Chain) chain.should be_an_instance_of(Enumerator::Chain)
chain.each { |item| ScratchPad << item } chain.each { |item| ScratchPad << item }
ScratchPad.recorded.should == [1, 2, 3] ScratchPad.recorded.should == [1, 2, 3]
end end
it "calls #each on each argument" do it "calls #each on each argument" do
enum = Enumerator.new { |y| y << "one" } enum = Enumerator.new { |y| y << "one" }
obj1 = mock("obj1") obj1 = mock("obj1")
obj1.should_receive(:each).once.and_yield("two") obj1.should_receive(:each).once.and_yield("two")
obj2 = mock("obj2") obj2 = mock("obj2")
obj2.should_receive(:each).once.and_yield("three") obj2.should_receive(:each).once.and_yield("three")
chain = enum + obj1 + obj2 chain = enum + obj1 + obj2
chain.each { |item| ScratchPad << item } chain.each { |item| ScratchPad << item }
ScratchPad.recorded.should == ["one", "two", "three"] ScratchPad.recorded.should == ["one", "two", "three"]
end
end end
end end

View file

@ -23,25 +23,13 @@ describe "Enumerator::Yielder#<<" do
end end
context "when multiple arguments passed" do context "when multiple arguments passed" do
ruby_version_is '' ... '2.6' do it "raises an ArgumentError" do
it "yields the arguments list to the block" do ary = []
ary = [] y = Enumerator::Yielder.new { |*x| ary << x }
y = Enumerator::Yielder.new { |*x| ary << x }
-> {
y.<<(1, 2) y.<<(1, 2)
}.should raise_error(ArgumentError, /wrong number of arguments/)
ary.should == [[1, 2]]
end
end
ruby_version_is '2.6' do
it "raises an ArgumentError" do
ary = []
y = Enumerator::Yielder.new { |*x| ary << x }
-> {
y.<<(1, 2)
}.should raise_error(ArgumentError, /wrong number of arguments/)
end
end end
end end
end end

View file

@ -2,14 +2,12 @@ require_relative '../../spec_helper'
require_relative '../enumerable/shared/enumeratorized' require_relative '../enumerable/shared/enumeratorized'
require_relative 'shared/select' require_relative 'shared/select'
ruby_version_is "2.6" do describe "ENV.filter!" do
describe "ENV.filter!" do it_behaves_like :env_select!, :filter!
it_behaves_like :env_select!, :filter! it_behaves_like :enumeratorized_with_origin_size, :filter!, ENV
it_behaves_like :enumeratorized_with_origin_size, :filter!, ENV end
end
describe "ENV.filter" do
describe "ENV.filter" do it_behaves_like :env_select, :filter
it_behaves_like :env_select, :filter it_behaves_like :enumeratorized_with_origin_size, :filter, ENV
it_behaves_like :enumeratorized_with_origin_size, :filter, ENV
end
end end

View file

@ -1,29 +1,27 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.6" do describe "ENV.slice" do
describe "ENV.slice" do before :each do
before :each do @saved_foo = ENV["foo"]
@saved_foo = ENV["foo"] @saved_bar = ENV["bar"]
@saved_bar = ENV["bar"] ENV["foo"] = "0"
ENV["foo"] = "0" ENV["bar"] = "1"
ENV["bar"] = "1" end
end
after :each do after :each do
ENV["foo"] = @saved_foo ENV["foo"] = @saved_foo
ENV["bar"] = @saved_bar ENV["bar"] = @saved_bar
end end
it "returns a hash of the given environment variable names and their values" do it "returns a hash of the given environment variable names and their values" do
ENV.slice("foo", "bar").should == {"foo" => "0", "bar" => "1"} ENV.slice("foo", "bar").should == {"foo" => "0", "bar" => "1"}
end end
it "ignores each String that is not an environment variable name" do it "ignores each String that is not an environment variable name" do
ENV.slice("foo", "boo", "bar").should == {"foo" => "0", "bar" => "1"} ENV.slice("foo", "boo", "bar").should == {"foo" => "0", "bar" => "1"}
end end
it "raises TypeError if any argument is not a String and does not respond to #to_str" do it "raises TypeError if any argument is not a String and does not respond to #to_str" do
-> { ENV.slice(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String") -> { ENV.slice(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
end
end end
end end

View file

@ -4,57 +4,55 @@ require_relative 'shared/to_hash'
describe "ENV.to_h" do describe "ENV.to_h" do
it_behaves_like :env_to_hash, :to_h it_behaves_like :env_to_hash, :to_h
ruby_version_is "2.6" do context "with block" do
context "with block" do before do
before do @orig_hash = ENV.to_hash
@orig_hash = ENV.to_hash end
end
after do after do
ENV.replace @orig_hash ENV.replace @orig_hash
end end
it "converts [key, value] pairs returned by the block to a hash" do it "converts [key, value] pairs returned by the block to a hash" do
ENV.replace("a" => "b", "c" => "d") ENV.replace("a" => "b", "c" => "d")
ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" } ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" }
end end
it "does not require the array elements to be strings" do it "does not require the array elements to be strings" do
ENV.replace("a" => "b", "c" => "d") ENV.replace("a" => "b", "c" => "d")
ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d } ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d }
end end
it "raises ArgumentError if block returns longer or shorter array" do it "raises ArgumentError if block returns longer or shorter array" do
-> do -> do
ENV.to_h { |k, v| [k, v.upcase, 1] } ENV.to_h { |k, v| [k, v.upcase, 1] }
end.should raise_error(ArgumentError, /element has wrong array length/) end.should raise_error(ArgumentError, /element has wrong array length/)
-> do -> do
ENV.to_h { |k, v| [k] } ENV.to_h { |k, v| [k] }
end.should raise_error(ArgumentError, /element has wrong array length/) end.should raise_error(ArgumentError, /element has wrong array length/)
end end
it "raises TypeError if block returns something other than Array" do it "raises TypeError if block returns something other than Array" do
-> do -> do
ENV.to_h { |k, v| "not-array" } ENV.to_h { |k, v| "not-array" }
end.should raise_error(TypeError, /wrong element type String/) end.should raise_error(TypeError, /wrong element type String/)
end end
it "coerces returned pair to Array with #to_ary" do it "coerces returned pair to Array with #to_ary" do
x = mock('x') x = mock('x')
x.stub!(:to_ary).and_return([:b, 'b']) x.stub!(:to_ary).and_return([:b, 'b'])
ENV.to_h { |k| x }.should == { :b => 'b' } ENV.to_h { |k| x }.should == { :b => 'b' }
end end
it "does not coerce returned pair to Array with #to_a" do it "does not coerce returned pair to Array with #to_a" do
x = mock('x') x = mock('x')
x.stub!(:to_a).and_return([:b, 'b']) x.stub!(:to_a).and_return([:b, 'b'])
-> do -> do
ENV.to_h { |k| x } ENV.to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject/) end.should raise_error(TypeError, /wrong element type MockObject/)
end
end end
end end
end end

View file

@ -12,81 +12,77 @@ describe "Exception#full_message" do
full_message.should include "b.rb:2" full_message.should include "b.rb:2"
end end
ruby_version_is "2.5.1" do it "supports :highlight option and adds escape sequences to highlight some strings" do
it "supports :highlight option and adds escape sequences to highlight some strings" do e = RuntimeError.new("Some runtime error")
e = RuntimeError.new("Some runtime error")
full_message = e.full_message(highlight: true, order: :bottom) full_message = e.full_message(highlight: true, order: :bottom)
full_message.should include "\e[1mTraceback\e[m (most recent call last)" full_message.should include "\e[1mTraceback\e[m (most recent call last)"
full_message.should include "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)" full_message.should include "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)"
full_message = e.full_message(highlight: false, order: :bottom) full_message = e.full_message(highlight: false, order: :bottom)
full_message.should include "Traceback (most recent call last)" full_message.should include "Traceback (most recent call last)"
full_message.should include "Some runtime error (RuntimeError)" full_message.should include "Some runtime error (RuntimeError)"
end end
it "supports :order option and places the error message and the backtrace at the top or the bottom" do it "supports :order option and places the error message and the backtrace at the top or the bottom" do
e = RuntimeError.new("Some runtime error") e = RuntimeError.new("Some runtime error")
e.set_backtrace(["a.rb:1", "b.rb:2"]) e.set_backtrace(["a.rb:1", "b.rb:2"])
e.full_message(order: :top, highlight: false).should =~ /a.rb:1.*b.rb:2/m e.full_message(order: :top, highlight: false).should =~ /a.rb:1.*b.rb:2/m
e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m
end end
it "shows the caller if the exception has no backtrace" do it "shows the caller if the exception has no backtrace" do
e = RuntimeError.new("Some runtime error") e = RuntimeError.new("Some runtime error")
e.backtrace.should == nil e.backtrace.should == nil
full_message = e.full_message(highlight: false, order: :top) full_message = e.full_message(highlight: false, order: :top)
full_message.should include("#{__FILE__}:#{__LINE__-1}:in `") full_message.should include("#{__FILE__}:#{__LINE__-1}:in `")
full_message.should include("': Some runtime error (RuntimeError)\n") full_message.should include("': Some runtime error (RuntimeError)\n")
end end
it "shows the exception class at the end of the first line of the message when the message contains multiple lines" do it "shows the exception class at the end of the first line of the message when the message contains multiple lines" do
begin begin
line = __LINE__; raise "first line\nsecond line" line = __LINE__; raise "first line\nsecond line"
rescue => e rescue => e
full_message = e.full_message(highlight: false, order: :top).lines full_message = e.full_message(highlight: false, order: :top).lines
full_message[0].should include("#{__FILE__}:#{line}:in `") full_message[0].should include("#{__FILE__}:#{line}:in `")
full_message[0].should include(": first line (RuntimeError)\n") full_message[0].should include(": first line (RuntimeError)\n")
full_message[1].should == "second line\n" full_message[1].should == "second line\n"
end
end end
end end
ruby_version_is "2.6" do it "contains cause of exception" do
it "contains cause of exception" do begin
begin begin
begin raise 'the cause'
raise 'the cause' rescue
rescue raise 'main exception'
raise 'main exception'
end
rescue => e
exception = e
end end
rescue => e
exception.full_message.should include "main exception" exception = e
exception.full_message.should include "the cause"
end end
it 'contains all the chain of exceptions' do exception.full_message.should include "main exception"
exception.full_message.should include "the cause"
end
it 'contains all the chain of exceptions' do
begin
begin begin
begin begin
begin raise 'origin exception'
raise 'origin exception'
rescue
raise 'intermediate exception'
end
rescue rescue
raise 'last exception' raise 'intermediate exception'
end end
rescue => e rescue
exception = e raise 'last exception'
end end
rescue => e
exception.full_message.should include "last exception" exception = e
exception.full_message.should include "intermediate exception"
exception.full_message.should include "origin exception"
end end
exception.full_message.should include "last exception"
exception.full_message.should include "intermediate exception"
exception.full_message.should include "origin exception"
end end
end end

View file

@ -1,21 +1,19 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
describe "KeyError" do describe "KeyError" do
ruby_version_is "2.6" do it "accepts :receiver and :key options" do
it "accepts :receiver and :key options" do receiver = mock("receiver")
receiver = mock("receiver") key = mock("key")
key = mock("key")
error = KeyError.new(receiver: receiver, key: key) error = KeyError.new(receiver: receiver, key: key)
error.receiver.should == receiver error.receiver.should == receiver
error.key.should == key error.key.should == key
error = KeyError.new("message", receiver: receiver, key: key) error = KeyError.new("message", receiver: receiver, key: key)
error.message.should == "message" error.message.should == "message"
error.receiver.should == receiver error.receiver.should == receiver
error.key.should == key error.key.should == key
end
end end
end end

View file

@ -5,15 +5,13 @@ describe "NameError.new" do
NameError.new("msg","name").name.should == "name" NameError.new("msg","name").name.should == "name"
end end
ruby_version_is "2.6" do it "accepts a :receiver keyword argument" do
it "accepts a :receiver keyword argument" do receiver = mock("receiver")
receiver = mock("receiver")
error = NameError.new("msg", :name, receiver: receiver) error = NameError.new("msg", :name, receiver: receiver)
error.receiver.should == receiver error.receiver.should == receiver
error.name.should == :name error.name.should == :name
end
end end
end end

View file

@ -10,15 +10,13 @@ describe "NoMethodError.new" do
NoMethodError.new("msg").message.should == "msg" NoMethodError.new("msg").message.should == "msg"
end end
ruby_version_is "2.6" do it "accepts a :receiver keyword argument" do
it "accepts a :receiver keyword argument" do receiver = mock("receiver")
receiver = mock("receiver")
error = NoMethodError.new("msg", :name, receiver: receiver) error = NoMethodError.new("msg", :name, receiver: receiver)
error.receiver.should == receiver error.receiver.should == receiver
error.name.should == :name error.name.should == :name
end
end end
end end

View file

@ -30,10 +30,8 @@ describe "SignalException.new" do
-> { SignalException.new("NONEXISTENT") }.should raise_error(ArgumentError) -> { SignalException.new("NONEXISTENT") }.should raise_error(ArgumentError)
end end
ruby_version_is "2.6" do it "raises an exception with an invalid first argument type" do
it "raises an exception with an invalid first argument type" do -> { SignalException.new(Object.new) }.should raise_error(ArgumentError)
-> { SignalException.new(Object.new) }.should raise_error(ArgumentError)
end
end end
it "takes a signal symbol without SIG prefix as the first argument" do it "takes a signal symbol without SIG prefix as the first argument" do

View file

@ -5,29 +5,27 @@ describe "An Exception reaching the top level" do
ruby_exe('raise "foo"', args: "2>&1", exit_status: 1).should.include?("in `<main>': foo (RuntimeError)") ruby_exe('raise "foo"', args: "2>&1", exit_status: 1).should.include?("in `<main>': foo (RuntimeError)")
end end
ruby_version_is "2.6" do it "the Exception#cause is printed to STDERR with backtraces" do
it "the Exception#cause is printed to STDERR with backtraces" do code = <<-RUBY
code = <<-RUBY def raise_cause
def raise_cause raise "the cause"
raise "the cause"
end
def raise_wrapped
raise "wrapped"
end
begin
raise_cause
rescue
raise_wrapped
end
RUBY
lines = ruby_exe(code, args: "2>&1", exit_status: 1).lines
lines.reject! { |l| l.include?('rescue in') }
lines.map! { |l| l.chomp[/:(in.+)/, 1] }
lines.should == ["in `raise_wrapped': wrapped (RuntimeError)",
"in `<main>'",
"in `raise_cause': the cause (RuntimeError)",
"in `<main>'"]
end end
def raise_wrapped
raise "wrapped"
end
begin
raise_cause
rescue
raise_wrapped
end
RUBY
lines = ruby_exe(code, args: "2>&1", exit_status: 1).lines
lines.reject! { |l| l.include?('rescue in') }
lines.map! { |l| l.chomp[/:(in.+)/, 1] }
lines.should == ["in `raise_wrapped': wrapped (RuntimeError)",
"in `<main>'",
"in `raise_cause': the cause (RuntimeError)",
"in `<main>'"]
end end
describe "with a custom backtrace" do describe "with a custom backtrace" do

View file

@ -629,31 +629,29 @@ describe "File.open" do
}.should raise_error(ArgumentError, "newline decorator with binary mode") }.should raise_error(ArgumentError, "newline decorator with binary mode")
end end
ruby_version_is "2.6" do context "'x' flag" do
context "'x' flag" do before :each do
before :each do @xfile = tmp("x-flag")
@xfile = tmp("x-flag") rm_r @xfile
rm_r @xfile end
end
after :each do after :each do
rm_r @xfile rm_r @xfile
end end
it "does nothing if the file doesn't exist" do it "does nothing if the file doesn't exist" do
File.open(@xfile, "wx") { |f| f.write("content") } File.open(@xfile, "wx") { |f| f.write("content") }
File.read(@xfile).should == "content" File.read(@xfile).should == "content"
end end
it "throws a Errno::EEXIST error if the file exists" do it "throws a Errno::EEXIST error if the file exists" do
touch @xfile touch @xfile
-> { File.open(@xfile, "wx") }.should raise_error(Errno::EEXIST) -> { File.open(@xfile, "wx") }.should raise_error(Errno::EEXIST)
end end
it "can't be used with 'r' and 'a' flags" do it "can't be used with 'r' and 'a' flags" do
-> { File.open(@xfile, "rx") }.should raise_error(ArgumentError, 'invalid access mode rx') -> { File.open(@xfile, "rx") }.should raise_error(ArgumentError, 'invalid access mode rx')
-> { File.open(@xfile, "ax") }.should raise_error(ArgumentError, 'invalid access mode ax') -> { File.open(@xfile, "ax") }.should raise_error(ArgumentError, 'invalid access mode ax')
end
end end
end end
end end

View file

@ -63,4 +63,28 @@ describe "Float#<=>" do
it "returns 1 when self is negative and other is -Infinity" do it "returns 1 when self is negative and other is -Infinity" do
(-Float::MAX.to_i*2 <=> -infinity_value).should == 1 (-Float::MAX.to_i*2 <=> -infinity_value).should == 1
end end
it "returns 0 when self is Infinity and other other is infinite?=1" do
obj = Object.new
def obj.infinite?
1
end
(infinity_value <=> obj).should == 0
end
it "returns 1 when self is Infinity and other is infinite?=-1" do
obj = Object.new
def obj.infinite?
-1
end
(infinity_value <=> obj).should == 1
end
it "returns 1 when self is Infinity and other is infinite?=nil (which means finite)" do
obj = Object.new
def obj.infinite?
nil
end
(infinity_value <=> obj).should == 1
end
end end

View file

@ -1,12 +1,10 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'shared/select' require_relative 'shared/select'
ruby_version_is "2.6" do describe "Hash#filter" do
describe "Hash#filter" do it_behaves_like :hash_select, :filter
it_behaves_like :hash_select, :filter end
end
describe "Hash#filter!" do
describe "Hash#filter!" do it_behaves_like :hash_select!, :filter!
it_behaves_like :hash_select!, :filter!
end
end end

View file

@ -81,19 +81,17 @@ describe "Hash#merge" do
merge_pairs.should == expected_pairs merge_pairs.should == expected_pairs
end end
ruby_version_is "2.6" do it "accepts multiple hashes" do
it "accepts multiple hashes" do result = { a: 1 }.merge({ b: 2 }, { c: 3 }, { d: 4 })
result = { a: 1 }.merge({ b: 2 }, { c: 3 }, { d: 4 }) result.should == { a: 1, b: 2, c: 3, d: 4 }
result.should == { a: 1, b: 2, c: 3, d: 4 } end
end
it "accepts zero arguments and returns a copy of self" do it "accepts zero arguments and returns a copy of self" do
hash = { a: 1 } hash = { a: 1 }
merged = hash.merge merged = hash.merge
merged.should eql(hash) merged.should eql(hash)
merged.should_not equal(hash) merged.should_not equal(hash)
end
end end
end end

View file

@ -64,15 +64,13 @@ describe :hash_update, shared: true do
hash.should == {1 => :foo, 3 => :bar, 5 => 6} hash.should == {1 => :foo, 3 => :bar, 5 => 6}
end end
ruby_version_is "2.6" do it "accepts multiple hashes" do
it "accepts multiple hashes" do result = { a: 1 }.send(@method, { b: 2 }, { c: 3 }, { d: 4 })
result = { a: 1 }.send(@method, { b: 2 }, { c: 3 }, { d: 4 }) result.should == { a: 1, b: 2, c: 3, d: 4 }
result.should == { a: 1, b: 2, c: 3, d: 4 } end
end
it "accepts zero arguments" do it "accepts zero arguments" do
hash = { a: 1 } hash = { a: 1 }
hash.send(@method).should eql(hash) hash.send(@method).should eql(hash)
end
end end
end end

View file

@ -32,43 +32,41 @@ describe "Hash#to_h" do
end end
end end
ruby_version_is "2.6" do context "with block" do
context "with block" do it "converts [key, value] pairs returned by the block to a hash" do
it "converts [key, value] pairs returned by the block to a hash" do { a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v]}.should == { "a" => 1, "b" => 4 }
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v]}.should == { "a" => 1, "b" => 4 } end
end
it "raises ArgumentError if block returns longer or shorter array" do it "raises ArgumentError if block returns longer or shorter array" do
-> do -> do
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v, 1] } { a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v, 1] }
end.should raise_error(ArgumentError, /element has wrong array length/) end.should raise_error(ArgumentError, /element has wrong array length/)
-> do -> do
{ a: 1, b: 2 }.to_h { |k, v| [k] } { a: 1, b: 2 }.to_h { |k, v| [k] }
end.should raise_error(ArgumentError, /element has wrong array length/) end.should raise_error(ArgumentError, /element has wrong array length/)
end end
it "raises TypeError if block returns something other than Array" do it "raises TypeError if block returns something other than Array" do
-> do -> do
{ a: 1, b: 2 }.to_h { |k, v| "not-array" } { a: 1, b: 2 }.to_h { |k, v| "not-array" }
end.should raise_error(TypeError, /wrong element type String/) end.should raise_error(TypeError, /wrong element type String/)
end end
it "coerces returned pair to Array with #to_ary" do it "coerces returned pair to Array with #to_ary" do
x = mock('x') x = mock('x')
x.stub!(:to_ary).and_return([:b, 'b']) x.stub!(:to_ary).and_return([:b, 'b'])
{ a: 1 }.to_h { |k| x }.should == { :b => 'b' } { a: 1 }.to_h { |k| x }.should == { :b => 'b' }
end end
it "does not coerce returned pair to Array with #to_a" do it "does not coerce returned pair to Array with #to_a" do
x = mock('x') x = mock('x')
x.stub!(:to_a).and_return([:b, 'b']) x.stub!(:to_a).and_return([:b, 'b'])
-> do -> do
{ a: 1 }.to_h { |k| x } { a: 1 }.to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject/) end.should raise_error(TypeError, /wrong element type MockObject/)
end
end end
end end
end end

View file

@ -60,31 +60,12 @@ describe "Hash#transform_keys!" do
end end
# https://bugs.ruby-lang.org/issues/14380 # https://bugs.ruby-lang.org/issues/14380
ruby_version_is ""..."2.5.1" do it "prevents conflicts between new keys and old ones" do
it "does not prevent conflicts between new keys and old ones" do @hash.transform_keys!(&:succ)
@hash.transform_keys!(&:succ) @hash.should == { b: 1, c: 2, d: 3, e: 4 }
@hash.should == { e: 1 }
end
end end
ruby_version_is "2.5.1" do ruby_version_is ""..."3.0.2" do # https://bugs.ruby-lang.org/issues/17735
it "prevents conflicts between new keys and old ones" do
@hash.transform_keys!(&:succ)
@hash.should == { b: 1, c: 2, d: 3, e: 4 }
end
end
ruby_version_is ""..."2.5.1" do
it "partially modifies the contents if we broke from the block" do
@hash.transform_keys! do |v|
break if v == :c
v.succ
end
@hash.should == { c: 1, d: 4 }
end
end
ruby_version_is "2.5.1"..."3.0.2" do # https://bugs.ruby-lang.org/issues/17735
it "returns the processed keys if we broke from the block" do it "returns the processed keys if we broke from the block" do
@hash.transform_keys! do |v| @hash.transform_keys! do |v|
break if v == :c break if v == :c

View file

@ -67,5 +67,11 @@ describe "IO#set_encoding_by_bom" do
-> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already') -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already')
end end
it 'returns exception if encoding conversion is already set' do
@io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE)
-> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding conversion is set')
end
end end
end end

View file

@ -36,20 +36,7 @@ describe "IO#ungetbyte" do
@io.getbyte.should == 97 @io.getbyte.should == 97
end end
ruby_version_is ''...'2.6' do ruby_version_is ''...'2.6.1' do
it "puts back one byte for an Integer argument..." do
@io.ungetbyte(4095).should be_nil
@io.getbyte.should == 255
end
it "... but not for Integer argument (eh?)" do
-> {
@io.ungetbyte(0x4f7574206f6620636861722072616e6765)
}.should raise_error(TypeError)
end
end
ruby_version_is '2.6'...'2.6.1' do
it "is an RangeError if the integer is not in 8bit" do it "is an RangeError if the integer is not in 8bit" do
for i in [4095, 0x4f7574206f6620636861722072616e6765] do for i in [4095, 0x4f7574206f6620636861722072616e6765] do
-> { @io.ungetbyte(i) }.should raise_error(RangeError) -> { @io.ungetbyte(i) }.should raise_error(RangeError)

View file

@ -139,48 +139,46 @@ describe "Kernel.Complex()" do
end end
end end
ruby_version_is "2.6" do describe "when passed exception: false" do
describe "when passed exception: false" do describe "and [Numeric]" do
describe "and [Numeric]" do it "returns a complex number" do
it "returns a complex number" do Complex("123", exception: false).should == Complex(123)
Complex("123", exception: false).should == Complex(123)
end
end end
end
describe "and [non-Numeric]" do describe "and [non-Numeric]" do
it "swallows an error" do it "swallows an error" do
Complex(:sym, exception: false).should == nil Complex(:sym, exception: false).should == nil
end
end end
end
describe "and [non-Numeric, Numeric] argument" do describe "and [non-Numeric, Numeric] argument" do
it "throws a TypeError" do it "throws a TypeError" do
-> { Complex(:sym, 0, exception: false) }.should raise_error(TypeError, "not a real") -> { Complex(:sym, 0, exception: false) }.should raise_error(TypeError, "not a real")
end
end end
end
describe "and [anything, non-Numeric] argument" do describe "and [anything, non-Numeric] argument" do
it "swallows an error" do it "swallows an error" do
Complex("a", :sym, exception: false).should == nil Complex("a", :sym, exception: false).should == nil
Complex(:sym, :sym, exception: false).should == nil Complex(:sym, :sym, exception: false).should == nil
Complex(0, :sym, exception: false).should == nil Complex(0, :sym, exception: false).should == nil
end
end end
end
describe "and non-numeric String arguments" do describe "and non-numeric String arguments" do
it "swallows an error" do it "swallows an error" do
Complex("a", "b", exception: false).should == nil Complex("a", "b", exception: false).should == nil
Complex("a", 0, exception: false).should == nil Complex("a", 0, exception: false).should == nil
Complex(0, "b", exception: false).should == nil Complex(0, "b", exception: false).should == nil
end
end end
end
describe "and nil arguments" do describe "and nil arguments" do
it "swallows an error" do it "swallows an error" do
Complex(nil, exception: false).should == nil Complex(nil, exception: false).should == nil
Complex(0, nil, exception: false).should == nil Complex(0, nil, exception: false).should == nil
Complex(nil, 0, exception: false).should == nil Complex(nil, 0, exception: false).should == nil
end
end end
end end
end end

View file

@ -306,27 +306,25 @@ describe :kernel_float, shared: true do
-> { @object.send(:Float, c) }.should raise_error(RangeError) -> { @object.send(:Float, c) }.should raise_error(RangeError)
end end
ruby_version_is "2.6" do describe "when passed exception: false" do
describe "when passed exception: false" do describe "and valid input" do
describe "and valid input" do it "returns a Float number" do
it "returns a Float number" do @object.send(:Float, 1, exception: false).should == 1.0
@object.send(:Float, 1, exception: false).should == 1.0 @object.send(:Float, "1", exception: false).should == 1.0
@object.send(:Float, "1", exception: false).should == 1.0 @object.send(:Float, "1.23", exception: false).should == 1.23
@object.send(:Float, "1.23", exception: false).should == 1.23
end
end end
end
describe "and invalid input" do describe "and invalid input" do
it "swallows an error" do it "swallows an error" do
@object.send(:Float, "abc", exception: false).should == nil @object.send(:Float, "abc", exception: false).should == nil
@object.send(:Float, :sym, exception: false).should == nil @object.send(:Float, :sym, exception: false).should == nil
end
end end
end
describe "and nil" do describe "and nil" do
it "swallows it" do it "swallows it" do
@object.send(:Float, nil, exception: false).should == nil @object.send(:Float, nil, exception: false).should == nil
end
end end
end end
end end

View file

@ -10,29 +10,18 @@ describe :kernel_integer, shared: true do
Integer(100).should == 100 Integer(100).should == 100
end end
ruby_version_is ""..."2.6" do it "raises a TypeError when to_int returns not-an-Integer object and to_i returns nil" do
it "uncritically return the value of to_int even if it is not an Integer" do obj = mock("object")
obj = mock("object") obj.should_receive(:to_int).and_return("1")
obj.should_receive(:to_int).and_return("1") obj.should_receive(:to_i).and_return(nil)
obj.should_not_receive(:to_i) -> { Integer(obj) }.should raise_error(TypeError)
Integer(obj).should == "1"
end
end end
ruby_version_is "2.6" do it "return a result of to_i when to_int does not return an Integer" do
it "raises a TypeError when to_int returns not-an-Integer object and to_i returns nil" do obj = mock("object")
obj = mock("object") obj.should_receive(:to_int).and_return("1")
obj.should_receive(:to_int).and_return("1") obj.should_receive(:to_i).and_return(42)
obj.should_receive(:to_i).and_return(nil) Integer(obj).should == 42
-> { Integer(obj) }.should raise_error(TypeError)
end
it "return a result of to_i when to_int does not return an Integer" do
obj = mock("object")
obj.should_receive(:to_int).and_return("1")
obj.should_receive(:to_i).and_return(42)
Integer(obj).should == 42
end
end end
it "raises a TypeError when passed nil" do it "raises a TypeError when passed nil" do
@ -100,59 +89,57 @@ describe :kernel_integer, shared: true do
-> { Integer(infinity_value) }.should raise_error(FloatDomainError) -> { Integer(infinity_value) }.should raise_error(FloatDomainError)
end end
ruby_version_is "2.6" do describe "when passed exception: false" do
describe "when passed exception: false" do describe "and to_i returns a value that is not an Integer" do
describe "and to_i returns a value that is not an Integer" do it "swallows an error" do
it "swallows an error" do obj = mock("object")
obj = mock("object") obj.should_receive(:to_i).and_return("1")
obj.should_receive(:to_i).and_return("1") Integer(obj, exception: false).should == nil
Integer(obj, exception: false).should == nil
end
end end
end
describe "and no to_int or to_i methods exist" do describe "and no to_int or to_i methods exist" do
it "swallows an error" do it "swallows an error" do
obj = mock("object") obj = mock("object")
Integer(obj, exception: false).should == nil Integer(obj, exception: false).should == nil
end
end end
end
describe "and to_int returns nil and no to_i exists" do describe "and to_int returns nil and no to_i exists" do
it "swallows an error" do it "swallows an error" do
obj = mock("object") obj = mock("object")
obj.should_receive(:to_i).and_return(nil) obj.should_receive(:to_i).and_return(nil)
Integer(obj, exception: false).should == nil Integer(obj, exception: false).should == nil
end
end end
end
describe "and passed NaN" do describe "and passed NaN" do
it "swallows an error" do it "swallows an error" do
Integer(nan_value, exception: false).should == nil Integer(nan_value, exception: false).should == nil
end
end end
end
describe "and passed Infinity" do describe "and passed Infinity" do
it "swallows an error" do it "swallows an error" do
Integer(infinity_value, exception: false).should == nil Integer(infinity_value, exception: false).should == nil
end
end end
end
describe "and passed nil" do describe "and passed nil" do
it "swallows an error" do it "swallows an error" do
Integer(nil, exception: false).should == nil Integer(nil, exception: false).should == nil
end
end end
end
describe "and passed a String that contains numbers" do describe "and passed a String that contains numbers" do
it "normally parses it and returns an Integer" do it "normally parses it and returns an Integer" do
Integer("42", exception: false).should == 42 Integer("42", exception: false).should == 42
end
end end
end
describe "and passed a String that can't be converted to an Integer" do describe "and passed a String that can't be converted to an Integer" do
it "swallows an error" do it "swallows an error" do
Integer("abc", exception: false).should == nil Integer("abc", exception: false).should == nil
end
end end
end end
end end
@ -246,30 +233,28 @@ describe "Integer() given a String", shared: true do
-> { Integer("") }.should raise_error(ArgumentError) -> { Integer("") }.should raise_error(ArgumentError)
end end
ruby_version_is "2.6" do describe "when passed exception: false" do
describe "when passed exception: false" do describe "and multiple leading -s" do
describe "and multiple leading -s" do it "swallows an error" do
it "swallows an error" do Integer("---1", exception: false).should == nil
Integer("---1", exception: false).should == nil
end
end end
end
describe "and multiple trailing -s" do describe "and multiple trailing -s" do
it "swallows an error" do it "swallows an error" do
Integer("1---", exception: false).should == nil Integer("1---", exception: false).should == nil
end
end end
end
describe "and an argument that contains a period" do describe "and an argument that contains a period" do
it "swallows an error" do it "swallows an error" do
Integer("0.0", exception: false).should == nil Integer("0.0", exception: false).should == nil
end
end end
end
describe "and an empty string" do describe "and an empty string" do
it "swallows an error" do it "swallows an error" do
Integer("", exception: false).should == nil Integer("", exception: false).should == nil
end
end end
end end
end end
@ -594,20 +579,18 @@ describe "Integer() given a String and base", shared: true do
end end
end end
ruby_version_is "2.6" do describe "when passed exception: false" do
describe "when passed exception: false" do describe "and valid argument" do
describe "and valid argument" do it "returns an Integer number" do
it "returns an Integer number" do Integer("100", 10, exception: false).should == 100
Integer("100", 10, exception: false).should == 100 Integer("100", 2, exception: false).should == 4
Integer("100", 2, exception: false).should == 4
end
end end
end
describe "and invalid argument" do describe "and invalid argument" do
it "swallows an error" do it "swallows an error" do
Integer("999", 2, exception: false).should == nil Integer("999", 2, exception: false).should == nil
Integer("abc", 10, exception: false).should == nil Integer("abc", 10, exception: false).should == nil
end
end end
end end
end end

View file

@ -56,6 +56,21 @@ describe "Kernel#autoload" do
end end
end end
describe "inside a Class.new method body" do
# NOTE: this spec is being discussed in https://github.com/ruby/spec/pull/839
it "should define on the new anonymous class" do
cls = Class.new do
def go
autoload :Object, 'bogus'
autoload? :Object
end
end
cls.new.go.should == 'bogus'
cls.autoload?(:Object).should == 'bogus'
end
end
describe "when Object is frozen" do describe "when Object is frozen" do
it "raises a FrozenError before defining the constant" do it "raises a FrozenError before defining the constant" do
ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "FrozenError - nil" ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "FrozenError - nil"

View file

@ -28,12 +28,10 @@ describe 'Kernel#caller_locations' do
locations1[2..4].map(&:to_s).should == locations2.map(&:to_s) locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
end end
ruby_version_is "2.6" do it "works with endless ranges" do
it "works with endless ranges" do locations1 = caller_locations(0)
locations1 = caller_locations(0) locations2 = caller_locations(eval("(2..)"))
locations2 = caller_locations(eval("(2..)")) locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -44,12 +44,10 @@ describe 'Kernel#caller' do
] ]
end end
ruby_version_is "2.6" do it "works with endless ranges" do
it "works with endless ranges" do locations1 = KernelSpecs::CallerTest.locations(0)
locations1 = KernelSpecs::CallerTest.locations(0) locations2 = KernelSpecs::CallerTest.locations(eval("(2..)"))
locations2 = KernelSpecs::CallerTest.locations(eval("(2..)")) locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -14,11 +14,9 @@ describe "Kernel#=~" do
end end
end end
ruby_version_is "2.6" do it "is deprecated" do
it "is deprecated" do -> do
-> do Object.new =~ /regexp/
Object.new =~ /regexp/ end.should complain(/deprecated Object#=~ is called on Object/, verbose: true)
end.should complain(/deprecated Object#=~ is called on Object/, verbose: true)
end
end end
end end

View file

@ -2,7 +2,6 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
describe "Kernel#open" do describe "Kernel#open" do
before :each do before :each do
@name = tmp("kernel_open.txt") @name = tmp("kernel_open.txt")
@content = "This is a test" @content = "This is a test"
@ -137,6 +136,18 @@ describe "Kernel#open" do
it "accepts nil for mode and permission" do it "accepts nil for mode and permission" do
open(@name, nil, nil) { |f| f.gets }.should == @content open(@name, nil, nil) { |f| f.gets }.should == @content
end end
ruby_version_is ""..."3.0" do
it "works correctly when redefined by open-uri" do
code = <<~RUBY
require 'open-uri'
obj = Object.new
def obj.to_open; self; end
p open(obj) == obj
RUBY
ruby_exe(code, args: "2>&1").should == "true\n"
end
end
end end
describe "Kernel.open" do describe "Kernel.open" do

View file

@ -28,25 +28,23 @@ describe "Kernel#raise" do
ScratchPad.recorded.should be_nil ScratchPad.recorded.should be_nil
end end
ruby_version_is "2.6" do it "accepts a cause keyword argument that sets the cause" do
it "accepts a cause keyword argument that sets the cause" do cause = StandardError.new
-> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause }
end
it "accepts a cause keyword argument that overrides the last exception" do
begin
raise "first raise"
rescue => ignored
cause = StandardError.new cause = StandardError.new
-> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause } -> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause }
end end
end
it "accepts a cause keyword argument that overrides the last exception" do it "raises an ArgumentError when only cause is given" do
begin cause = StandardError.new
raise "first raise" -> { raise(cause: cause) }.should raise_error(ArgumentError)
rescue => ignored
cause = StandardError.new
-> { raise("error", cause: cause) }.should raise_error(RuntimeError) { |e| e.cause.should == cause }
end
end
it "raises an ArgumentError when only cause is given" do
cause = StandardError.new
-> { raise(cause: cause) }.should raise_error(ArgumentError)
end
end end
end end

View file

@ -25,14 +25,12 @@ describe :kernel_system, shared: true do
$?.exitstatus.should == 1 $?.exitstatus.should == 1
end end
ruby_version_is "2.6" do it "raises RuntimeError when `exception: true` is given and the command exits with a non-zero exit status" do
it "raises RuntimeError when `exception: true` is given and the command exits with a non-zero exit status" do -> { @object.system(ruby_cmd('exit 1'), exception: true) }.should raise_error(RuntimeError)
-> { @object.system(ruby_cmd('exit 1'), exception: true) }.should raise_error(RuntimeError) end
end
it "raises Errno::ENOENT when `exception: true` is given and the specified command does not exist" do it "raises Errno::ENOENT when `exception: true` is given and the specified command does not exist" do
-> { @object.system('feature_14386', exception: true) }.should raise_error(Errno::ENOENT) -> { @object.system('feature_14386', exception: true) }.should raise_error(Errno::ENOENT)
end
end end
it "returns nil when command execution fails" do it "returns nil when command execution fails" do

View file

@ -1,8 +1,6 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'shared/then' require_relative 'shared/then'
ruby_version_is "2.6" do describe "Kernel#then" do
describe "Kernel#then" do it_behaves_like :kernel_then, :then
it_behaves_like :kernel_then, :then
end
end end

View file

@ -107,11 +107,9 @@ describe "Kernel#warn" do
ruby_exe(file, options: "--disable-gems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n" ruby_exe(file, options: "--disable-gems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n"
end end
ruby_version_is "2.6" do it "shows the caller of #require and not #require itself with RubyGems loaded" do
it "shows the caller of #require and not #require itself with RubyGems loaded" do file = fixture(__FILE__ , "warn_require_caller.rb")
file = fixture(__FILE__ , "warn_require_caller.rb") ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n"
ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n"
end
end end
guard -> { Kernel.instance_method(:tap).source_location } do guard -> { Kernel.instance_method(:tap).source_location } do

View file

@ -78,6 +78,20 @@ describe "Marshal.dump" do
s = "\u2192".force_encoding("binary").to_sym s = "\u2192".force_encoding("binary").to_sym
Marshal.dump(s).should == "\x04\b:\b\xE2\x86\x92" Marshal.dump(s).should == "\x04\b:\b\xE2\x86\x92"
end end
it "dumps multiple Symbols sharing the same encoding" do
# Note that the encoding is a link for the second Symbol
symbol1 = "I:\t\xE2\x82\xACa\x06:\x06ET"
symbol2 = "I:\t\xE2\x82\xACb\x06;\x06T"
value = [
"€a".force_encoding(Encoding::UTF_8).to_sym,
"€b".force_encoding(Encoding::UTF_8).to_sym
]
Marshal.dump(value).should == "\x04\b[\a#{symbol1}#{symbol2}"
value = [*value, value[0]]
Marshal.dump(value).should == "\x04\b[\b#{symbol1}#{symbol2};\x00"
end
end end
describe "with an object responding to #marshal_dump" do describe "with an object responding to #marshal_dump" do
@ -343,8 +357,13 @@ describe "Marshal.dump" do
end end
it "dumps an extended Struct" do it "dumps an extended Struct" do
st = Struct.new("Extended", :a, :b).new obj = Struct.new("Extended", :a, :b).new.extend(Meths)
Marshal.dump(st.extend(Meths)).should == "\004\be:\nMethsS:\025Struct::Extended\a:\006a0:\006b0" Marshal.dump(obj).should == "\004\be:\nMethsS:\025Struct::Extended\a:\006a0:\006b0"
s = 'hi'
obj.a = [:a, s]
obj.b = [:Meths, s]
Marshal.dump(obj).should == "\004\be:\nMethsS:\025Struct::Extended\a:\006a[\a;\a\"\ahi:\006b[\a;\000@\a"
Struct.send(:remove_const, :Extended) Struct.send(:remove_const, :Extended)
end end
end end

View file

@ -83,7 +83,7 @@ class UserPreviouslyDefinedWithInitializedIvar
end end
class UserMarshal class UserMarshal
attr_reader :data attr_accessor :data
def initialize def initialize
@data = 'stuff' @data = 'stuff'

View file

@ -309,7 +309,8 @@ describe :marshal_load, shared: true do
it "loads an extended Array object containing a user-marshaled object" do it "loads an extended Array object containing a user-marshaled object" do
obj = [UserMarshal.new, UserMarshal.new].extend(Meths) obj = [UserMarshal.new, UserMarshal.new].extend(Meths)
new_obj = Marshal.send(@method, "\x04\be:\nMeths[\ao:\x10UserMarshal\x06:\n@dataI\"\nstuff\x06:\x06ETo;\x06\x06;\aI\"\nstuff\x06;\bT") dump = "\x04\be:\nMeths[\ao:\x10UserMarshal\x06:\n@dataI\"\nstuff\x06:\x06ETo;\x06\x06;\aI\"\nstuff\x06;\bT"
new_obj = Marshal.send(@method, dump)
new_obj.should == obj new_obj.should == obj
obj_ancestors = class << obj; ancestors[1..-1]; end obj_ancestors = class << obj; ancestors[1..-1]; end
@ -399,6 +400,24 @@ describe :marshal_load, shared: true do
sym.should == s sym.should == s
sym.encoding.should == Encoding::BINARY sym.encoding.should == Encoding::BINARY
end end
it "loads multiple Symbols sharing the same encoding" do
# Note that the encoding is a link for the second Symbol
symbol1 = "I:\t\xE2\x82\xACa\x06:\x06ET"
symbol2 = "I:\t\xE2\x82\xACb\x06;\x06T"
dump = "\x04\b[\a#{symbol1}#{symbol2}"
value = Marshal.send(@method, dump)
value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8]
expected = [
"€a".force_encoding(Encoding::UTF_8).to_sym,
"€b".force_encoding(Encoding::UTF_8).to_sym
]
value.should == expected
value = Marshal.send(@method, "\x04\b[\b#{symbol1}#{symbol2};\x00")
value.map(&:encoding).should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8]
value.should == [*expected, expected[0]]
end
end end
describe "for a String" do describe "for a String" do
@ -460,20 +479,23 @@ describe :marshal_load, shared: true do
describe "for a Struct" do describe "for a Struct" do
it "loads a extended_struct having fields with same objects" do it "loads a extended_struct having fields with same objects" do
s = 'hi' s = 'hi'
obj = Struct.new("Ure2", :a, :b).new.extend(Meths) obj = Struct.new("Extended", :a, :b).new.extend(Meths)
dump = "\004\be:\nMethsS:\025Struct::Extended\a:\006a0:\006b0"
Marshal.send(@method, dump).should == obj
obj.a = [:a, s] obj.a = [:a, s]
obj.b = [:Meths, s] obj.b = [:Meths, s]
dump = "\004\be:\nMethsS:\025Struct::Extended\a:\006a[\a;\a\"\ahi:\006b[\a;\000@\a"
Marshal.send(@method, Marshal.send(@method, dump).should == obj
"\004\be:\nMethsS:\021Struct::Ure2\a:\006a[\a;\a\"\ahi:\006b[\a;\000@\a" Struct.send(:remove_const, :Extended)
).should == obj
Struct.send(:remove_const, :Ure2)
end end
it "loads a struct having ivar" do it "loads a struct having ivar" do
obj = Struct.new("Thick").new obj = Struct.new("Thick").new
obj.instance_variable_set(:@foo, 5) obj.instance_variable_set(:@foo, 5)
Marshal.send(@method, "\004\bIS:\022Struct::Thick\000\006:\t@fooi\n").should == obj reloaded = Marshal.send(@method, "\004\bIS:\022Struct::Thick\000\006:\t@fooi\n")
reloaded.should == obj
reloaded.instance_variable_get(:@foo).should == 5
Struct.send(:remove_const, :Thick) Struct.send(:remove_const, :Thick)
end end
@ -588,6 +610,18 @@ describe :marshal_load, shared: true do
end end
end end
describe "for an object responding to #marshal_dump and #marshal_load" do
it "loads a user-marshaled object" do
obj = UserMarshal.new
obj.data = :data
value = [obj, :data]
dump = Marshal.dump(value)
dump.should == "\x04\b[\aU:\x10UserMarshal:\tdata;\x06"
reloaded = Marshal.load(dump)
reloaded.should == value
end
end
describe "for a user object" do describe "for a user object" do
it "loads a user-marshaled extended object" do it "loads a user-marshaled extended object" do
obj = UserMarshal.new.extend(Meths) obj = UserMarshal.new.extend(Meths)

View file

@ -2,101 +2,99 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
require_relative '../proc/shared/compose' require_relative '../proc/shared/compose'
ruby_version_is "2.6" do describe "Method#<<" do
describe "Method#<<" do it "returns a Proc that is the composition of self and the passed Proc" do
it "returns a Proc that is the composition of self and the passed Proc" do succ = MethodSpecs::Composition.new.method(:succ)
succ = MethodSpecs::Composition.new.method(:succ) upcase = proc { |s| s.upcase }
upcase = proc { |s| s.upcase }
(succ << upcase).call('Ruby').should == "RUBZ" (succ << upcase).call('Ruby').should == "RUBZ"
end
it "calls passed Proc with arguments and then calls self with result" do
pow_2_proc = proc { |x| x * x }
double_proc = proc { |x| x + x }
pow_2_method = MethodSpecs::Composition.new.method(:pow_2)
double_method = MethodSpecs::Composition.new.method(:double)
(pow_2_method << double_proc).call(2).should == 16
(double_method << pow_2_proc).call(2).should == 8
end
it "accepts any callable object" do
inc = MethodSpecs::Composition.new.method(:inc)
double = Object.new
def double.call(n); n * 2; end
(inc << double).call(3).should == 7
end
it_behaves_like :proc_compose, :<<, -> { MethodSpecs::Composition.new.method(:upcase) }
describe "composition" do
it "is a lambda" do
pow_2 = MethodSpecs::Composition.new.method(:pow_2)
double = proc { |x| x + x }
(pow_2 << double).is_a?(Proc).should == true
ruby_version_is(''...'3.0') { (pow_2 << double).should.lambda? }
ruby_version_is('3.0') { (pow_2 << double).should_not.lambda? }
end
it "may accept multiple arguments" do
inc = MethodSpecs::Composition.new.method(:inc)
mul = proc { |n, m| n * m }
(inc << mul).call(2, 3).should == 7
end
end
end end
describe "Method#>>" do it "calls passed Proc with arguments and then calls self with result" do
it "returns a Proc that is the composition of self and the passed Proc" do pow_2_proc = proc { |x| x * x }
upcase = proc { |s| s.upcase } double_proc = proc { |x| x + x }
succ = MethodSpecs::Composition.new.method(:succ)
(succ >> upcase).call('Ruby').should == "RUBZ" pow_2_method = MethodSpecs::Composition.new.method(:pow_2)
double_method = MethodSpecs::Composition.new.method(:double)
(pow_2_method << double_proc).call(2).should == 16
(double_method << pow_2_proc).call(2).should == 8
end
it "accepts any callable object" do
inc = MethodSpecs::Composition.new.method(:inc)
double = Object.new
def double.call(n); n * 2; end
(inc << double).call(3).should == 7
end
it_behaves_like :proc_compose, :<<, -> { MethodSpecs::Composition.new.method(:upcase) }
describe "composition" do
it "is a lambda" do
pow_2 = MethodSpecs::Composition.new.method(:pow_2)
double = proc { |x| x + x }
(pow_2 << double).is_a?(Proc).should == true
ruby_version_is(''...'3.0') { (pow_2 << double).should.lambda? }
ruby_version_is('3.0') { (pow_2 << double).should_not.lambda? }
end end
it "calls passed Proc with arguments and then calls self with result" do it "may accept multiple arguments" do
pow_2_proc = proc { |x| x * x }
double_proc = proc { |x| x + x }
pow_2_method = MethodSpecs::Composition.new.method(:pow_2)
double_method = MethodSpecs::Composition.new.method(:double)
(pow_2_method >> double_proc).call(2).should == 8
(double_method >> pow_2_proc).call(2).should == 16
end
it "accepts any callable object" do
inc = MethodSpecs::Composition.new.method(:inc) inc = MethodSpecs::Composition.new.method(:inc)
mul = proc { |n, m| n * m }
double = Object.new (inc << mul).call(2, 3).should == 7
def double.call(n); n * 2; end end
end
(inc >> double).call(3).should == 8 end
end
describe "Method#>>" do
it_behaves_like :proc_compose, :>>, -> { MethodSpecs::Composition.new.method(:upcase) } it "returns a Proc that is the composition of self and the passed Proc" do
upcase = proc { |s| s.upcase }
describe "composition" do succ = MethodSpecs::Composition.new.method(:succ)
it "is a lambda" do
pow_2 = MethodSpecs::Composition.new.method(:pow_2) (succ >> upcase).call('Ruby').should == "RUBZ"
double = proc { |x| x + x } end
(pow_2 >> double).is_a?(Proc).should == true it "calls passed Proc with arguments and then calls self with result" do
(pow_2 >> double).should.lambda? pow_2_proc = proc { |x| x * x }
end double_proc = proc { |x| x + x }
it "may accept multiple arguments" do pow_2_method = MethodSpecs::Composition.new.method(:pow_2)
mul = MethodSpecs::Composition.new.method(:mul) double_method = MethodSpecs::Composition.new.method(:double)
inc = proc { |n| n + 1 }
(pow_2_method >> double_proc).call(2).should == 8
(mul >> inc).call(2, 3).should == 7 (double_method >> pow_2_proc).call(2).should == 16
end end
it "accepts any callable object" do
inc = MethodSpecs::Composition.new.method(:inc)
double = Object.new
def double.call(n); n * 2; end
(inc >> double).call(3).should == 8
end
it_behaves_like :proc_compose, :>>, -> { MethodSpecs::Composition.new.method(:upcase) }
describe "composition" do
it "is a lambda" do
pow_2 = MethodSpecs::Composition.new.method(:pow_2)
double = proc { |x| x + x }
(pow_2 >> double).is_a?(Proc).should == true
(pow_2 >> double).should.lambda?
end
it "may accept multiple arguments" do
mul = MethodSpecs::Composition.new.method(:mul)
inc = proc { |n| n + 1 }
(mul >> inc).call(2, 3).should == 7
end end
end end
end end

View file

@ -376,6 +376,162 @@ describe "Module#include" do
foo.call.should == 'n' foo.call.should == 'n'
end end
it "updates the constant when an included module is updated" do
module ModuleSpecs::ConstUpdated
module A
FOO = 'a'
end
module M
end
module B
include A
include M
def self.foo
FOO
end
end
B.foo.should == 'a'
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
end
it "updates the constant when a module included after a call is later updated" do
module ModuleSpecs::ConstLaterUpdated
module A
FOO = 'a'
end
module B
include A
def self.foo
FOO
end
end
B.foo.should == 'a'
module M
end
B.include M
B.foo.should == 'a'
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
end
it "updates the constant when a module included in another module after a call is later updated" do
module ModuleSpecs::ConstModuleLaterUpdated
module A
FOO = 'a'
end
module B
include A
def self.foo
FOO
end
end
B.foo.should == 'a'
module M
end
B.include M
B.foo.should == 'a'
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
end
it "updates the constant when a nested included module is updated" do
module ModuleSpecs::ConstUpdatedNestedIncludeUpdated
module A
FOO = 'a'
end
module N
end
module M
include N
end
module B
include A
include M
def self.foo
FOO
end
end
B.foo.should == 'a'
N.const_set(:FOO, 'n')
B.foo.should == 'n'
end
end
it "updates the constant when a new module is included" do
module ModuleSpecs::ConstUpdatedNewInclude
module A
FOO = 'a'
end
module M
FOO = 'm'
end
module B
include A
def self.foo
FOO
end
end
B.foo.should == 'a'
B.include(M)
B.foo.should == 'm'
end
end
it "updates the constant when a new module with nested module is included" do
module ModuleSpecs::ConstUpdatedNestedIncluded
module A
FOO = 'a'
end
module N
FOO = 'n'
end
module M
include N
end
module B
include A
def self.foo
FOO
end
end
B.foo.should == 'a'
B.include M
B.foo.should == 'n'
end
end
end end
describe "Module#include?" do describe "Module#include?" do

View file

@ -47,54 +47,52 @@ describe "Module#method_defined?" do
c.method_defined?(o).should == true c.method_defined?(o).should == true
end end
ruby_version_is "2.6" do # works as method_defined?(method_name)
# works as method_defined?(method_name) describe "when passed true as a second optional argument" do
describe "when passed true as a second optional argument" do it "performs a lookup in ancestors" do
it "performs a lookup in ancestors" do ModuleSpecs::Child.method_defined?(:public_child, true).should == true
ModuleSpecs::Child.method_defined?(:public_child, true).should == true ModuleSpecs::Child.method_defined?(:protected_child, true).should == true
ModuleSpecs::Child.method_defined?(:protected_child, true).should == true ModuleSpecs::Child.method_defined?(:accessor_method, true).should == true
ModuleSpecs::Child.method_defined?(:accessor_method, true).should == true ModuleSpecs::Child.method_defined?(:private_child, true).should == false
ModuleSpecs::Child.method_defined?(:private_child, true).should == false
# Defined in Parent # Defined in Parent
ModuleSpecs::Child.method_defined?(:public_parent, true).should == true ModuleSpecs::Child.method_defined?(:public_parent, true).should == true
ModuleSpecs::Child.method_defined?(:protected_parent, true).should == true ModuleSpecs::Child.method_defined?(:protected_parent, true).should == true
ModuleSpecs::Child.method_defined?(:private_parent, true).should == false ModuleSpecs::Child.method_defined?(:private_parent, true).should == false
# Defined in Module # Defined in Module
ModuleSpecs::Child.method_defined?(:public_module, true).should == true ModuleSpecs::Child.method_defined?(:public_module, true).should == true
ModuleSpecs::Child.method_defined?(:protected_module, true).should == true ModuleSpecs::Child.method_defined?(:protected_module, true).should == true
ModuleSpecs::Child.method_defined?(:private_module, true).should == false ModuleSpecs::Child.method_defined?(:private_module, true).should == false
# Defined in SuperModule # Defined in SuperModule
ModuleSpecs::Child.method_defined?(:public_super_module, true).should == true ModuleSpecs::Child.method_defined?(:public_super_module, true).should == true
ModuleSpecs::Child.method_defined?(:protected_super_module, true).should == true ModuleSpecs::Child.method_defined?(:protected_super_module, true).should == true
ModuleSpecs::Child.method_defined?(:private_super_module, true).should == false ModuleSpecs::Child.method_defined?(:private_super_module, true).should == false
end
end end
end
describe "when passed false as a second optional argument" do describe "when passed false as a second optional argument" do
it "checks only the class itself" do it "checks only the class itself" do
ModuleSpecs::Child.method_defined?(:public_child, false).should == true ModuleSpecs::Child.method_defined?(:public_child, false).should == true
ModuleSpecs::Child.method_defined?(:protected_child, false).should == true ModuleSpecs::Child.method_defined?(:protected_child, false).should == true
ModuleSpecs::Child.method_defined?(:accessor_method, false).should == true ModuleSpecs::Child.method_defined?(:accessor_method, false).should == true
ModuleSpecs::Child.method_defined?(:private_child, false).should == false ModuleSpecs::Child.method_defined?(:private_child, false).should == false
# Defined in Parent # Defined in Parent
ModuleSpecs::Child.method_defined?(:public_parent, false).should == false ModuleSpecs::Child.method_defined?(:public_parent, false).should == false
ModuleSpecs::Child.method_defined?(:protected_parent, false).should == false ModuleSpecs::Child.method_defined?(:protected_parent, false).should == false
ModuleSpecs::Child.method_defined?(:private_parent, false).should == false ModuleSpecs::Child.method_defined?(:private_parent, false).should == false
# Defined in Module # Defined in Module
ModuleSpecs::Child.method_defined?(:public_module, false).should == false ModuleSpecs::Child.method_defined?(:public_module, false).should == false
ModuleSpecs::Child.method_defined?(:protected_module, false).should == false ModuleSpecs::Child.method_defined?(:protected_module, false).should == false
ModuleSpecs::Child.method_defined?(:private_module, false).should == false ModuleSpecs::Child.method_defined?(:private_module, false).should == false
# Defined in SuperModule # Defined in SuperModule
ModuleSpecs::Child.method_defined?(:public_super_module, false).should == false ModuleSpecs::Child.method_defined?(:public_super_module, false).should == false
ModuleSpecs::Child.method_defined?(:protected_super_module, false).should == false ModuleSpecs::Child.method_defined?(:protected_super_module, false).should == false
ModuleSpecs::Child.method_defined?(:private_super_module, false).should == false ModuleSpecs::Child.method_defined?(:private_super_module, false).should == false
end
end end
end end
end end

View file

@ -222,6 +222,191 @@ describe "Module#prepend" do
foo.call.should == 'n' foo.call.should == 'n'
end end
it "updates the constant when a module is prepended" do
module ModuleSpecs::ConstUpdatePrepended
module M
FOO = 'm'
end
module A
FOO = 'a'
end
module B
include A
def self.foo
FOO
end
end
B.foo.should == 'a'
B.prepend M
B.foo.should == 'm'
end
end
it "updates the constant when a prepended module is updated" do
module ModuleSpecs::ConstPrependedUpdated
module M
end
module A
FOO = 'a'
end
module B
include A
prepend M
def self.foo
FOO
end
end
B.foo.should == 'a'
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
end
it "updates the constant when there is a base included constant and the prepended module overrides it" do
module ModuleSpecs::ConstIncludedPrependedOverride
module Base
FOO = 'a'
end
module A
include Base
def self.foo
FOO
end
end
A.foo.should == 'a'
module M
FOO = 'm'
end
A.prepend M
A.foo.should == 'm'
end
end
it "updates the constant when there is a base included constant and the prepended module is later updated" do
module ModuleSpecs::ConstIncludedPrependedLaterUpdated
module Base
FOO = 'a'
end
module A
include Base
def self.foo
FOO
end
end
A.foo.should == 'a'
module M
end
A.prepend M
A.foo.should == 'a'
M.const_set(:FOO, 'm')
A.foo.should == 'm'
end
end
it "updates the constant when a module prepended after a constant is later updated" do
module ModuleSpecs::ConstUpdatedPrependedAfterLaterUpdated
module M
end
module A
FOO = 'a'
end
module B
include A
def self.foo
FOO
end
end
B.foo.should == 'a'
B.prepend M
B.foo.should == 'a'
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
end
it "updates the constant when a module is prepended after another and the constant is defined later on that module" do
module ModuleSpecs::ConstUpdatedPrependedAfterConstDefined
module M
FOO = 'm'
end
module A
prepend M
def self.foo
FOO
end
end
A.foo.should == 'm'
module N
end
A.prepend N
A.foo.should == 'm'
N.const_set(:FOO, 'n')
A.foo.should == 'n'
end
end
it "updates the constant when a module is included in a prepended module and the constant is defined later" do
module ModuleSpecs::ConstUpdatedIncludedInPrependedConstDefinedLater
module A
def self.foo
FOO
end
end
module Base
FOO = 'a'
end
A.prepend Base
A.foo.should == 'a'
module N
end
module M
include N
end
A.prepend M
N.const_set(:FOO, 'n')
A.foo.should == 'n'
end
end
it "updates the constant when a new module with an included module is prepended" do
module ModuleSpecs::ConstUpdatedNewModuleIncludedPrepended
module A
FOO = 'a'
end
module B
include A
def self.foo
FOO
end
end
module N
FOO = 'n'
end
module M
include N
end
B.foo.should == 'a'
B.prepend M
B.foo.should == 'n'
end
end
it "raises a TypeError when the argument is not a Module" do it "raises a TypeError when the argument is not a Module" do
-> { ModuleSpecs::Basic.prepend(Class.new) }.should raise_error(TypeError) -> { ModuleSpecs::Basic.prepend(Class.new) }.should raise_error(TypeError)
end end

View file

@ -70,53 +70,51 @@ describe "Module#private_method_defined?" do
ModuleSpecs::CountsMixin.private_method_defined?(str).should == true ModuleSpecs::CountsMixin.private_method_defined?(str).should == true
end end
ruby_version_is "2.6" do describe "when passed true as a second optional argument" do
describe "when passed true as a second optional argument" do it "performs a lookup in ancestors" do
it "performs a lookup in ancestors" do ModuleSpecs::Child.private_method_defined?(:public_child, true).should == false
ModuleSpecs::Child.private_method_defined?(:public_child, true).should == false ModuleSpecs::Child.private_method_defined?(:protected_child, true).should == false
ModuleSpecs::Child.private_method_defined?(:protected_child, true).should == false ModuleSpecs::Child.private_method_defined?(:accessor_method, true).should == false
ModuleSpecs::Child.private_method_defined?(:accessor_method, true).should == false ModuleSpecs::Child.private_method_defined?(:private_child, true).should == true
ModuleSpecs::Child.private_method_defined?(:private_child, true).should == true
# Defined in Parent # Defined in Parent
ModuleSpecs::Child.private_method_defined?(:public_parent, true).should == false ModuleSpecs::Child.private_method_defined?(:public_parent, true).should == false
ModuleSpecs::Child.private_method_defined?(:protected_parent, true).should == false ModuleSpecs::Child.private_method_defined?(:protected_parent, true).should == false
ModuleSpecs::Child.private_method_defined?(:private_parent, true).should == true ModuleSpecs::Child.private_method_defined?(:private_parent, true).should == true
# Defined in Module # Defined in Module
ModuleSpecs::Child.private_method_defined?(:public_module, true).should == false ModuleSpecs::Child.private_method_defined?(:public_module, true).should == false
ModuleSpecs::Child.private_method_defined?(:protected_module, true).should == false ModuleSpecs::Child.private_method_defined?(:protected_module, true).should == false
ModuleSpecs::Child.private_method_defined?(:private_module, true).should == true ModuleSpecs::Child.private_method_defined?(:private_module, true).should == true
# Defined in SuperModule # Defined in SuperModule
ModuleSpecs::Child.private_method_defined?(:public_super_module, true).should == false ModuleSpecs::Child.private_method_defined?(:public_super_module, true).should == false
ModuleSpecs::Child.private_method_defined?(:protected_super_module, true).should == false ModuleSpecs::Child.private_method_defined?(:protected_super_module, true).should == false
ModuleSpecs::Child.private_method_defined?(:private_super_module, true).should == true ModuleSpecs::Child.private_method_defined?(:private_super_module, true).should == true
end
end end
end
describe "when passed false as a second optional argument" do describe "when passed false as a second optional argument" do
it "checks only the class itself" do it "checks only the class itself" do
ModuleSpecs::Child.private_method_defined?(:public_child, false).should == false ModuleSpecs::Child.private_method_defined?(:public_child, false).should == false
ModuleSpecs::Child.private_method_defined?(:protected_child, false).should == false ModuleSpecs::Child.private_method_defined?(:protected_child, false).should == false
ModuleSpecs::Child.private_method_defined?(:accessor_method, false).should == false ModuleSpecs::Child.private_method_defined?(:accessor_method, false).should == false
ModuleSpecs::Child.private_method_defined?(:private_child, false).should == true ModuleSpecs::Child.private_method_defined?(:private_child, false).should == true
# Defined in Parent # Defined in Parent
ModuleSpecs::Child.private_method_defined?(:public_parent, false).should == false ModuleSpecs::Child.private_method_defined?(:public_parent, false).should == false
ModuleSpecs::Child.private_method_defined?(:protected_parent, false).should == false ModuleSpecs::Child.private_method_defined?(:protected_parent, false).should == false
ModuleSpecs::Child.private_method_defined?(:private_parent, false).should == false ModuleSpecs::Child.private_method_defined?(:private_parent, false).should == false
# Defined in Module # Defined in Module
ModuleSpecs::Child.private_method_defined?(:public_module, false).should == false ModuleSpecs::Child.private_method_defined?(:public_module, false).should == false
ModuleSpecs::Child.private_method_defined?(:protected_module, false).should == false ModuleSpecs::Child.private_method_defined?(:protected_module, false).should == false
ModuleSpecs::Child.private_method_defined?(:private_module, false).should == false ModuleSpecs::Child.private_method_defined?(:private_module, false).should == false
# Defined in SuperModule # Defined in SuperModule
ModuleSpecs::Child.private_method_defined?(:public_super_module, false).should == false ModuleSpecs::Child.private_method_defined?(:public_super_module, false).should == false
ModuleSpecs::Child.private_method_defined?(:protected_super_module, false).should == false ModuleSpecs::Child.private_method_defined?(:protected_super_module, false).should == false
ModuleSpecs::Child.private_method_defined?(:private_super_module, false).should == false ModuleSpecs::Child.private_method_defined?(:private_super_module, false).should == false
end
end end
end end
end end

View file

@ -70,53 +70,51 @@ describe "Module#protected_method_defined?" do
ModuleSpecs::CountsMixin.protected_method_defined?(str).should == true ModuleSpecs::CountsMixin.protected_method_defined?(str).should == true
end end
ruby_version_is "2.6" do describe "when passed true as a second optional argument" do
describe "when passed true as a second optional argument" do it "performs a lookup in ancestors" do
it "performs a lookup in ancestors" do ModuleSpecs::Child.protected_method_defined?(:public_child, true).should == false
ModuleSpecs::Child.protected_method_defined?(:public_child, true).should == false ModuleSpecs::Child.protected_method_defined?(:protected_child, true).should == true
ModuleSpecs::Child.protected_method_defined?(:protected_child, true).should == true ModuleSpecs::Child.protected_method_defined?(:accessor_method, true).should == false
ModuleSpecs::Child.protected_method_defined?(:accessor_method, true).should == false ModuleSpecs::Child.protected_method_defined?(:private_child, true).should == false
ModuleSpecs::Child.protected_method_defined?(:private_child, true).should == false
# Defined in Parent # Defined in Parent
ModuleSpecs::Child.protected_method_defined?(:public_parent, true).should == false ModuleSpecs::Child.protected_method_defined?(:public_parent, true).should == false
ModuleSpecs::Child.protected_method_defined?(:protected_parent, true).should == true ModuleSpecs::Child.protected_method_defined?(:protected_parent, true).should == true
ModuleSpecs::Child.protected_method_defined?(:private_parent, true).should == false ModuleSpecs::Child.protected_method_defined?(:private_parent, true).should == false
# Defined in Module # Defined in Module
ModuleSpecs::Child.protected_method_defined?(:public_module, true).should == false ModuleSpecs::Child.protected_method_defined?(:public_module, true).should == false
ModuleSpecs::Child.protected_method_defined?(:protected_module, true).should == true ModuleSpecs::Child.protected_method_defined?(:protected_module, true).should == true
ModuleSpecs::Child.protected_method_defined?(:private_module, true).should == false ModuleSpecs::Child.protected_method_defined?(:private_module, true).should == false
# Defined in SuperModule # Defined in SuperModule
ModuleSpecs::Child.protected_method_defined?(:public_super_module, true).should == false ModuleSpecs::Child.protected_method_defined?(:public_super_module, true).should == false
ModuleSpecs::Child.protected_method_defined?(:protected_super_module, true).should == true ModuleSpecs::Child.protected_method_defined?(:protected_super_module, true).should == true
ModuleSpecs::Child.protected_method_defined?(:private_super_module, true).should == false ModuleSpecs::Child.protected_method_defined?(:private_super_module, true).should == false
end
end end
end
describe "when passed false as a second optional argument" do describe "when passed false as a second optional argument" do
it "checks only the class itself" do it "checks only the class itself" do
ModuleSpecs::Child.protected_method_defined?(:public_child, false).should == false ModuleSpecs::Child.protected_method_defined?(:public_child, false).should == false
ModuleSpecs::Child.protected_method_defined?(:protected_child, false).should == true ModuleSpecs::Child.protected_method_defined?(:protected_child, false).should == true
ModuleSpecs::Child.protected_method_defined?(:accessor_method, false).should == false ModuleSpecs::Child.protected_method_defined?(:accessor_method, false).should == false
ModuleSpecs::Child.protected_method_defined?(:private_child, false).should == false ModuleSpecs::Child.protected_method_defined?(:private_child, false).should == false
# Defined in Parent # Defined in Parent
ModuleSpecs::Child.protected_method_defined?(:public_parent, false).should == false ModuleSpecs::Child.protected_method_defined?(:public_parent, false).should == false
ModuleSpecs::Child.protected_method_defined?(:protected_parent, false).should == false ModuleSpecs::Child.protected_method_defined?(:protected_parent, false).should == false
ModuleSpecs::Child.protected_method_defined?(:private_parent, false).should == false ModuleSpecs::Child.protected_method_defined?(:private_parent, false).should == false
# Defined in Module # Defined in Module
ModuleSpecs::Child.protected_method_defined?(:public_module, false).should == false ModuleSpecs::Child.protected_method_defined?(:public_module, false).should == false
ModuleSpecs::Child.protected_method_defined?(:protected_module, false).should == false ModuleSpecs::Child.protected_method_defined?(:protected_module, false).should == false
ModuleSpecs::Child.protected_method_defined?(:private_module, false).should == false ModuleSpecs::Child.protected_method_defined?(:private_module, false).should == false
# Defined in SuperModule # Defined in SuperModule
ModuleSpecs::Child.protected_method_defined?(:public_super_module, false).should == false ModuleSpecs::Child.protected_method_defined?(:public_super_module, false).should == false
ModuleSpecs::Child.protected_method_defined?(:protected_super_module, false).should == false ModuleSpecs::Child.protected_method_defined?(:protected_super_module, false).should == false
ModuleSpecs::Child.protected_method_defined?(:private_super_module, false).should == false ModuleSpecs::Child.protected_method_defined?(:private_super_module, false).should == false
end
end end
end end
end end

View file

@ -453,44 +453,22 @@ describe "Module#refine" do
result.should == ["(1)", "(2)", "(3)"] result.should == ["(1)", "(2)", "(3)"]
end end
ruby_version_is "" ... "2.6" do it "is honored by Kernel#public_send" do
it "is not honored by Kernel#public_send" do refined_class = ModuleSpecs.build_refined_class
refined_class = ModuleSpecs.build_refined_class
refinement = Module.new do refinement = Module.new do
refine refined_class do refine refined_class do
def foo; "foo from refinement"; end def foo; "foo from refinement"; end
end
end end
result = nil
Module.new do
using refinement
result = refined_class.new.public_send :foo
end
result.should == "foo"
end end
end
ruby_version_is "2.6" do result = nil
it "is honored by Kernel#public_send" do Module.new do
refined_class = ModuleSpecs.build_refined_class using refinement
result = refined_class.new.public_send :foo
refinement = Module.new do
refine refined_class do
def foo; "foo from refinement"; end
end
end
result = nil
Module.new do
using refinement
result = refined_class.new.public_send :foo
end
result.should == "foo from refinement"
end end
result.should == "foo from refinement"
end end
it "is honored by string interpolation" do it "is honored by string interpolation" do
@ -647,81 +625,39 @@ describe "Module#refine" do
end end
end end
ruby_version_is "" ... "2.6" do it "is honored by Kernel#respond_to?" do
it "is not honored by Kernel#respond_to?" do klass = Class.new
klass = Class.new refinement = Module.new do
refinement = Module.new do refine klass do
refine klass do def foo; end
def foo; end
end
end end
result = nil
Module.new do
using refinement
result = klass.new.respond_to?(:foo)
end
result.should == false
end end
result = nil
Module.new do
using refinement
result = klass.new.respond_to?(:foo)
end
result.should == true
end end
ruby_version_is "2.6" do it "is honored by &" do
it "is honored by Kernel#respond_to?" do refinement = Module.new do
klass = Class.new refine String do
refinement = Module.new do def to_proc(*args)
refine klass do -> * { 'foo' }
def foo; end
end end
end end
result = nil
Module.new do
using refinement
result = klass.new.respond_to?(:foo)
end
result.should == true
end end
end
ruby_version_is ""..."2.6" do result = nil
it "is not honored by &" do Module.new do
refinement = Module.new do using refinement
refine String do result = ["hola"].map(&"upcase")
def to_proc(*args)
-> * { 'foo' }
end
end
end
-> do
Module.new do
using refinement
["hola"].map(&"upcase")
end
end.should raise_error(TypeError, /wrong argument type String \(expected Proc\)/)
end end
end
ruby_version_is "2.6" do result.should == ['foo']
it "is honored by &" do
refinement = Module.new do
refine String do
def to_proc(*args)
-> * { 'foo' }
end
end
end
result = nil
Module.new do
using refinement
result = ["hola"].map(&"upcase")
end
result.should == ['foo']
end
end end
end end

View file

@ -81,4 +81,25 @@ describe "Module#remove_const" do
ConstantSpecs.autoload :AutoloadedConstant, 'a_file' ConstantSpecs.autoload :AutoloadedConstant, 'a_file'
ConstantSpecs.send(:remove_const, :AutoloadedConstant).should be_nil ConstantSpecs.send(:remove_const, :AutoloadedConstant).should be_nil
end end
it "updates the constant value" do
module ConstantSpecs::RemovedConstantUpdate
module M
FOO = 'm'
end
module A
include M
FOO = 'a'
def self.foo
FOO
end
end
A.foo.should == 'a'
A.send(:remove_const,:FOO)
A.foo.should == 'm'
end
end
end end

View file

@ -1,23 +1,21 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.6" do describe "NilClass#=~" do
describe "NilClass#=~" do it "returns nil matching any object" do
it "returns nil matching any object" do o = Object.new
o = Object.new
suppress_warning do suppress_warning do
(o =~ /Object/).should be_nil (o =~ /Object/).should be_nil
(o =~ 'Object').should be_nil (o =~ 'Object').should be_nil
(o =~ Object).should be_nil (o =~ Object).should be_nil
(o =~ Object.new).should be_nil (o =~ Object.new).should be_nil
(o =~ nil).should be_nil (o =~ nil).should be_nil
(o =~ false).should be_nil (o =~ false).should be_nil
(o =~ true).should be_nil (o =~ true).should be_nil
end
end
it "should not warn" do
-> { nil =~ /a/ }.should_not complain(verbose: true)
end end
end end
it "should not warn" do
-> { nil =~ /a/ }.should_not complain(verbose: true)
end
end end

View file

@ -257,9 +257,7 @@ describe :numeric_step, :shared => true do
describe "when no block is given" do describe "when no block is given" do
step_enum_class = Enumerator step_enum_class = Enumerator
ruby_version_is "2.6" do step_enum_class = Enumerator::ArithmeticSequence
step_enum_class = Enumerator::ArithmeticSequence
end
ruby_version_is ""..."3.0" do ruby_version_is ""..."3.0" do
it "returns an #{step_enum_class} when step is 0" do it "returns an #{step_enum_class} when step is 0" do

View file

@ -22,9 +22,7 @@ describe "Numeric#step" do
describe "when no block is given" do describe "when no block is given" do
step_enum_class = Enumerator step_enum_class = Enumerator
ruby_version_is "2.6" do step_enum_class = Enumerator::ArithmeticSequence
step_enum_class = Enumerator::ArithmeticSequence
end
ruby_version_is ""..."3.0" do ruby_version_is ""..."3.0" do
it "returns an #{step_enum_class} when step is 0" do it "returns an #{step_enum_class} when step is 0" do
@ -38,19 +36,7 @@ describe "Numeric#step" do
describe "returned #{step_enum_class}" do describe "returned #{step_enum_class}" do
describe "size" do describe "size" do
ruby_version_is ""..."2.6" do ruby_version_is ""..."3.0" do
it "raises an ArgumentError when step is 0" do
enum = 1.step(5, 0)
-> { enum.size }.should raise_error(ArgumentError)
end
it "raises an ArgumentError when step is 0.0" do
enum = 1.step(2, 0.0)
-> { enum.size }.should raise_error(ArgumentError)
end
end
ruby_version_is "2.6"..."3.0" do
it "is infinity when step is 0" do it "is infinity when step is 0" do
enum = 1.step(5, 0) enum = 1.step(5, 0)
enum.size.should == Float::INFINITY enum.size.should == Float::INFINITY
@ -69,16 +55,8 @@ describe "Numeric#step" do
end end
describe "type" do describe "type" do
ruby_version_is ""..."2.6" do it "returns an instance of Enumerator::ArithmeticSequence" do
it "returns an instance of Enumerator" do 1.step(10).class.should == Enumerator::ArithmeticSequence
1.step(10).class.should == Enumerator
end
end
ruby_version_is "2.6" do
it "returns an instance of Enumerator::ArithmeticSequence" do
1.step(10).class.should == Enumerator::ArithmeticSequence
end
end end
end end
end end

View file

@ -1,156 +1,154 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'shared/compose' require_relative 'shared/compose'
ruby_version_is "2.6" do describe "Proc#<<" do
describe "Proc#<<" do it "returns a Proc that is the composition of self and the passed Proc" do
it "returns a Proc that is the composition of self and the passed Proc" do upcase = proc { |s| s.upcase }
upcase = proc { |s| s.upcase } succ = proc { |s| s.succ }
succ = proc { |s| s.succ }
(succ << upcase).call('Ruby').should == "RUBZ" (succ << upcase).call('Ruby').should == "RUBZ"
end
it "calls passed Proc with arguments and then calls self with result" do
f = proc { |x| x * x }
g = proc { |x| x + x }
(f << g).call(2).should == 16
(g << f).call(2).should == 8
end
it "accepts any callable object" do
inc = proc { |n| n + 1 }
double = Object.new
def double.call(n); n * 2; end
(inc << double).call(3).should == 7
end
it_behaves_like :proc_compose, :<<, -> { proc { |s| s.upcase } }
describe "composition" do
it "is a Proc" do
f = proc { |x| x * x }
g = proc { |x| x + x }
(f << g).is_a?(Proc).should == true
(f << g).should_not.lambda?
end
ruby_version_is(''...'3.0') do
it "is a Proc when other is lambda" do
f = proc { |x| x * x }
g = -> x { x + x }
(f << g).is_a?(Proc).should == true
(f << g).should_not.lambda?
end
it "is a lambda when self is lambda" do
f = -> x { x * x }
g = proc { |x| x + x }
(f << g).is_a?(Proc).should == true
(f << g).should.lambda?
end
end
ruby_version_is('3.0') do
it "is a lambda when parameter is lambda" do
f = -> x { x * x }
g = proc { |x| x + x }
lambda_proc = -> x { x }
(f << g).is_a?(Proc).should == true
(f << g).should_not.lambda?
(f << lambda_proc).should.lambda?
end
end
it "may accept multiple arguments" do
inc = proc { |n| n + 1 }
mul = proc { |n, m| n * m }
(inc << mul).call(2, 3).should == 7
end
it "passes blocks to the second proc" do
ScratchPad.record []
one = proc { |&arg| arg.call :one if arg }
two = proc { |&arg| arg.call :two if arg }
(one << two).call { |x| ScratchPad << x }
ScratchPad.recorded.should == [:two]
end
end
end end
describe "Proc#>>" do it "calls passed Proc with arguments and then calls self with result" do
it "returns a Proc that is the composition of self and the passed Proc" do f = proc { |x| x * x }
upcase = proc { |s| s.upcase } g = proc { |x| x + x }
succ = proc { |s| s.succ }
(succ >> upcase).call('Ruby').should == "RUBZ" (f << g).call(2).should == 16
end (g << f).call(2).should == 8
end
it "calls passed Proc with arguments and then calls self with result" do it "accepts any callable object" do
inc = proc { |n| n + 1 }
double = Object.new
def double.call(n); n * 2; end
(inc << double).call(3).should == 7
end
it_behaves_like :proc_compose, :<<, -> { proc { |s| s.upcase } }
describe "composition" do
it "is a Proc" do
f = proc { |x| x * x } f = proc { |x| x * x }
g = proc { |x| x + x } g = proc { |x| x + x }
(f >> g).call(2).should == 8 (f << g).is_a?(Proc).should == true
(g >> f).call(2).should == 16 (f << g).should_not.lambda?
end end
it "accepts any callable object" do ruby_version_is(''...'3.0') do
inc = proc { |n| n + 1 }
double = Object.new
def double.call(n); n * 2; end
(inc >> double).call(3).should == 8
end
it_behaves_like :proc_compose, :>>, -> { proc { |s| s.upcase } }
describe "composition" do
it "is a Proc" do
f = proc { |x| x * x }
g = proc { |x| x + x }
(f >> g).is_a?(Proc).should == true
(f >> g).should_not.lambda?
end
it "is a Proc when other is lambda" do it "is a Proc when other is lambda" do
f = proc { |x| x * x } f = proc { |x| x * x }
g = -> x { x + x } g = -> x { x + x }
(f >> g).is_a?(Proc).should == true (f << g).is_a?(Proc).should == true
(f >> g).should_not.lambda? (f << g).should_not.lambda?
end end
it "is a lambda when self is lambda" do it "is a lambda when self is lambda" do
f = -> x { x * x } f = -> x { x * x }
g = proc { |x| x + x } g = proc { |x| x + x }
(f >> g).is_a?(Proc).should == true (f << g).is_a?(Proc).should == true
(f >> g).should.lambda? (f << g).should.lambda?
end end
end
it "may accept multiple arguments" do ruby_version_is('3.0') do
inc = proc { |n| n + 1 } it "is a lambda when parameter is lambda" do
mul = proc { |n, m| n * m } f = -> x { x * x }
g = proc { |x| x + x }
lambda_proc = -> x { x }
(mul >> inc).call(2, 3).should == 7 (f << g).is_a?(Proc).should == true
(f << g).should_not.lambda?
(f << lambda_proc).should.lambda?
end end
end
it "passes blocks to the first proc" do it "may accept multiple arguments" do
ScratchPad.record [] inc = proc { |n| n + 1 }
one = proc { |&arg| arg.call :one if arg } mul = proc { |n, m| n * m }
two = proc { |&arg| arg.call :two if arg }
(one >> two).call { |x| ScratchPad << x } (inc << mul).call(2, 3).should == 7
ScratchPad.recorded.should == [:one] end
end
it "passes blocks to the second proc" do
ScratchPad.record []
one = proc { |&arg| arg.call :one if arg }
two = proc { |&arg| arg.call :two if arg }
(one << two).call { |x| ScratchPad << x }
ScratchPad.recorded.should == [:two]
end
end
end
describe "Proc#>>" do
it "returns a Proc that is the composition of self and the passed Proc" do
upcase = proc { |s| s.upcase }
succ = proc { |s| s.succ }
(succ >> upcase).call('Ruby').should == "RUBZ"
end
it "calls passed Proc with arguments and then calls self with result" do
f = proc { |x| x * x }
g = proc { |x| x + x }
(f >> g).call(2).should == 8
(g >> f).call(2).should == 16
end
it "accepts any callable object" do
inc = proc { |n| n + 1 }
double = Object.new
def double.call(n); n * 2; end
(inc >> double).call(3).should == 8
end
it_behaves_like :proc_compose, :>>, -> { proc { |s| s.upcase } }
describe "composition" do
it "is a Proc" do
f = proc { |x| x * x }
g = proc { |x| x + x }
(f >> g).is_a?(Proc).should == true
(f >> g).should_not.lambda?
end
it "is a Proc when other is lambda" do
f = proc { |x| x * x }
g = -> x { x + x }
(f >> g).is_a?(Proc).should == true
(f >> g).should_not.lambda?
end
it "is a lambda when self is lambda" do
f = -> x { x * x }
g = proc { |x| x + x }
(f >> g).is_a?(Proc).should == true
(f >> g).should.lambda?
end
it "may accept multiple arguments" do
inc = proc { |n| n + 1 }
mul = proc { |n, m| n * m }
(mul >> inc).call(2, 3).should == 7
end
it "passes blocks to the first proc" do
ScratchPad.record []
one = proc { |&arg| arg.call :one if arg }
two = proc { |&arg| arg.call :two if arg }
(one >> two).call { |x| ScratchPad << x }
ScratchPad.recorded.should == [:one]
end end
end end
end end

View file

@ -1,5 +1,5 @@
describe :proc_compose, shared: true do describe :proc_compose, shared: true do
ruby_version_is "2.6"..."2.7" do ruby_version_is ""..."2.7" do
it "raises NoMethodError when called if passed not callable object" do it "raises NoMethodError when called if passed not callable object" do
not_callable = Object.new not_callable = Object.new
composed = @object.call.send(@method, not_callable) composed = @object.call.send(@method, not_callable)

View file

@ -551,27 +551,14 @@ describe "Process.spawn" do
platform_is_not :windows do platform_is_not :windows do
context "defaults :close_others to" do context "defaults :close_others to" do
ruby_version_is ""..."2.6" do it "false" do
it "true" do IO.pipe do |r, w|
IO.pipe do |r, w| w.close_on_exec = false
w.close_on_exec = false code = "io = IO.new(#{w.fileno}); io.puts('inherited'); io.close"
code = "begin; IO.new(#{w.fileno}).close; rescue Errno::EBADF; puts 'not inherited'; end" pid = Process.spawn(ruby_cmd(code))
Process.wait Process.spawn(ruby_cmd(code), :out => @name) w.close
File.read(@name).should == "not inherited\n" Process.wait(pid)
end r.read.should == "inherited\n"
end
end
ruby_version_is "2.6" do
it "false" do
IO.pipe do |r, w|
w.close_on_exec = false
code = "io = IO.new(#{w.fileno}); io.puts('inherited'); io.close"
pid = Process.spawn(ruby_cmd(code))
w.close
Process.wait(pid)
r.read.should == "inherited\n"
end
end end
end end
end end

View file

@ -0,0 +1,102 @@
require_relative '../../../spec_helper'
require_relative '../fixtures/common'
ruby_version_is "3.0" do
describe "Process::Status.wait" do
ProcessSpecs.use_system_ruby(self)
before :all do
begin
leaked = Process.waitall
# Ruby-space should not see PIDs used by mjit
raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty?
rescue NotImplementedError
end
end
it "returns a status with pid -1 if there are no child processes" do
Process::Status.wait.pid.should == -1
end
platform_is_not :windows do
it "returns a status with its child pid" do
pid = Process.spawn(ruby_cmd('exit'))
status = Process::Status.wait
status.should be_an_instance_of(Process::Status)
status.pid.should == pid
end
it "should not set $? to the Process::Status" do
pid = Process.spawn(ruby_cmd('exit'))
status = Process::Status.wait
$?.should_not equal(status)
end
it "should not change the value of $?" do
pid = Process.spawn(ruby_cmd('exit'))
Process.wait
status = $?
Process::Status.wait
status.should equal($?)
end
it "waits for any child process if no pid is given" do
pid = Process.spawn(ruby_cmd('exit'))
Process::Status.wait.pid.should == pid
-> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
end
it "waits for a specific child if a pid is given" do
pid1 = Process.spawn(ruby_cmd('exit'))
pid2 = Process.spawn(ruby_cmd('exit'))
Process::Status.wait(pid2).pid.should == pid2
Process::Status.wait(pid1).pid.should == pid1
-> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
-> { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH)
end
it "coerces the pid to an Integer" do
pid1 = Process.spawn(ruby_cmd('exit'))
Process::Status.wait(mock_int(pid1)).pid.should == pid1
-> { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH)
end
# This spec is probably system-dependent.
it "waits for a child whose process group ID is that of the calling process" do
pid1 = Process.spawn(ruby_cmd('exit'), pgroup: true)
pid2 = Process.spawn(ruby_cmd('exit'))
Process::Status.wait(0).pid.should == pid2
Process::Status.wait.pid.should == pid1
end
# This spec is probably system-dependent.
it "doesn't block if no child is available when WNOHANG is used" do
read, write = IO.pipe
pid = Process.fork do
read.close
Signal.trap("TERM") { Process.exit! }
write << 1
write.close
sleep
end
Process::Status.wait(pid, Process::WNOHANG).should be_nil
# wait for the child to setup its TERM handler
write.close
read.read(1)
read.close
Process.kill("TERM", pid)
Process::Status.wait.pid.should == pid
end
it "always accepts flags=0" do
pid = Process.spawn(ruby_cmd('exit'))
Process::Status.wait(-1, 0).pid.should == pid
-> { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
end
end
end
end

View file

@ -25,8 +25,6 @@ describe "Random#bytes" do
end end
end end
ruby_version_is "2.6" do describe "Random.bytes" do
describe "Random.bytes" do it_behaves_like :random_bytes, :bytes, Random
it_behaves_like :random_bytes, :bytes, Random
end
end end

View file

@ -4,7 +4,5 @@ require_relative 'shared/rand'
describe "Random.random_number" do describe "Random.random_number" do
it_behaves_like :random_number, :random_number, Random.new it_behaves_like :random_number, :random_number, Random.new
ruby_version_is "2.6" do it_behaves_like :random_number, :random_number, Random
it_behaves_like :random_number, :random_number, Random
end
end end

View file

@ -215,118 +215,116 @@ describe "Range#bsearch" do
end end
end end
ruby_version_is "2.6" do context "with endless ranges and Integer values" do
context "with endless ranges and Integer values" do context "with a block returning true or false" do
context "with a block returning true or false" do it "returns minimum element if the block returns true for every element" do
it "returns minimum element if the block returns true for every element" do eval("(-2..)").bsearch { |x| true }.should == -2
eval("(-2..)").bsearch { |x| true }.should == -2
end
it "returns the smallest element for which block returns true" do
eval("(0..)").bsearch { |x| x >= 2 }.should == 2
eval("(-1..)").bsearch { |x| x >= 1 }.should == 1
end
end end
context "with a block returning negative, zero, positive numbers" do it "returns the smallest element for which block returns true" do
it "returns nil if the block returns less than zero for every element" do eval("(0..)").bsearch { |x| x >= 2 }.should == 2
eval("(0..)").bsearch { |x| -1 }.should be_nil eval("(-1..)").bsearch { |x| x >= 1 }.should == 1
end
it "returns nil if the block never returns zero" do
eval("(0..)").bsearch { |x| x > 5 ? -1 : 1 }.should be_nil
end
it "accepts -Float::INFINITY from the block" do
eval("(0..)").bsearch { |x| -Float::INFINITY }.should be_nil
end
it "returns an element at an index for which block returns 0.0" do
result = eval("(0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
result.should == 2
end
it "returns an element at an index for which block returns 0" do
result = eval("(0..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
[1, 2, 3].should include(result)
end
end end
end end
context "with endless ranges and Float values" do context "with a block returning negative, zero, positive numbers" do
context "with a block returning true or false" do it "returns nil if the block returns less than zero for every element" do
it "returns nil if the block returns false for every element" do eval("(0..)").bsearch { |x| -1 }.should be_nil
eval("(0.1..)").bsearch { |x| x < 0.0 }.should be_nil
eval("(0.1...)").bsearch { |x| x < 0.0 }.should be_nil
end
it "returns nil if the block returns nil for every element" do
eval("(-0.0..)").bsearch { |x| nil }.should be_nil
eval("(-0.0...)").bsearch { |x| nil }.should be_nil
end
it "returns minimum element if the block returns true for every element" do
eval("(-0.2..)").bsearch { |x| true }.should == -0.2
eval("(-0.2...)").bsearch { |x| true }.should == -0.2
end
it "returns the smallest element for which block returns true" do
eval("(0..)").bsearch { |x| x >= 2 }.should == 2
eval("(-1.2..)").bsearch { |x| x >= 1 }.should == 1
end
it "works with infinity bounds" do
inf = Float::INFINITY
eval("(inf..)").bsearch { |x| true }.should == inf
eval("(inf...)").bsearch { |x| true }.should == nil
eval("(-inf..)").bsearch { |x| true }.should == -inf
eval("(-inf...)").bsearch { |x| true }.should == -inf
end
end end
context "with a block returning negative, zero, positive numbers" do it "returns nil if the block never returns zero" do
it "returns nil if the block returns less than zero for every element" do eval("(0..)").bsearch { |x| x > 5 ? -1 : 1 }.should be_nil
eval("(-2.0..)").bsearch { |x| -1 }.should be_nil end
eval("(-2.0...)").bsearch { |x| -1 }.should be_nil
end
it "returns nil if the block returns greater than zero for every element" do it "accepts -Float::INFINITY from the block" do
eval("(0.3..)").bsearch { |x| 1 }.should be_nil eval("(0..)").bsearch { |x| -Float::INFINITY }.should be_nil
eval("(0.3...)").bsearch { |x| 1 }.should be_nil end
end
it "returns nil if the block never returns zero" do it "returns an element at an index for which block returns 0.0" do
eval("(0.2..)").bsearch { |x| x < 2 ? 1 : -1 }.should be_nil result = eval("(0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
end result.should == 2
end
it "accepts (+/-)Float::INFINITY from the block" do it "returns an element at an index for which block returns 0" do
eval("(0.1..)").bsearch { |x| Float::INFINITY }.should be_nil result = eval("(0..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
eval("(-5.0..)").bsearch { |x| -Float::INFINITY }.should be_nil [1, 2, 3].should include(result)
end end
end
end
it "returns an element at an index for which block returns 0.0" do context "with endless ranges and Float values" do
result = eval("(0.0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 } context "with a block returning true or false" do
result.should == 2 it "returns nil if the block returns false for every element" do
end eval("(0.1..)").bsearch { |x| x < 0.0 }.should be_nil
eval("(0.1...)").bsearch { |x| x < 0.0 }.should be_nil
end
it "returns an element at an index for which block returns 0" do it "returns nil if the block returns nil for every element" do
result = eval("(0.1..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 } eval("(-0.0..)").bsearch { |x| nil }.should be_nil
result.should >= 1 eval("(-0.0...)").bsearch { |x| nil }.should be_nil
result.should <= 3 end
end
it "works with infinity bounds" do it "returns minimum element if the block returns true for every element" do
inf = Float::INFINITY eval("(-0.2..)").bsearch { |x| true }.should == -0.2
eval("(inf..)").bsearch { |x| 1 }.should == nil eval("(-0.2...)").bsearch { |x| true }.should == -0.2
eval("(inf...)").bsearch { |x| 1 }.should == nil end
eval("(inf..)").bsearch { |x| x == inf ? 0 : 1 }.should == inf
eval("(inf...)").bsearch { |x| x == inf ? 0 : 1 }.should == nil it "returns the smallest element for which block returns true" do
eval("(-inf..)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf eval("(0..)").bsearch { |x| x >= 2 }.should == 2
eval("(-inf...)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf eval("(-1.2..)").bsearch { |x| x >= 1 }.should == 1
eval("(-inf..)").bsearch { |x| 3 - x }.should == 3 end
eval("(-inf...)").bsearch { |x| 3 - x }.should == 3
eval("(0.0...)").bsearch { 0 }.should != inf it "works with infinity bounds" do
end inf = Float::INFINITY
eval("(inf..)").bsearch { |x| true }.should == inf
eval("(inf...)").bsearch { |x| true }.should == nil
eval("(-inf..)").bsearch { |x| true }.should == -inf
eval("(-inf...)").bsearch { |x| true }.should == -inf
end
end
context "with a block returning negative, zero, positive numbers" do
it "returns nil if the block returns less than zero for every element" do
eval("(-2.0..)").bsearch { |x| -1 }.should be_nil
eval("(-2.0...)").bsearch { |x| -1 }.should be_nil
end
it "returns nil if the block returns greater than zero for every element" do
eval("(0.3..)").bsearch { |x| 1 }.should be_nil
eval("(0.3...)").bsearch { |x| 1 }.should be_nil
end
it "returns nil if the block never returns zero" do
eval("(0.2..)").bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
end
it "accepts (+/-)Float::INFINITY from the block" do
eval("(0.1..)").bsearch { |x| Float::INFINITY }.should be_nil
eval("(-5.0..)").bsearch { |x| -Float::INFINITY }.should be_nil
end
it "returns an element at an index for which block returns 0.0" do
result = eval("(0.0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
result.should == 2
end
it "returns an element at an index for which block returns 0" do
result = eval("(0.1..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
result.should >= 1
result.should <= 3
end
it "works with infinity bounds" do
inf = Float::INFINITY
eval("(inf..)").bsearch { |x| 1 }.should == nil
eval("(inf...)").bsearch { |x| 1 }.should == nil
eval("(inf..)").bsearch { |x| x == inf ? 0 : 1 }.should == inf
eval("(inf...)").bsearch { |x| x == inf ? 0 : 1 }.should == nil
eval("(-inf..)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf
eval("(-inf...)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf
eval("(-inf..)").bsearch { |x| 3 - x }.should == 3
eval("(-inf...)").bsearch { |x| 3 - x }.should == 3
eval("(0.0...)").bsearch { 0 }.should != inf
end end
end end
end end

View file

@ -3,27 +3,9 @@ require_relative 'shared/cover_and_include'
require_relative 'shared/cover' require_relative 'shared/cover'
describe "Range#===" do describe "Range#===" do
ruby_version_is ""..."2.6" do it "returns the result of calling #cover? on self" do
it "returns the result of calling #include? on self" do range = RangeSpecs::WithoutSucc.new(0)..RangeSpecs::WithoutSucc.new(10)
range = 0...10 (range === RangeSpecs::WithoutSucc.new(2)).should == true
range.should_receive(:include?).with(2).and_return(:true)
(range === 2).should == :true
end
it "requires #succ method to be implemented" do
range = RangeSpecs::WithoutSucc.new(0)..RangeSpecs::WithoutSucc.new(10)
-> do
range === RangeSpecs::WithoutSucc.new(2)
end.should raise_error(TypeError, /can't iterate from/)
end
end
ruby_version_is "2.6" do
it "returns the result of calling #cover? on self" do
range = RangeSpecs::WithoutSucc.new(0)..RangeSpecs::WithoutSucc.new(10)
(range === RangeSpecs::WithoutSucc.new(2)).should == true
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -38,26 +38,24 @@ describe "Range#each" do
a.should == ["Σ", "Τ", "Υ", "Φ", "Χ", "Ψ", "Ω"] a.should == ["Σ", "Τ", "Υ", "Φ", "Χ", "Ψ", "Ω"]
end end
ruby_version_is "2.6" do it "works with endless ranges" do
it "works with endless ranges" do a = []
a = [] eval("(-2..)").each { |x| break if x > 2; a << x }
eval("(-2..)").each { |x| break if x > 2; a << x } a.should == [-2, -1, 0, 1, 2]
a.should == [-2, -1, 0, 1, 2]
a = [] a = []
eval("(-2...)").each { |x| break if x > 2; a << x } eval("(-2...)").each { |x| break if x > 2; a << x }
a.should == [-2, -1, 0, 1, 2] a.should == [-2, -1, 0, 1, 2]
end end
it "works with String endless ranges" do it "works with String endless ranges" do
a = [] a = []
eval("('A'..)").each { |x| break if x > "D"; a << x } eval("('A'..)").each { |x| break if x > "D"; a << x }
a.should == ["A", "B", "C", "D"] a.should == ["A", "B", "C", "D"]
a = [] a = []
eval("('A'...)").each { |x| break if x > "D"; a << x } eval("('A'...)").each { |x| break if x > "D"; a << x }
a.should == ["A", "B", "C", "D"] a.should == ["A", "B", "C", "D"]
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

View file

@ -8,10 +8,8 @@ describe "Range#==" do
(0..1).should == (0..1.0) (0..1).should == (0..1.0)
end end
ruby_version_is "2.6" do it "returns true if the endpoints are == for endless ranges" do
it "returns true if the endpoints are == for endless ranges" do eval("(1.0..)").should == eval("(1.0..)")
eval("(1.0..)").should == eval("(1.0..)")
end
end end
ruby_version_is "2.7" do ruby_version_is "2.7" do

Some files were not shown because too many files have changed in this diff Show more