git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66888 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2019-01-20 20:38:57 +00:00
Родитель 58573c33e4
Коммит 6204e0804b
147 изменённых файлов: 2728 добавлений и 21522 удалений

Просмотреть файл

@ -15,14 +15,11 @@ matrix:
env: CHECK_LEAKS=true
- rvm: 2.6.0
env: CHECK_LEAKS=true
- rvm: ruby-head
- env: RUBOCOP=true
rvm: 2.4.5
script:
- gem install rubocop:0.61.0
- rubocop
allow_failures:
- rvm: ruby-head
branches:
only:
- master

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -4,7 +4,7 @@
[![Build Status](https://ci.appveyor.com/api/projects/status/1gs6f399320o44b1?svg=true)](https://ci.appveyor.com/project/eregon/spec-x948i)
[![Gitter](https://badges.gitter.im/ruby/spec.svg)](https://gitter.im/ruby/spec)
The Ruby Spec Suite is a test suite for the behavior of the Ruby programming language.
The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language.
It is not a standardized specification like the ISO one, and does not aim to become one.
Instead, it is a practical tool to describe and test the behavior of Ruby with code.
@ -112,6 +112,7 @@ under the MIT license in ruby/spec.
### History and RubySpec
This project was originally born from [Rubinius](https://github.com/rubinius/rubinius) tests being converted to the spec style.
The revision history of these specs is available [here](https://github.com/ruby/spec/blob/2b886623/CHANGES.before-2008-05-10).
These specs were later extracted to their own project, RubySpec, with a specific vision and principles.
At the end of 2014, Brian Shirai, the creator of RubySpec, decided to [end RubySpec](http://rubinius.com/2014/12/31/matz-s-ruby-developers-don-t-use-rubyspec/).
A couple months later, the different repositories were merged and [the project was revived](http://eregon.github.io/rubyspec/2015/07/29/rubyspec-is-reborn.html).

Просмотреть файл

@ -4,7 +4,7 @@ require_relative 'shared/difference'
ruby_version_is "2.6" do
describe "Array#difference" do
it_behaves_like :array_binary_difference, :-
it_behaves_like :array_binary_difference, :difference
it "returns a copy when called without any parameter" do
x = [1, 2, 3, 2]

Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,6 @@
module BindingSpecs
module LocationMethod
FILE_PATH = __FILE__
TEST_BINDING = binding
end
end

Просмотреть файл

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

Просмотреть файл

@ -70,3 +70,69 @@ ruby_version_is "2.5" do
end
end
end
ruby_version_is "2.6" do
describe "Dir#children" do
before :all do
DirSpecs.create_mock_dirs
end
before :each do
@internal = Encoding.default_internal
end
after :all do
DirSpecs.delete_mock_dirs
end
after :each do
Encoding.default_internal = @internal
@dir.close if @dir
end
it "returns an Array of filenames in an existing directory including dotfiles" do
@dir = Dir.new(DirSpecs.mock_dir)
a = @dir.children.sort
@dir.close
a.should == DirSpecs.expected_paths - %w[. ..]
@dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested")
a = @dir.children.sort
a.should == %w|.dotfile.ext directory|
end
it "accepts an options Hash" do
@dir = Dir.new("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8")
a = @dir.children.sort
a.should == %w|.dotfile.ext directory|
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 ASCII-8BIT encoded.
@dir = Dir.new(File.join(DirSpecs.mock_dir, 'special'))
children = @dir.children.sort
encoding = Encoding.find("filesystem")
encoding = Encoding::ASCII_8BIT 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

Просмотреть файл

@ -51,3 +51,55 @@ ruby_version_is "2.5" do
end
end
end
ruby_version_is "2.6" do
describe "Dir#each_child" do
before :all do
DirSpecs.create_mock_dirs
end
after :all do
DirSpecs.delete_mock_dirs
end
after :each do
@dir.close if @dir
end
it "yields all names in an existing directory to the provided block" do
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.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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,22 @@
require_relative '../../../spec_helper'
ruby_version_is "2.6" do
describe "Enumerator::ArithmeticSequence#hash" 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 == 1.step(10).hash
1.step(10, 5).hash.should == 1.step(10, 5).hash
(1..10).step.hash.should == (1..10).step.hash
(1...10).step(8).hash.should == (1...10).step(8).hash
# both have exclude_end? == false
(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...10).step.hash).should == false
((1..10).step.hash == (1..10).step(2).hash).should == false
end
end
end

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,24 @@
require_relative '../../../spec_helper'
require_relative '../../enumerable/fixtures/classes'
ruby_version_is "2.6" do
describe "Enumerator::Chain#size" 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.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

Просмотреть файл

@ -1,5 +1,89 @@
require_relative '../../shared/enumerator/each'
require_relative '../../spec_helper'
describe "Enumerator#each" do
it_behaves_like :enum_each, :each
before :each do
object_each_with_arguments = Object.new
def object_each_with_arguments.each_with_arguments(arg, *args)
yield arg, *args
:method_returned
end
@enum_with_arguments = object_each_with_arguments.to_enum(:each_with_arguments, :arg0, :arg1, :arg2)
@enum_with_yielder = Enumerator.new {|y| y.yield :ok}
end
it "yields each element of self to the given block" do
acc = []
[1,2,3].to_enum.each {|e| acc << e }
acc.should == [1,2,3]
end
it "calls #each on the object given in the constructor by default" do
each = mock('each')
each.should_receive(:each)
each.to_enum.each {|e| e }
end
it "calls #each on the underlying object until it's exhausted" do
each = mock('each')
each.should_receive(:each).and_yield(1).and_yield(2).and_yield(3)
acc = []
each.to_enum.each {|e| acc << e }
acc.should == [1,2,3]
end
it "calls the method given in the constructor instead of #each" do
each = mock('peach')
each.should_receive(:peach)
each.to_enum(:peach).each {|e| e }
end
it "calls the method given in the constructor until it's exhausted" do
each = mock('each')
each.should_receive(:each).and_yield(1).and_yield(2).and_yield(3)
acc = []
each.to_enum.each {|e| acc << e }
acc.should == [1,2,3]
end
it "raises a NoMethodError if the object doesn't respond to #each" do
enum = Object.new.to_enum
lambda do
enum.each { |e| e }
end.should raise_error(NoMethodError)
end
it "returns self if not given arguments and not given a block" do
@enum_with_arguments.each.should equal(@enum_with_arguments)
@enum_with_yielder.each.should equal(@enum_with_yielder)
end
it "returns the same value from receiver.each if block is given" do
@enum_with_arguments.each {}.should equal(:method_returned)
end
it "passes given arguments at initialized to receiver.each" do
@enum_with_arguments.each.to_a.should == [[:arg0, :arg1, :arg2]]
end
it "requires multiple arguments" do
Enumerator.instance_method(:each).arity.should < 0
end
it "appends given arguments to receiver.each" do
@enum_with_arguments.each(:each0, :each1).to_a.should == [[:arg0, :arg1, :arg2, :each0, :each1]]
@enum_with_arguments.each(:each2, :each3).to_a.should == [[:arg0, :arg1, :arg2, :each2, :each3]]
end
it "returns the same value from receiver.each if block and arguments are given" do
@enum_with_arguments.each(:each1, :each2) {}.should equal(:method_returned)
end
it "returns new Enumerator if given arguments but not given a block" do
ret = @enum_with_arguments.each 1
ret.should be_an_instance_of(Enumerator)
ret.should_not equal(@enum_with_arguments)
end
end

Просмотреть файл

@ -1,15 +0,0 @@
require_relative '../../shared/enumerator/each'
describe "Enumerator#inject" do
it_behaves_like :enum_each, :each
it "works when chained against each_with_index" do
passed_values = []
[:a].each_with_index.inject(0) do |accumulator,value|
passed_values << value
accumulator + 1
end.should == 1
passed_values.should == [[:a,0]]
end
end

Просмотреть файл

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

Просмотреть файл

@ -1,6 +1,41 @@
require_relative '../../spec_helper'
require_relative '../../shared/enumerator/new'
describe "Enumerator.new" do
it_behaves_like :enum_new, :new
it "creates a new custom enumerator with the given object, iterator and arguments" do
enum = Enumerator.new(1, :upto, 3)
enum.should be_an_instance_of(Enumerator)
end
it "creates a new custom enumerator that responds to #each" do
enum = Enumerator.new(1, :upto, 3)
enum.respond_to?(:each).should == true
end
it "creates a new custom enumerator that runs correctly" do
Enumerator.new(1, :upto, 3).map{|x|x}.should == [1,2,3]
end
it "aliases the second argument to :each" do
Enumerator.new(1..2).to_a.should == Enumerator.new(1..2, :each).to_a
end
it "doesn't check for the presence of the iterator method" do
Enumerator.new(nil).should be_an_instance_of(Enumerator)
end
it "uses the latest define iterator method" do
class StrangeEach
def each
yield :foo
end
end
enum = Enumerator.new(StrangeEach.new)
enum.to_a.should == [:foo]
class StrangeEach
def each
yield :bar
end
end
enum.to_a.should == [:bar]
end
end

Просмотреть файл

@ -1,6 +1,27 @@
require_relative '../../spec_helper'
require_relative '../../shared/enumerator/next'
describe "Enumerator#next" do
it_behaves_like :enum_next,:next
before :each do
@enum = 1.upto(3)
end
it "returns the next element of the enumeration" do
@enum.next.should == 1
@enum.next.should == 2
@enum.next.should == 3
end
it "raises a StopIteration exception at the end of the stream" do
3.times { @enum.next }
lambda { @enum.next }.should raise_error(StopIteration)
end
it "cannot be called again until the enumerator is rewound" do
3.times { @enum.next }
lambda { @enum.next }.should raise_error(StopIteration)
lambda { @enum.next }.should raise_error(StopIteration)
lambda { @enum.next }.should raise_error(StopIteration)
@enum.rewind
@enum.next.should == 1
end
end

Просмотреть файл

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

Просмотреть файл

@ -1,9 +1,41 @@
require_relative '../../spec_helper'
require_relative '../../shared/enumerator/rewind'
require_relative 'fixtures/common'
describe "Enumerator#rewind" do
it_behaves_like :enum_rewind, :rewind
before :each do
@enum = 1.upto(3)
end
it "resets the enumerator to its initial state" do
@enum.next.should == 1
@enum.next.should == 2
@enum.rewind
@enum.next.should == 1
end
it "returns self" do
@enum.rewind.should == @enum
end
it "has no effect on a new enumerator" do
@enum.rewind
@enum.next.should == 1
end
it "has no effect if called multiple, consecutive times" do
@enum.next.should == 1
@enum.rewind
@enum.rewind
@enum.next.should == 1
end
it "works with peek to reset the position" do
@enum.next
@enum.next
@enum.rewind
@enum.next
@enum.peek.should == 2
end
it "calls the enclosed object's rewind method if one exists" do
obj = mock('rewinder')

15
spec/ruby/core/env/filter_spec.rb поставляемый Normal file
Просмотреть файл

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

32
spec/ruby/core/env/select_spec.rb поставляемый
Просмотреть файл

@ -1,39 +1,13 @@
require_relative '../../spec_helper'
require_relative '../enumerable/shared/enumeratorized'
require_relative 'shared/select'
describe "ENV.select!" do
it "removes environment variables for which the block returns true" do
ENV["foo"] = "bar"
ENV.select! { |k, v| k != "foo" }
ENV["foo"].should == nil
end
it "returns self if any changes were made" do
ENV["foo"] = "bar"
ENV.select! { |k, v| k != "foo" }.should == ENV
end
it "returns nil if no changes were made" do
ENV.select! { true }.should == nil
end
it "returns an Enumerator if called without a block" do
ENV.select!.should be_an_instance_of(Enumerator)
end
it_behaves_like :env_select!, :select!
it_behaves_like :enumeratorized_with_origin_size, :select!, ENV
end
describe "ENV.select" do
it "returns a Hash of names and values for which block return true" do
ENV["foo"] = "bar"
ENV.select { |k, v| k == "foo" }.should == {"foo" => "bar"}
ENV.delete "foo"
end
it "returns an Enumerator when no block is given" do
ENV.select.should be_an_instance_of(Enumerator)
end
it_behaves_like :env_select, :select
it_behaves_like :enumeratorized_with_origin_size, :select, ENV
end

32
spec/ruby/core/env/shared/select.rb поставляемый Normal file
Просмотреть файл

@ -0,0 +1,32 @@
describe :env_select, shared: true do
it "returns a Hash of names and values for which block return true" do
ENV["foo"] = "bar"
(ENV.send(@method) { |k, v| k == "foo" }).should == { "foo" => "bar" }
ENV.delete "foo"
end
it "returns an Enumerator when no block is given" do
ENV.send(@method).should be_an_instance_of(Enumerator)
end
end
describe :env_select!, shared: true do
it "removes environment variables for which the block returns true" do
ENV["foo"] = "bar"
ENV.send(@method) { |k, v| k != "foo" }
ENV["foo"].should == nil
end
it "returns self if any changes were made" do
ENV["foo"] = "bar"
(ENV.send(@method) { |k, v| k != "foo" }).should == ENV
end
it "returns nil if no changes were made" do
(ENV.send(@method) { true }).should == nil
end
it "returns an Enumerator if called without a block" do
ENV.send(@method).should be_an_instance_of(Enumerator)
end
end

54
spec/ruby/core/env/to_h_spec.rb поставляемый
Просмотреть файл

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

Просмотреть файл

@ -34,5 +34,42 @@ ruby_version_is "2.5" do
e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m
end
end
ruby_version_is "2.6" do
it "contains cause of exception" do
begin
begin
raise 'the cause'
rescue
raise 'main exception'
end
rescue => e
exception = e
end
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
raise 'origin exception'
rescue
raise 'intermediate exception'
end
rescue
raise 'last exception'
end
rescue => e
exception = e
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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -3,12 +3,23 @@ require_relative 'fixtures/common'
describe "NoMethodError.new" do
it "allows passing method args" do
NoMethodError.new("msg","name","args").args.should == "args"
NoMethodError.new("msg", "name", ["args"]).args.should == ["args"]
end
it "does not require a name" do
NoMethodError.new("msg").message.should == "msg"
end
ruby_version_is "2.6" do
it "accepts a :receiver keyword argument" do
receiver = mock("receiver")
error = NoMethodError.new("msg", :name, receiver: receiver)
error.receiver.should == receiver
error.name.should == :name
end
end
end
describe "NoMethodError#args" do

Просмотреть файл

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

Просмотреть файл

@ -63,6 +63,17 @@ describe "Hash#merge" do
merge_pairs.should == each_pairs
end
ruby_version_is "2.6" do
it "accepts multiple hashes" do
result = { a: 1 }.merge({ b: 2 }, { c: 3 }, { d: 4 })
result.should == { a: 1, b: 2, c: 3, d: 4 }
end
it "accepts zero arguments and returns self" do
hash = { a: 1 }
hash.merge.should eql(hash)
end
end
end
describe "Hash#merge!" do

Просмотреть файл

@ -56,4 +56,16 @@ describe :hash_update, shared: true do
HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash)
end.should raise_error(frozen_error_class)
end
ruby_version_is "2.6" do
it "accepts multiple hashes" do
result = { a: 1 }.send(@method, { b: 2 }, { c: 3 }, { d: 4 })
result.should == { a: 1, b: 2, c: 3, d: 4 }
end
it "accepts zero arguments" do
hash = { a: 1 }
hash.send(@method).should eql(hash)
end
end
end

Просмотреть файл

@ -7,12 +7,6 @@ describe "Hash#to_h" do
h.to_h.should equal(h)
end
ruby_version_is "2.6" 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 }
end
end
describe "when called on a subclass of Hash" do
before :each do
@h = HashSpecs::MyHash.new
@ -37,4 +31,44 @@ describe "Hash#to_h" do
@h[42].should == 84
end
end
ruby_version_is "2.6" do
context "with block" 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 }
end
it "raises ArgumentError if block returns longer or shorter array" do
-> do
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v, 1] }
end.should raise_error(ArgumentError, /element has wrong array length/)
-> do
{ a: 1, b: 2 }.to_h { |k, v| [k] }
end.should raise_error(ArgumentError, /element has wrong array length/)
end
it "raises TypeError if block returns something other than Array" do
-> do
{ a: 1, b: 2 }.to_h { |k, v| "not-array" }
end.should raise_error(TypeError, /wrong element type String/)
end
it "coerces returned pair to Array with #to_ary" do
x = mock('x')
x.stub!(:to_ary).and_return([:b, 'b'])
{ a: 1 }.to_h { |k| x }.should == { :b => 'b' }
end
it "does not coerce returned pair to Array with #to_a" do
x = mock('x')
x.stub!(:to_a).and_return([:b, 'b'])
-> do
{ a: 1 }.to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject/)
end
end
end
end

Просмотреть файл

@ -49,7 +49,7 @@ describe "IO#ungetbyte" do
end
end
ruby_version_is '2.6'...'2.7' do
ruby_version_is '2.6'...'2.6.1' do
it "is an RangeError if the integer is not in 8bit" do
for i in [4095, 0x4f7574206f6620636861722072616e6765] do
lambda { @io.ungetbyte(i) }.should raise_error(RangeError)
@ -57,10 +57,11 @@ describe "IO#ungetbyte" do
end
end
ruby_version_is '2.7' do
ruby_version_is '2.6.1' do
it "never raises RangeError" do
for i in [4095, 0x4f7574206f6620636861722072616e6765] do
lambda { @io.ungetbyte(i) }.should_not raise_error
for i in [4095, 0x4f7574206f6620636861722072616e67ff] do
@io.ungetbyte(i).should be_nil
@io.getbyte.should == 255
end
end
end

Просмотреть файл

@ -138,4 +138,52 @@ describe "Kernel.Complex()" do
lambda { Complex(nil, 0) }.should raise_error(TypeError, "can't convert nil into Complex")
end
end
ruby_version_is "2.6" do
describe "when passed exception: false" do
describe "and [Numeric]" do
it "returns a complex number" do
Complex("123", exception: false).should == Complex(123)
end
end
describe "and [non-Numeric]" do
it "swallows an error" do
Complex(:sym, exception: false).should == nil
end
end
describe "and [non-Numeric, Numeric] argument" do
it "throws a TypeError" do
lambda { Complex(:sym, 0, exception: false) }.should raise_error(TypeError, "not a real")
end
end
describe "and [anything, non-Numeric] argument" do
it "swallows an error" do
Complex("a", :sym, exception: false).should == nil
Complex(:sym, :sym, exception: false).should == nil
Complex(0, :sym, exception: false).should == nil
end
end
describe "and non-numeric String arguments" do
it "swallows an error" do
Complex("a", "b", exception: false).should == nil
Complex("a", 0, exception: false).should == nil
Complex(0, "b", exception: false).should == nil
end
end
ruby_bug "#15525", "2.6"..."2.6.1" do
describe "and nil arguments" do
it "swallows an error" do
Complex(nil, exception: false).should == nil
Complex(0, nil, exception: false).should == nil
Complex(nil, 0, exception: false).should == nil
end
end
end
end
end
end

Просмотреть файл

@ -299,6 +299,31 @@ describe :kernel_float, shared: true do
c = Complex(2, 3)
lambda { @object.send(:Float, c) }.should raise_error(RangeError)
end
ruby_version_is "2.6" do
describe "when passed exception: false" do
describe "and valid input" 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.23", exception: false).should == 1.23
end
end
describe "and invalid input" do
it "swallows an error" do
@object.send(:Float, "abc", exception: false).should == nil
@object.send(:Float, :sym, exception: false).should == nil
end
end
describe "and nil" do
it "swallows it" do
@object.send(:Float, nil, exception: false).should == nil
end
end
end
end
end
describe "Kernel.Float" do

Просмотреть файл

@ -99,6 +99,65 @@ describe :kernel_integer, shared: true do
it "raises a FloatDomainError when passed Infinity" do
lambda { Integer(infinity_value) }.should raise_error(FloatDomainError)
end
ruby_version_is "2.6" do
describe "when passed exception: false" do
describe "and to_i returns a value that is not an Integer" do
it "swallows an error" do
obj = mock("object")
obj.should_receive(:to_i).and_return("1")
Integer(obj, exception: false).should == nil
end
end
describe "and no to_int or to_i methods exist" do
it "swallows an error" do
obj = mock("object")
Integer(obj, exception: false).should == nil
end
end
describe "and to_int returns nil and no to_i exists" do
it "swallows an error" do
obj = mock("object")
obj.should_receive(:to_i).and_return(nil)
Integer(obj, exception: false).should == nil
end
end
ruby_bug "#15525", "2.6"..."2.6.1" do
describe "and passed NaN" do
it "swallows an error" do
Integer(nan_value, exception: false).should == nil
end
end
describe "and passed Infinity" do
it "swallows an error" do
Integer(infinity_value, exception: false).should == nil
end
end
end
describe "and passed nil" do
it "swallows an error" do
Integer(nil, exception: false).should == nil
end
end
describe "and passed a String that contains numbers" do
it "normally parses it and returns an Integer" do
Integer("42", exception: false).should == 42
end
end
describe "and passed a String that can't be converted to an Integer" do
it "swallows an error" do
Integer("abc", exception: false).should == nil
end
end
end
end
end
describe "Integer() given a String", shared: true do
@ -189,6 +248,34 @@ describe "Integer() given a String", shared: true do
lambda { Integer("") }.should raise_error(ArgumentError)
end
ruby_version_is "2.6" do
describe "when passed exception: false" do
describe "and multiple leading -s" do
it "swallows an error" do
Integer("---1", exception: false).should == nil
end
end
describe "and multiple trailing -s" do
it "swallows an error" do
Integer("1---", exception: false).should == nil
end
end
describe "and an argument that contains a period" do
it "swallows an error" do
Integer("0.0", exception: false).should == nil
end
end
describe "and an empty string" do
it "swallows an error" do
Integer("", exception: false).should == nil
end
end
end
end
it "parses the value as 0 if the string consists of a single zero character" do
Integer("0").should == 0
end
@ -508,6 +595,24 @@ describe "Integer() given a String and base", shared: true do
lambda { Integer(98, 15) }.should raise_error(ArgumentError)
end
end
ruby_version_is "2.6" do
describe "when passed exception: false" do
describe "and valid argument" do
it "returns an Integer number" do
Integer("100", 10, exception: false).should == 100
Integer("100", 2, exception: false).should == 4
end
end
describe "and invalid argument" do
it "swallows an error" do
Integer("999", 2, exception: false).should == nil
Integer("abc", 10, exception: false).should == nil
end
end
end
end
end
describe :kernel_Integer, shared: true do

Просмотреть файл

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

Просмотреть файл

@ -30,9 +30,8 @@ describe :kernel_load, shared: true do
it "loads a file that recursively requires itself" do
path = File.expand_path "recursive_require_fixture.rb", CODE_LOADING_DIR
-> {
$VERBOSE = true
@object.load(path).should be_true
}.should complain(/circular require considered harmful/)
}.should complain(/circular require considered harmful/, verbose: true)
ScratchPad.recorded.should == [:loaded, :loaded]
end

Просмотреть файл

@ -225,9 +225,8 @@ describe :kernel_require, shared: true do
it "loads a file that recursively requires itself" do
path = File.expand_path "recursive_require_fixture.rb", CODE_LOADING_DIR
-> {
$VERBOSE = true
@object.require(path).should be_true
}.should complain(/circular require considered harmful/)
}.should complain(/circular require considered harmful/, verbose: true)
ScratchPad.recorded.should == [:loaded]
end
end

Просмотреть файл

@ -0,0 +1,101 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative '../proc/shared/compose'
ruby_version_is "2.6" do
describe "Method#<<" do
it "returns a Proc that is the composition of self and the passed Proc" do
succ = MethodSpecs::Composition.new.method(:succ)
upcase = proc { |s| s.upcase }
(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
(pow_2 << double).lambda?.should == true
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
describe "Method#>>" do
it "returns a Proc that is the composition of self and the passed Proc" do
upcase = proc { |s| s.upcase }
succ = MethodSpecs::Composition.new.method(:succ)
(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 == 8
(double_method >> pow_2_proc).call(2).should == 16
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).lambda?.should == true
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

Просмотреть файл

@ -181,4 +181,29 @@ module MethodSpecs
end
end
class Composition
def upcase(s)
s.upcase
end
def succ(s)
s.succ
end
def pow_2(n)
n * n
end
def double(n)
n + n
end
def inc(n)
n + 1
end
def mul(n, m)
n * m
end
end
end

Просмотреть файл

@ -138,9 +138,8 @@ describe "Module#attr" do
it "with a boolean argument emits a warning when $VERBOSE is true" do
lambda {
$VERBOSE = true
Class.new { attr :foo, true }
}.should complain(/boolean argument is obsoleted/)
}.should complain(/boolean argument is obsoleted/, verbose: true)
end
ruby_version_is ''...'2.5' do

Просмотреть файл

@ -582,9 +582,8 @@ describe "Module#autoload" do
end
-> {
$VERBOSE = true
Kernel.require fixture(__FILE__, "autoload_during_require.rb")
}.should_not complain
}.should_not complain(verbose: true)
ModuleSpecs::Autoload::AutoloadDuringRequire.should be_kind_of(Class)
end

Просмотреть файл

@ -46,4 +46,55 @@ describe "Module#method_defined?" do
c.method_defined?(o).should == true
end
ruby_version_is "2.6" do
# works as method_defined?(method_name)
describe "when passed true as a second optional argument" do
it "performs a lookup in ancestors" do
ModuleSpecs::Child.method_defined?(:public_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?(:private_child, true).should == false
# Defined in Parent
ModuleSpecs::Child.method_defined?(:public_parent, true).should == true
ModuleSpecs::Child.method_defined?(:protected_parent, true).should == true
ModuleSpecs::Child.method_defined?(:private_parent, true).should == false
# Defined in Module
ModuleSpecs::Child.method_defined?(:public_module, true).should == true
ModuleSpecs::Child.method_defined?(:protected_module, true).should == true
ModuleSpecs::Child.method_defined?(:private_module, true).should == false
# Defined in SuperModule
ModuleSpecs::Child.method_defined?(:public_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
end
end
describe "when passed false as a second optional argument" do
it "checks only the class itself" do
ModuleSpecs::Child.method_defined?(:public_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?(:private_child, false).should == false
# Defined in Parent
ModuleSpecs::Child.method_defined?(:public_parent, false).should == false
ModuleSpecs::Child.method_defined?(:protected_parent, false).should == false
ModuleSpecs::Child.method_defined?(:private_parent, false).should == false
# Defined in Module
ModuleSpecs::Child.method_defined?(:public_module, false).should == false
ModuleSpecs::Child.method_defined?(:protected_module, false).should == false
ModuleSpecs::Child.method_defined?(:private_module, false).should == false
# Defined in SuperModule
ModuleSpecs::Child.method_defined?(:public_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
end
end
end
end

Просмотреть файл

@ -69,4 +69,54 @@ describe "Module#private_method_defined?" do
def str.to_str() 'private_3' end
ModuleSpecs::CountsMixin.private_method_defined?(str).should == true
end
ruby_version_is "2.6" do
describe "when passed true as a second optional argument" do
it "performs a lookup in ancestors" do
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?(:accessor_method, true).should == false
ModuleSpecs::Child.private_method_defined?(:private_child, true).should == true
# Defined in Parent
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?(:private_parent, true).should == true
# Defined in Module
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?(:private_module, true).should == true
# Defined in SuperModule
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?(:private_super_module, true).should == true
end
end
describe "when passed false as a second optional argument" do
it "checks only the class itself" do
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?(:accessor_method, false).should == false
ModuleSpecs::Child.private_method_defined?(:private_child, false).should == true
# Defined in Parent
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?(:private_parent, false).should == false
# Defined in Module
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?(:private_module, false).should == false
# Defined in SuperModule
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?(:private_super_module, false).should == false
end
end
end
end

Просмотреть файл

@ -69,4 +69,54 @@ describe "Module#protected_method_defined?" do
str.should_receive(:to_str).and_return("protected_3")
ModuleSpecs::CountsMixin.protected_method_defined?(str).should == true
end
ruby_version_is "2.6" do
describe "when passed true as a second optional argument" do
it "performs a lookup in ancestors" do
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?(:accessor_method, true).should == false
ModuleSpecs::Child.protected_method_defined?(:private_child, true).should == false
# Defined in Parent
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?(:private_parent, true).should == false
# Defined in Module
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?(:private_module, true).should == false
# Defined in SuperModule
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?(:private_super_module, true).should == false
end
end
describe "when passed false as a second optional argument" do
it "checks only the class itself" do
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?(:accessor_method, false).should == false
ModuleSpecs::Child.protected_method_defined?(:private_child, false).should == false
# Defined in Parent
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?(:private_parent, false).should == false
# Defined in Module
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?(:private_module, false).should == false
# Defined in SuperModule
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?(:private_super_module, false).should == false
end
end
end
end

Просмотреть файл

@ -425,6 +425,24 @@ describe "Module#refine" do
end
end
ruby_version_is "" ... "2.6" do
it "is not honored by Kernel#public_send" do
refinement = Module.new do
refine ModuleSpecs::ClassWithFoo do
def foo; "foo from refinement"; end
end
end
result = nil
Module.new do
using refinement
result = ModuleSpecs::ClassWithFoo.new.public_send :foo
end
result.should == "foo"
end
end
ruby_version_is "2.6" do
it "is honored by Kernel#public_send" do
refinement = Module.new do
@ -561,6 +579,45 @@ describe "Module#refine" do
result.should == true
end
end
ruby_version_is ""..."2.6" do
it "is not honored by &" do
refinement = Module.new do
refine String do
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
ruby_version_is "2.6" do
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
context "when super is called in a refinement" do

Просмотреть файл

@ -0,0 +1,19 @@
require_relative '../../spec_helper'
ruby_version_is "2.6" do
describe "NilClass#=~" do
it "returns nil matching any object" do
o = Object.new
suppress_warning do
(o =~ /Object/).should be_nil
(o =~ 'Object').should be_nil
(o =~ Object).should be_nil
(o =~ Object.new).should be_nil
(o =~ nil).should be_nil
(o =~ false).should be_nil
(o =~ true).should be_nil
end
end
end
end

Просмотреть файл

@ -61,6 +61,20 @@ describe "Numeric#step" do
end
end
end
describe "type" do
ruby_version_is ""..."2.6" do
it "returns an instance of Enumerator" do
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

Просмотреть файл

@ -0,0 +1,94 @@
require_relative '../../spec_helper'
require_relative 'shared/compose'
ruby_version_is "2.6" do
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 == 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).lambda?.should == false
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
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).lambda?.should == false
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
end
end
end

Просмотреть файл

@ -0,0 +1,47 @@
describe :proc_compose, shared: true do
ruby_version_is "2.6"..."2.7" do
it "raises NoMethodError when called if passed not callable object" do
not_callable = Object.new
composed = @object.call.send(@method, not_callable)
-> {
composed.call('a')
}.should raise_error(NoMethodError, /undefined method `call' for/)
end
it "when called does not try to coerce argument with #to_proc" do
succ = Object.new
def succ.to_proc(s); s.succ; end
composed = @object.call.send(@method, succ)
-> {
composed.call('a')
}.should raise_error(NoMethodError, /undefined method `call' for/)
end
end
ruby_version_is "2.7" do # https://bugs.ruby-lang.org/issues/15428
it "raises TypeError if passed not callable object" do
lhs = @object.call
not_callable = Object.new
-> {
lhs.send(@method, not_callable)
}.should raise_error(TypeError, "callable object is expected")
end
it "does not try to coerce argument with #to_proc" do
lhs = @object.call
succ = Object.new
def succ.to_proc(s); s.succ; end
-> {
lhs.send(@method, succ)
}.should raise_error(TypeError, "callable object is expected")
end
end
end

Просмотреть файл

@ -0,0 +1 @@
stdin

Просмотреть файл

@ -8,10 +8,10 @@ end
describe :process_spawn_does_not_close_std_streams, shared: true do
it "does not close STDIN" do
code = "STDOUT.puts STDIN.read(0).inspect"
code = "puts STDIN.read"
cmd = "Process.wait Process.spawn(#{ruby_cmd(code).inspect}, #{@options.inspect})"
ruby_exe(cmd, args: "> #{@name}")
File.binread(@name).should == %[""#{newline}]
ruby_exe(cmd, args: "< #{fixture(__FILE__, "in.txt")} > #{@name}")
File.binread(@name).should == %[stdin#{newline}]
end
it "does not close STDOUT" do
@ -530,7 +530,35 @@ describe "Process.spawn" do
File.read(@name).should == "glarkbang"
end
# :close_others
platform_is_not :windows do
context "defaults :close_others to" do
ruby_version_is ""..."2.6" do
it "true" do
IO.pipe do |r, w|
w.close_on_exec = false
code = "begin; IO.new(#{w.fileno}).close; rescue Errno::EBADF; puts 'not inherited'; end"
Process.wait Process.spawn(ruby_cmd(code), :out => @name)
File.read(@name).should == "not inherited\n"
end
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
context "when passed close_others: true" do
before :each do
@options = { close_others: true }

Просмотреть файл

@ -9,12 +9,20 @@ describe "Range#===" do
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)
lambda 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::Custom.new(0)..RangeSpecs::Custom.new(10)
(range === RangeSpecs::Custom.new(2)).should == true
range = RangeSpecs::WithoutSucc.new(0)..RangeSpecs::WithoutSucc.new(10)
(range === RangeSpecs::WithoutSucc.new(2)).should == true
end
end
end

Просмотреть файл

@ -40,6 +40,28 @@ module RangeSpecs
end
end
class WithoutSucc
include Comparable
attr_reader :n
def initialize(n)
@n = n
end
def eql?(other)
inspect.eql? other.inspect
end
alias :== :eql?
def inspect
"WithoutSucc(#{@n})"
end
def <=>(other)
@n <=> other.n
end
end
class Xs < Custom # represent a string of 'x's
def succ
Xs.new(@length + 1)

Просмотреть файл

@ -42,4 +42,30 @@ describe "Range.new" do
-> { Range.new(a, b) }.should raise_error(RangeSpecs::ComparisonError)
end
end
describe "endless range" do
it "does not allow range without left boundary" do
-> { Range.new(nil, 1) }.should raise_error(ArgumentError, /bad value for range/)
end
ruby_version_is ""..."2.6" do
it "does not allow range without right boundary" do
-> { Range.new(1, nil) }.should raise_error(ArgumentError, /bad value for range/)
end
end
ruby_version_is "2.6" do
it "allows endless right boundary" do
range = Range.new(1, nil)
range.end.should == nil
end
it "distinguishes ranges with included and excluded right boundary" do
range_exclude = Range.new(1, nil, true)
range_include = Range.new(1, nil, false)
range_exclude.should_not == range_include
end
end
end
end

Просмотреть файл

@ -0,0 +1,18 @@
require_relative '../../spec_helper'
ruby_version_is "2.6" do
describe "Range#%" do
it "works as a Range#step" do
aseq = (1..10) % 2
aseq.class.should == Enumerator::ArithmeticSequence
aseq.begin.should == 1
aseq.end.should == 10
aseq.step.should == 2
aseq.to_a.should == [1, 3, 5, 7, 9]
end
it "produces an arithmetic sequence with a percent sign in #inspect" do
((1..10) % 2).inspect.should == "((1..10).%(2))"
end
end
end

Просмотреть файл

@ -90,4 +90,64 @@ describe :range_cover, shared: true do
end
end
end
ruby_version_is "2.6" do
context "range argument" do
it "accepts range argument" do
(0..10).send(@method, (3..7)).should be_true
(0..10).send(@method, (3..15)).should be_false
(0..10).send(@method, (-2..7)).should be_false
(1.1..7.9).send(@method, (2.5..6.5)).should be_true
(1.1..7.9).send(@method, (2.5..8.5)).should be_false
(1.1..7.9).send(@method, (0.5..6.5)).should be_false
('c'..'i').send(@method, ('d'..'f')).should be_true
('c'..'i').send(@method, ('d'..'z')).should be_false
('c'..'i').send(@method, ('a'..'f')).should be_false
range_10_100 = RangeSpecs::TenfoldSucc.new(10)..RangeSpecs::TenfoldSucc.new(100)
range_20_90 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(90)
range_20_110 = RangeSpecs::TenfoldSucc.new(20)..RangeSpecs::TenfoldSucc.new(110)
range_0_90 = RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(90)
range_10_100.send(@method, range_20_90).should be_true
range_10_100.send(@method, range_20_110).should be_false
range_10_100.send(@method, range_0_90).should be_false
end
it "supports boundaries of different comparable types" do
(0..10).send(@method, (3.1..7.9)).should be_true
(0..10).send(@method, (3.1..15.9)).should be_false
(0..10).send(@method, (-2.1..7.9)).should be_false
end
it "returns false if types are not comparable" do
(0..10).send(@method, ('a'..'z')).should be_false
(0..10).send(@method, (RangeSpecs::TenfoldSucc.new(0)..RangeSpecs::TenfoldSucc.new(100))).should be_false
end
it "honors exclusion of right boundary (:exclude_end option)" do
# Integer
(0..10).send(@method, (0..10)).should be_true
(0...10).send(@method, (0...10)).should be_true
(0..10).send(@method, (0...10)).should be_true
(0...10).send(@method, (0..10)).should be_false
(0...11).send(@method, (0..10)).should be_true
(0..10).send(@method, (0...11)).should be_true
# Float
(0..10.1).send(@method, (0..10.1)).should be_true
(0...10.1).send(@method, (0...10.1)).should be_true
(0..10.1).send(@method, (0...10.1)).should be_true
(0...10.1).send(@method, (0..10.1)).should be_false
(0...11.1).send(@method, (0..10.1)).should be_true
(0..10.1).send(@method, (0...11.1)).should be_false
end
end
end
end

Просмотреть файл

@ -1,21 +1,10 @@
require_relative '../../spec_helper'
describe "Range#step" do
step_enum_class = Enumerator
ruby_version_is "2.6" do
step_enum_class = Enumerator::ArithmeticSequence
end
before :each do
ScratchPad.record []
end
it "returns an #{step_enum_class} when no block is given" do
enum = (1..10).step(4)
enum.should be_an_instance_of(step_enum_class)
enum.to_a.should eql([1, 5, 9])
end
it "returns self" do
r = 1..2
r.step { }.should equal(r)
@ -268,7 +257,7 @@ describe "Range#step" do
end
describe "when no block is given" do
describe "returned #{step_enum_class}" do
describe "returned Enumerator" do
describe "size" do
it "raises a TypeError if step does not respond to #to_int" do
obj = mock("Range#step non-integer")
@ -363,6 +352,28 @@ describe "Range#step" do
enum.size.should == nil
end
end
describe "type" do
ruby_version_is ""..."2.6" do
it "returns an instance of Enumerator" do
(1..10).step.class.should == Enumerator
end
end
ruby_version_is "2.6" do
context "when both begin and end are numerics" do
it "returns an instance of Enumerator::ArithmeticSequence" do
(1..10).step.class.should == Enumerator::ArithmeticSequence
end
end
context "when begin and end are not numerics" do
it "returns an instance of Enumerator" do
("a".."z").step.class.should == Enumerator
end
end
end
end
end
end
end

Просмотреть файл

@ -411,5 +411,17 @@ describe "String#split with Regexp" do
returned_object.should == "chunky bacon"
a.should == ["Chunky", "Bacon"]
end
describe "for a String subclass" do
a = []
StringSpecs::MyString.new("a|b").split("|") { |str| a << str }
first, last = a
first.should be_an_instance_of(StringSpecs::MyString)
first.should == "a"
last.should be_an_instance_of(StringSpecs::MyString)
last.should == "b"
end
end
end

Просмотреть файл

@ -14,10 +14,45 @@ describe "Struct#to_h" do
end
ruby_version_is "2.6" do
it "converts [key, value] pairs returned by the block to a hash" do
car = StructClasses::Car.new('Ford', 'Ranger')
h = car.to_h {|k, v| [k.to_s, "#{v}".downcase]}
h.should == {"make" => "ford", "model" => "ranger", "year" => ""}
context "with block" do
it "converts [key, value] pairs returned by the block to a hash" do
car = StructClasses::Car.new('Ford', 'Ranger')
h = car.to_h { |k, v| [k.to_s, "#{v}".downcase] }
h.should == { "make" => "ford", "model" => "ranger", "year" => "" }
end
it "raises ArgumentError if block returns longer or shorter array" do
-> do
StructClasses::Car.new.to_h { |k, v| [k.to_s, "#{v}".downcase, 1] }
end.should raise_error(ArgumentError, /element has wrong array length/)
-> do
StructClasses::Car.new.to_h { |k, v| [k] }
end.should raise_error(ArgumentError, /element has wrong array length/)
end
it "raises TypeError if block returns something other than Array" do
-> do
StructClasses::Car.new.to_h { |k, v| "not-array" }
end.should raise_error(TypeError, /wrong element type String/)
end
it "coerces returned pair to Array with #to_ary" do
x = mock('x')
x.stub!(:to_ary).and_return([:b, 'b'])
StructClasses::Car.new.to_h { |k| x }.should == { :b => 'b' }
end
it "does not coerce returned pair to Array with #to_a" do
x = mock('x')
x.stub!(:to_a).and_return([:b, 'b'])
-> do
StructClasses::Car.new.to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject/)
end
end
end
end

Просмотреть файл

@ -0,0 +1,22 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
ruby_version_is "2.6" do
describe "#eval_script" do
ScratchPad.record []
script = <<-CODE
def foo
p :hello
end
CODE
TracePoint.new(:script_compiled) do |e|
ScratchPad << e.eval_script
end.enable do
eval script
end
ScratchPad.recorded.should == [script]
end
end

Просмотреть файл

@ -0,0 +1,23 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
ruby_version_is "2.6" do
describe "#instruction_sequence" do
ScratchPad.record []
script = <<-CODE
def foo
p :hello
end
CODE
TracePoint.new(:script_compiled) do |e|
ScratchPad << e.instruction_sequence
end.enable do
eval script
end
ScratchPad.recorded.size.should == 1
ScratchPad.recorded[0].class.should == RubyVM::InstructionSequence
end
end

Просмотреть файл

@ -713,3 +713,35 @@ describe "Module#public_constant marked constants" do
end
end
end
describe 'Allowed characters' do
it 'allows not ASCII characters in the middle of a name' do
mod = Module.new
mod.const_set("BBἍBB", 1)
eval("mod::BBἍBB").should == 1
end
it 'does not allow not ASCII characters that cannot be upcased or lowercased at the beginning' do
-> do
Module.new.const_set("થBB", 1)
end.should raise_error(NameError, /wrong constant name/)
end
ruby_version_is ""..."2.6" do
it 'does not allow not ASCII upcased characters at the beginning' do
-> do
Module.new.const_set("ἍBB", 1)
end.should raise_error(NameError, /wrong constant name/)
end
end
ruby_version_is "2.6" do
it 'allows not ASCII upcased characters at the beginning' do
mod = Module.new
mod.const_set("ἍBB", 1)
eval("mod::ἍBB").should == 1
end
end
end

Просмотреть файл

@ -310,6 +310,18 @@ describe "The if expression" do
6.times(&b)
ScratchPad.recorded.should == [4, 5, 4, 5]
end
ruby_version_is "2.6" do
it 'is deprecated' do
i = 4
-> do
eval "ScratchPad << 'it works' if (i == 4)..(i == 7)"
end.should complain(/flip-flop is deprecated/)
ScratchPad.recorded.should == ['it works']
end
end
end
end

Просмотреть файл

@ -0,0 +1,19 @@
require_relative '../spec_helper'
require_relative 'fixtures/classes'
describe "Literal Ranges" do
it "creates range object" do
(1..10).should == Range.new(1, 10)
end
it "creates range with excluded right boundary" do
(1...10).should == Range.new(1, 10, true)
end
ruby_version_is "2.6" do
it "creates endless ranges" do
eval("(1..)").should == Range.new(1, nil)
eval("(1...)").should == Range.new(1, nil, true)
end
end
end

Просмотреть файл

@ -41,20 +41,30 @@ describe "The $SAFE variable" do
ruby_version_is ""..."2.6" do
it "cannot be set to values below 0" do
lambda {
proc {
$SAFE = -100
}.call
}.should raise_error(SecurityError, /tried to downgrade safe level from 0 to -100/)
lambda {
proc {
$SAFE = -100
}.call
}.should raise_error(SecurityError, /tried to downgrade safe level from 0 to -100/)
end
end
ruby_version_is "2.6" do
it "raises ArgumentError when set to values below 0" do
lambda {
proc {
$SAFE = -100
}.call
}.should raise_error(ArgumentError, "$SAFE should be >= 0")
end
end
it "cannot be set to values above 4" do
lambda {
proc {
$SAFE = 100
}.call
}.should raise_error(ArgumentError, /\$SAFE=2 to 4 are obsolete/)
lambda {
proc {
$SAFE = 100
}.call
}.should raise_error(ArgumentError, /\$SAFE=2 to 4 are obsolete/)
end
ruby_version_is ""..."2.6" do
@ -84,6 +94,36 @@ describe "The $SAFE variable" do
end
end
ruby_version_is "2.6" do
it "can be manually lowered" do
$SAFE = 1
$SAFE = 0
$SAFE.should == 0
end
it "is not Proc local" do
$SAFE.should == 0
proc {
$SAFE = 1
}.call
$SAFE.should == 1
end
it "is not lambda local" do
$SAFE.should == 0
lambda {
$SAFE = 1
}.call
$SAFE.should == 1
end
it "is global like regular global variables" do
Thread.new { $SAFE }.value.should == 0
$SAFE = 1
Thread.new { $SAFE }.value.should == 1
end
end
it "can be read when default from Thread#safe_level" do
Thread.current.safe_level.should == 0
end

Просмотреть файл

@ -758,3 +758,31 @@ describe "A local variable assigned only within a conditional block" do
end
end
end
describe 'Local variable shadowing' do
ruby_version_is ""..."2.6" do
it "leads to warning in verbose mode" do
-> do
eval <<-CODE
a = [1, 2, 3]
a.each { |a| a = 3 }
CODE
end.should complain(/shadowing outer local variable/, verbose: true)
end
end
ruby_version_is "2.6" do
it "does not warn in verbose mode" do
result = nil
-> do
eval <<-CODE
a = [1, 2, 3]
result = a.map { |a| a = 3 }
CODE
end.should_not complain(verbose: true)
result.should == [3, 3, 3]
end
end
end

Просмотреть файл

@ -14,9 +14,8 @@ describe "Net::HTTPGenericRequest#body_exist?" do
it "emits a warning" do
request = Net::HTTPGenericRequest.new("POST", true, false, "/some/path")
lambda {
$VERBOSE = true
request.body_exist?
}.should complain(/body_exist\? is obsolete/)
}.should complain(/body_exist\? is obsolete/, verbose: true)
end
end
end

Просмотреть файл

@ -15,8 +15,7 @@ describe "Net::HTTPHeader#initialize_http_header when passed Hash" do
it "complains about duplicate keys when in verbose mode" do
lambda do
$VERBOSE = true
@headers.initialize_http_header("My-Header" => "test", "my-header" => "another test")
end.should complain(/duplicated HTTP header/)
end.should complain(/duplicated HTTP header/, verbose: true)
end
end

Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,23 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#disjoint?" do
it "returns false when two Sets have at least one element in common" do
Set[1, 2].disjoint?(Set[2, 3]).should == false
end
it "returns true when two Sets have no element in common" do
Set[1, 2].disjoint?(Set[3, 4]).should == true
end
context "when comparing to a Set-like object" do
it "returns false when a Set has at least one element in common with a Set-like object" do
Set[1, 2].disjoint?(SetSpecs::SetLike.new([2, 3])).should be_false
end
it "returns true when a Set has no element in common with a Set-like object" do
Set[1, 2].disjoint?(SetSpecs::SetLike.new([3, 4])).should be_true
end
end
end

Просмотреть файл

@ -1,4 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#==" do
@ -23,4 +24,10 @@ describe "Set#==" do
set2 = Set[Set["c", "d"], Set["a", "b"], Set["e", "f"]]
set1.should == set2
end
context "when comparing to a Set-like object" do
it "returns true when a Set and a Set-like object contain the same elements" do
Set[1, 2, 3].should == SetSpecs::SetLike.new([1, 2, 3])
end
end
end

Просмотреть файл

@ -0,0 +1,31 @@
require 'set'
module SetSpecs
# This class is used to test the interaction of "Set-like" objects with real Sets
#
# These "Set-like" objects reply to is_a?(Set) with true and thus real Set objects are able to transparently
# interoperate with them in a duck-typing manner.
class SetLike
include Enumerable
def is_a?(klass)
super || klass == ::Set
end
def initialize(entries)
@entries = entries
end
def each(&block)
@entries.each(&block)
end
def inspect
"#<#{self.class}: {#{map(&:inspect).join(", ")}}>"
end
def size
@entries.size
end
end
end

Просмотреть файл

@ -1,4 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#flatten" do
@ -14,6 +15,12 @@ describe "Set#flatten" do
(set = Set[]) << set
lambda { set.flatten }.should raise_error(ArgumentError)
end
context "when Set contains a Set-like object" do
it "returns a copy of self with each included Set-like object flattened" do
Set[SetSpecs::SetLike.new([1])].flatten.should == Set[1]
end
end
end
describe "Set#flatten!" do
@ -37,4 +44,10 @@ describe "Set#flatten!" do
(set = Set[]) << set
lambda { set.flatten! }.should raise_error(ArgumentError)
end
context "when Set contains a Set-like object" do
it "flattens self, including Set-like objects" do
Set[SetSpecs::SetLike.new([1])].flatten!.should == Set[1]
end
end
end

Просмотреть файл

@ -0,0 +1,23 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#intersect?" do
it "returns true when two Sets have at least one element in common" do
Set[1, 2].intersect?(Set[2, 3]).should == true
end
it "returns false when two Sets have no element in common" do
Set[1, 2].intersect?(Set[3, 4]).should == false
end
context "when comparing to a Set-like object" do
it "returns true when a Set has at least one element in common with a Set-like object" do
Set[1, 2].intersect?(SetSpecs::SetLike.new([2, 3])).should be_true
end
it "returns false when a Set has no element in common with a Set-like object" do
Set[1, 2].intersect?(SetSpecs::SetLike.new([3, 4])).should be_false
end
end
end

Просмотреть файл

@ -1,4 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#proper_subset?" do
@ -31,4 +32,10 @@ describe "Set#proper_subset?" do
lambda { Set[].proper_subset?("test") }.should raise_error(ArgumentError)
lambda { Set[].proper_subset?(Object.new) }.should raise_error(ArgumentError)
end
context "when comparing to a Set-like object" do
it "returns true if passed a Set-like object that self is a proper subset of" do
Set[1, 2, 3].proper_subset?(SetSpecs::SetLike.new([1, 2, 3, 4])).should be_true
end
end
end

Просмотреть файл

@ -1,4 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#proper_superset?" do
@ -31,4 +32,10 @@ describe "Set#proper_superset?" do
lambda { Set[].proper_superset?("test") }.should raise_error(ArgumentError)
lambda { Set[].proper_superset?(Object.new) }.should raise_error(ArgumentError)
end
context "when comparing to a Set-like object" do
it "returns true if passed a Set-like object that self is a proper superset of" do
Set[1, 2, 3, 4].proper_superset?(SetSpecs::SetLike.new([1, 2, 3])).should be_true
end
end
end

Просмотреть файл

@ -1,4 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#subset?" do
@ -31,4 +32,10 @@ describe "Set#subset?" do
lambda { Set[].subset?("test") }.should raise_error(ArgumentError)
lambda { Set[].subset?(Object.new) }.should raise_error(ArgumentError)
end
context "when comparing to a Set-like object" do
it "returns true if passed a Set-like object that self is a subset of" do
Set[1, 2, 3].subset?(SetSpecs::SetLike.new([1, 2, 3, 4])).should be_true
end
end
end

Просмотреть файл

@ -1,4 +1,5 @@
require_relative '../../spec_helper'
require_relative 'fixtures/set_like'
require 'set'
describe "Set#superset?" do
@ -31,4 +32,10 @@ describe "Set#superset?" do
lambda { Set[].superset?("test") }.should raise_error(ArgumentError)
lambda { Set[].superset?(Object.new) }.should raise_error(ArgumentError)
end
context "when comparing to a Set-like object" do
it "returns true if passed a Set-like object that self is a superset of" do
Set[1, 2, 3, 4].superset?(SetSpecs::SetLike.new([1, 2, 3])).should be_true
end
end
end

Просмотреть файл

@ -8,13 +8,11 @@ describe "StringScanner#clear" do
it "warns in verbose mode that the method is obsolete" do
s = StringScanner.new("abc")
lambda {
$VERBOSE = true
s.clear
}.should complain(/clear.*obsolete.*terminate/)
}.should complain(/clear.*obsolete.*terminate/, verbose: true)
lambda {
$VERBOSE = false
s.clear
}.should_not complain
}.should_not complain(verbose: false)
end
end

Просмотреть файл

@ -8,13 +8,11 @@ describe "StringScanner#empty?" do
it "warns in verbose mode that the method is obsolete" do
s = StringScanner.new("abc")
lambda {
$VERBOSE = true
s.empty?
}.should complain(/empty?.*obsolete.*eos?/)
}.should complain(/empty?.*obsolete.*eos?/, verbose: true)
lambda {
$VERBOSE = false
s.empty?
}.should_not complain
}.should_not complain(verbose: false)
end
end

Просмотреть файл

@ -9,14 +9,12 @@ describe "StringScanner#getbyte" do
it "warns in verbose mode that the method is obsolete" do
s = StringScanner.new("abc")
lambda {
$VERBOSE = true
s.getbyte
}.should complain(/getbyte.*obsolete.*get_byte/)
}.should complain(/getbyte.*obsolete.*get_byte/, verbose: true)
lambda {
$VERBOSE = false
s.getbyte
}.should_not complain
}.should_not complain(verbose: false)
end
it_behaves_like :extract_range, :getbyte

Просмотреть файл

@ -8,13 +8,11 @@ describe "StringScanner#peep" do
it "warns in verbose mode that the method is obsolete" do
s = StringScanner.new("abc")
lambda {
$VERBOSE = true
s.peep(1)
}.should complain(/peep.*obsolete.*peek/)
}.should complain(/peep.*obsolete.*peek/, verbose: true)
lambda {
$VERBOSE = false
s.peep(1)
}.should_not complain
}.should_not complain(verbose: false)
end
end

Просмотреть файл

@ -8,13 +8,11 @@ describe "StringScanner#restsize" do
it "warns in verbose mode that the method is obsolete" do
s = StringScanner.new("abc")
lambda {
$VERBOSE = true
s.restsize
}.should complain(/restsize.*obsolete.*rest_size/)
}.should complain(/restsize.*obsolete.*rest_size/, verbose: true)
lambda {
$VERBOSE = false
s.restsize
}.should_not complain
}.should_not complain(verbose: false)
end
end

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше