summaryrefslogtreecommitdiff
path: root/spec/ruby/core
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core')
-rw-r--r--spec/ruby/core/array/difference_spec.rb2
-rw-r--r--spec/ruby/core/array/to_h_spec.rb39
-rw-r--r--spec/ruby/core/binding/fixtures/location.rb6
-rw-r--r--spec/ruby/core/binding/source_location_spec.rb11
-rw-r--r--spec/ruby/core/dir/children_spec.rb66
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb52
-rw-r--r--spec/ruby/core/enumerable/chain_spec.rb22
-rw-r--r--spec/ruby/core/enumerable/to_h_spec.rb44
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb19
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb20
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb19
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb22
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb22
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb19
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb19
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb15
-rw-r--r--spec/ruby/core/enumerator/chain/each_spec.rb17
-rw-r--r--spec/ruby/core/enumerator/chain/initialize_spec.rb33
-rw-r--r--spec/ruby/core/enumerator/chain/inspect_spec.rb16
-rw-r--r--spec/ruby/core/enumerator/chain/rewind_spec.rb53
-rw-r--r--spec/ruby/core/enumerator/chain/size_spec.rb24
-rw-r--r--spec/ruby/core/enumerator/each_spec.rb88
-rw-r--r--spec/ruby/core/enumerator/inject_spec.rb15
-rw-r--r--spec/ruby/core/enumerator/lazy/filter_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/new_spec.rb39
-rw-r--r--spec/ruby/core/enumerator/next_spec.rb25
-rw-r--r--spec/ruby/core/enumerator/plus_spec.rb35
-rw-r--r--spec/ruby/core/enumerator/rewind_spec.rb36
-rw-r--r--spec/ruby/core/env/filter_spec.rb15
-rw-r--r--spec/ruby/core/env/select_spec.rb32
-rw-r--r--spec/ruby/core/env/shared/select.rb32
-rw-r--r--spec/ruby/core/env/to_h_spec.rb54
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb37
-rw-r--r--spec/ruby/core/exception/key_error_spec.rb15
-rw-r--r--spec/ruby/core/exception/name_error_spec.rb11
-rw-r--r--spec/ruby/core/exception/no_method_error_spec.rb13
-rw-r--r--spec/ruby/core/file/open_spec.rb27
-rw-r--r--spec/ruby/core/hash/merge_spec.rb11
-rw-r--r--spec/ruby/core/hash/shared/update.rb12
-rw-r--r--spec/ruby/core/hash/to_h_spec.rb46
-rw-r--r--spec/ruby/core/io/ungetbyte_spec.rb9
-rw-r--r--spec/ruby/core/kernel/Complex_spec.rb48
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb25
-rw-r--r--spec/ruby/core/kernel/Integer_spec.rb105
-rw-r--r--spec/ruby/core/kernel/match_spec.rb8
-rw-r--r--spec/ruby/core/kernel/shared/load.rb3
-rw-r--r--spec/ruby/core/kernel/shared/require.rb3
-rw-r--r--spec/ruby/core/method/compose_spec.rb101
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb25
-rw-r--r--spec/ruby/core/module/attr_spec.rb3
-rw-r--r--spec/ruby/core/module/autoload_spec.rb3
-rw-r--r--spec/ruby/core/module/method_defined_spec.rb51
-rw-r--r--spec/ruby/core/module/private_method_defined_spec.rb50
-rw-r--r--spec/ruby/core/module/protected_method_defined_spec.rb50
-rw-r--r--spec/ruby/core/module/refine_spec.rb57
-rw-r--r--spec/ruby/core/nil/match_spec.rb19
-rw-r--r--spec/ruby/core/numeric/step_spec.rb14
-rw-r--r--spec/ruby/core/proc/compose_spec.rb94
-rw-r--r--spec/ruby/core/proc/shared/compose.rb47
-rw-r--r--spec/ruby/core/process/fixtures/in.txt1
-rw-r--r--spec/ruby/core/process/spawn_spec.rb34
-rw-r--r--spec/ruby/core/range/case_compare_spec.rb12
-rw-r--r--spec/ruby/core/range/fixtures/classes.rb22
-rw-r--r--spec/ruby/core/range/new_spec.rb26
-rw-r--r--spec/ruby/core/range/percent_spec.rb18
-rw-r--r--spec/ruby/core/range/shared/cover.rb60
-rw-r--r--spec/ruby/core/range/step_spec.rb35
-rw-r--r--spec/ruby/core/string/split_spec.rb12
-rw-r--r--spec/ruby/core/struct/to_h_spec.rb43
-rw-r--r--spec/ruby/core/tracepoint/eval_script_spec.rb22
-rw-r--r--spec/ruby/core/tracepoint/instruction_sequence_spec.rb23
75 files changed, 2049 insertions, 109 deletions
diff --git a/spec/ruby/core/array/difference_spec.rb b/spec/ruby/core/array/difference_spec.rb
index 33ea8e1f3c..a357657967 100644
--- a/spec/ruby/core/array/difference_spec.rb
+++ b/spec/ruby/core/array/difference_spec.rb
@@ -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]
diff --git a/spec/ruby/core/array/to_h_spec.rb b/spec/ruby/core/array/to_h_spec.rb
index e845d2c950..27a0b6112f 100644
--- a/spec/ruby/core/array/to_h_spec.rb
+++ b/spec/ruby/core/array/to_h_spec.rb
@@ -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
diff --git a/spec/ruby/core/binding/fixtures/location.rb b/spec/ruby/core/binding/fixtures/location.rb
new file mode 100644
index 0000000000..a78ae75731
--- /dev/null
+++ b/spec/ruby/core/binding/fixtures/location.rb
@@ -0,0 +1,6 @@
+module BindingSpecs
+ module LocationMethod
+ FILE_PATH = __FILE__
+ TEST_BINDING = binding
+ end
+end
diff --git a/spec/ruby/core/binding/source_location_spec.rb b/spec/ruby/core/binding/source_location_spec.rb
new file mode 100644
index 0000000000..e562bc65c8
--- /dev/null
+++ b/spec/ruby/core/binding/source_location_spec.rb
@@ -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
diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb
index 4bc64934b3..c6329b416f 100644
--- a/spec/ruby/core/dir/children_spec.rb
+++ b/spec/ruby/core/dir/children_spec.rb
@@ -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
diff --git a/spec/ruby/core/dir/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb
index 913b9cb96f..c04d212bfa 100644
--- a/spec/ruby/core/dir/each_child_spec.rb
+++ b/spec/ruby/core/dir/each_child_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerable/chain_spec.rb b/spec/ruby/core/enumerable/chain_spec.rb
new file mode 100644
index 0000000000..0e86a02905
--- /dev/null
+++ b/spec/ruby/core/enumerable/chain_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerable/to_h_spec.rb b/spec/ruby/core/enumerable/to_h_spec.rb
index 966325c736..f15ced122e 100644
--- a/spec/ruby/core/enumerable/to_h_spec.rb
+++ b/spec/ruby/core/enumerable/to_h_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb
new file mode 100644
index 0000000000..c8d91ebaec
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb
new file mode 100644
index 0000000000..d7edf3a21f
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb
new file mode 100644
index 0000000000..5a436e8167
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb
new file mode 100644
index 0000000000..7895f98047
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb
new file mode 100644
index 0000000000..8ce0ce0cd9
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb
new file mode 100644
index 0000000000..43c520d1f0
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb
new file mode 100644
index 0000000000..236f845f41
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb
new file mode 100644
index 0000000000..21e64a6b58
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb
new file mode 100644
index 0000000000..ebb20090fc
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb
new file mode 100644
index 0000000000..5a62d3f346
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb
new file mode 100644
index 0000000000..00403b0238
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb
new file mode 100644
index 0000000000..20a5cb6e7b
--- /dev/null
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/chain/each_spec.rb b/spec/ruby/core/enumerator/chain/each_spec.rb
new file mode 100644
index 0000000000..dab2c1cf1d
--- /dev/null
+++ b/spec/ruby/core/enumerator/chain/each_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/chain/initialize_spec.rb b/spec/ruby/core/enumerator/chain/initialize_spec.rb
new file mode 100644
index 0000000000..4ede1b8670
--- /dev/null
+++ b/spec/ruby/core/enumerator/chain/initialize_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/chain/inspect_spec.rb b/spec/ruby/core/enumerator/chain/inspect_spec.rb
new file mode 100644
index 0000000000..a644d88c6f
--- /dev/null
+++ b/spec/ruby/core/enumerator/chain/inspect_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/chain/rewind_spec.rb b/spec/ruby/core/enumerator/chain/rewind_spec.rb
new file mode 100644
index 0000000000..61b07b8c0a
--- /dev/null
+++ b/spec/ruby/core/enumerator/chain/rewind_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/chain/size_spec.rb b/spec/ruby/core/enumerator/chain/size_spec.rb
new file mode 100644
index 0000000000..42c31ac10b
--- /dev/null
+++ b/spec/ruby/core/enumerator/chain/size_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/each_spec.rb b/spec/ruby/core/enumerator/each_spec.rb
index e2a78a6a99..f66951851e 100644
--- a/spec/ruby/core/enumerator/each_spec.rb
+++ b/spec/ruby/core/enumerator/each_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/inject_spec.rb b/spec/ruby/core/enumerator/inject_spec.rb
deleted file mode 100644
index 326c7ed581..0000000000
--- a/spec/ruby/core/enumerator/inject_spec.rb
+++ /dev/null
@@ -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
diff --git a/spec/ruby/core/enumerator/lazy/filter_spec.rb b/spec/ruby/core/enumerator/lazy/filter_spec.rb
new file mode 100644
index 0000000000..2ababa69cc
--- /dev/null
+++ b/spec/ruby/core/enumerator/lazy/filter_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/new_spec.rb b/spec/ruby/core/enumerator/new_spec.rb
index 86d2d38022..170809dbc1 100644
--- a/spec/ruby/core/enumerator/new_spec.rb
+++ b/spec/ruby/core/enumerator/new_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/next_spec.rb b/spec/ruby/core/enumerator/next_spec.rb
index 1d3baf54d7..e0d3c0a39b 100644
--- a/spec/ruby/core/enumerator/next_spec.rb
+++ b/spec/ruby/core/enumerator/next_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/plus_spec.rb b/spec/ruby/core/enumerator/plus_spec.rb
new file mode 100644
index 0000000000..c9bae08b04
--- /dev/null
+++ b/spec/ruby/core/enumerator/plus_spec.rb
@@ -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
diff --git a/spec/ruby/core/enumerator/rewind_spec.rb b/spec/ruby/core/enumerator/rewind_spec.rb
index e846f63c49..2a83b7c6ee 100644
--- a/spec/ruby/core/enumerator/rewind_spec.rb
+++ b/spec/ruby/core/enumerator/rewind_spec.rb
@@ -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')
diff --git a/spec/ruby/core/env/filter_spec.rb b/spec/ruby/core/env/filter_spec.rb
new file mode 100644
index 0000000000..ba18a3b33b
--- /dev/null
+++ b/spec/ruby/core/env/filter_spec.rb
@@ -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
diff --git a/spec/ruby/core/env/select_spec.rb b/spec/ruby/core/env/select_spec.rb
index 9ccd27f3e7..c3a76f4434 100644
--- a/spec/ruby/core/env/select_spec.rb
+++ b/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
diff --git a/spec/ruby/core/env/shared/select.rb b/spec/ruby/core/env/shared/select.rb
new file mode 100644
index 0000000000..a0b46a775a
--- /dev/null
+++ b/spec/ruby/core/env/shared/select.rb
@@ -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
diff --git a/spec/ruby/core/env/to_h_spec.rb b/spec/ruby/core/env/to_h_spec.rb
index f6c796b4d6..81a17700e9 100644
--- a/spec/ruby/core/env/to_h_spec.rb
+++ b/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
diff --git a/spec/ruby/core/exception/full_message_spec.rb b/spec/ruby/core/exception/full_message_spec.rb
index f56282d67b..bc611c165b 100644
--- a/spec/ruby/core/exception/full_message_spec.rb
+++ b/spec/ruby/core/exception/full_message_spec.rb
@@ -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
diff --git a/spec/ruby/core/exception/key_error_spec.rb b/spec/ruby/core/exception/key_error_spec.rb
new file mode 100644
index 0000000000..ad280279d8
--- /dev/null
+++ b/spec/ruby/core/exception/key_error_spec.rb
@@ -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
diff --git a/spec/ruby/core/exception/name_error_spec.rb b/spec/ruby/core/exception/name_error_spec.rb
index a5810f178f..d0a810029b 100644
--- a/spec/ruby/core/exception/name_error_spec.rb
+++ b/spec/ruby/core/exception/name_error_spec.rb
@@ -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
diff --git a/spec/ruby/core/exception/no_method_error_spec.rb b/spec/ruby/core/exception/no_method_error_spec.rb
index 7839c080a8..28c3549562 100644
--- a/spec/ruby/core/exception/no_method_error_spec.rb
+++ b/spec/ruby/core/exception/no_method_error_spec.rb
@@ -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
diff --git a/spec/ruby/core/file/open_spec.rb b/spec/ruby/core/file/open_spec.rb
index c6a0b68233..c37e7316ba 100644
--- a/spec/ruby/core/file/open_spec.rb
+++ b/spec/ruby/core/file/open_spec.rb
@@ -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
diff --git a/spec/ruby/core/hash/merge_spec.rb b/spec/ruby/core/hash/merge_spec.rb
index 3af1ea6d4f..5ea70610be 100644
--- a/spec/ruby/core/hash/merge_spec.rb
+++ b/spec/ruby/core/hash/merge_spec.rb
@@ -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
diff --git a/spec/ruby/core/hash/shared/update.rb b/spec/ruby/core/hash/shared/update.rb
index be03ac019e..250c5ab440 100644
--- a/spec/ruby/core/hash/shared/update.rb
+++ b/spec/ruby/core/hash/shared/update.rb
@@ -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
diff --git a/spec/ruby/core/hash/to_h_spec.rb b/spec/ruby/core/hash/to_h_spec.rb
index 40bd0d06d2..d6eaac9f33 100644
--- a/spec/ruby/core/hash/to_h_spec.rb
+++ b/spec/ruby/core/hash/to_h_spec.rb
@@ -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
diff --git a/spec/ruby/core/io/ungetbyte_spec.rb b/spec/ruby/core/io/ungetbyte_spec.rb
index 2e51fb0298..f5f9a11be1 100644
--- a/spec/ruby/core/io/ungetbyte_spec.rb
+++ b/spec/ruby/core/io/ungetbyte_spec.rb
@@ -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
diff --git a/spec/ruby/core/kernel/Complex_spec.rb b/spec/ruby/core/kernel/Complex_spec.rb
index 44e4f44ada..e5435a56e6 100644
--- a/spec/ruby/core/kernel/Complex_spec.rb
+++ b/spec/ruby/core/kernel/Complex_spec.rb
@@ -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
diff --git a/spec/ruby/core/kernel/Float_spec.rb b/spec/ruby/core/kernel/Float_spec.rb
index 47d7d0816f..43daefa6aa 100644
--- a/spec/ruby/core/kernel/Float_spec.rb
+++ b/spec/ruby/core/kernel/Float_spec.rb
@@ -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
diff --git a/spec/ruby/core/kernel/Integer_spec.rb b/spec/ruby/core/kernel/Integer_spec.rb
index b79c827d31..72e33fc737 100644
--- a/spec/ruby/core/kernel/Integer_spec.rb
+++ b/spec/ruby/core/kernel/Integer_spec.rb
@@ -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
diff --git a/spec/ruby/core/kernel/match_spec.rb b/spec/ruby/core/kernel/match_spec.rb
index d5808b6ede..6dc1eb7de8 100644
--- a/spec/ruby/core/kernel/match_spec.rb
+++ b/spec/ruby/core/kernel/match_spec.rb
@@ -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
diff --git a/spec/ruby/core/kernel/shared/load.rb b/spec/ruby/core/kernel/shared/load.rb
index 0ce7d58d2c..b479b29399 100644
--- a/spec/ruby/core/kernel/shared/load.rb
+++ b/spec/ruby/core/kernel/shared/load.rb
@@ -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
diff --git a/spec/ruby/core/kernel/shared/require.rb b/spec/ruby/core/kernel/shared/require.rb
index a81a68088a..b502476bc3 100644
--- a/spec/ruby/core/kernel/shared/require.rb
+++ b/spec/ruby/core/kernel/shared/require.rb
@@ -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
diff --git a/spec/ruby/core/method/compose_spec.rb b/spec/ruby/core/method/compose_spec.rb
new file mode 100644
index 0000000000..aa0aded775
--- /dev/null
+++ b/spec/ruby/core/method/compose_spec.rb
@@ -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
diff --git a/spec/ruby/core/method/fixtures/classes.rb b/spec/ruby/core/method/fixtures/classes.rb
index 142cbd1bec..315672c6e0 100644
--- a/spec/ruby/core/method/fixtures/classes.rb
+++ b/spec/ruby/core/method/fixtures/classes.rb
@@ -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
diff --git a/spec/ruby/core/module/attr_spec.rb b/spec/ruby/core/module/attr_spec.rb
index 87bf8ea57f..b114b06b6e 100644
--- a/spec/ruby/core/module/attr_spec.rb
+++ b/spec/ruby/core/module/attr_spec.rb
@@ -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
diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb
index d6af169cff..b028dbc56c 100644
--- a/spec/ruby/core/module/autoload_spec.rb
+++ b/spec/ruby/core/module/autoload_spec.rb
@@ -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
diff --git a/spec/ruby/core/module/method_defined_spec.rb b/spec/ruby/core/module/method_defined_spec.rb
index 62e0db8ee6..f5203917b4 100644
--- a/spec/ruby/core/module/method_defined_spec.rb
+++ b/spec/ruby/core/module/method_defined_spec.rb
@@ -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
diff --git a/spec/ruby/core/module/private_method_defined_spec.rb b/spec/ruby/core/module/private_method_defined_spec.rb
index e00a8c8a9b..a3cf55852e 100644
--- a/spec/ruby/core/module/private_method_defined_spec.rb
+++ b/spec/ruby/core/module/private_method_defined_spec.rb
@@ -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
diff --git a/spec/ruby/core/module/protected_method_defined_spec.rb b/spec/ruby/core/module/protected_method_defined_spec.rb
index 8492a497d3..75e02e0433 100644
--- a/spec/ruby/core/module/protected_method_defined_spec.rb
+++ b/spec/ruby/core/module/protected_method_defined_spec.rb
@@ -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
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index 97ea0a706d..662d49205d 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -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
diff --git a/spec/ruby/core/nil/match_spec.rb b/spec/ruby/core/nil/match_spec.rb
new file mode 100644
index 0000000000..3f69312bfe
--- /dev/null
+++ b/spec/ruby/core/nil/match_spec.rb
@@ -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
diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb
index 1eb91aa1e5..96439927a4 100644
--- a/spec/ruby/core/numeric/step_spec.rb
+++ b/spec/ruby/core/numeric/step_spec.rb
@@ -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
diff --git a/spec/ruby/core/proc/compose_spec.rb b/spec/ruby/core/proc/compose_spec.rb
new file mode 100644
index 0000000000..f1befe658b
--- /dev/null
+++ b/spec/ruby/core/proc/compose_spec.rb
@@ -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
diff --git a/spec/ruby/core/proc/shared/compose.rb b/spec/ruby/core/proc/shared/compose.rb
new file mode 100644
index 0000000000..64338cada8
--- /dev/null
+++ b/spec/ruby/core/proc/shared/compose.rb
@@ -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
diff --git a/spec/ruby/core/process/fixtures/in.txt b/spec/ruby/core/process/fixtures/in.txt
new file mode 100644
index 0000000000..cf52303bdc
--- /dev/null
+++ b/spec/ruby/core/process/fixtures/in.txt
@@ -0,0 +1 @@
+stdin
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index 951941888b..bb55fe299b 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -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 }
diff --git a/spec/ruby/core/range/case_compare_spec.rb b/spec/ruby/core/range/case_compare_spec.rb
index 9a33c5b73b..37d8cc4677 100644
--- a/spec/ruby/core/range/case_compare_spec.rb
+++ b/spec/ruby/core/range/case_compare_spec.rb
@@ -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
diff --git a/spec/ruby/core/range/fixtures/classes.rb b/spec/ruby/core/range/fixtures/classes.rb
index b62704ca39..3a1df010b2 100644
--- a/spec/ruby/core/range/fixtures/classes.rb
+++ b/spec/ruby/core/range/fixtures/classes.rb
@@ -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)
diff --git a/spec/ruby/core/range/new_spec.rb b/spec/ruby/core/range/new_spec.rb
index 26ea12867d..c110687163 100644
--- a/spec/ruby/core/range/new_spec.rb
+++ b/spec/ruby/core/range/new_spec.rb
@@ -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
diff --git a/spec/ruby/core/range/percent_spec.rb b/spec/ruby/core/range/percent_spec.rb
new file mode 100644
index 0000000000..41badd4f72
--- /dev/null
+++ b/spec/ruby/core/range/percent_spec.rb
@@ -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
diff --git a/spec/ruby/core/range/shared/cover.rb b/spec/ruby/core/range/shared/cover.rb
index b2de86531d..7d2367d712 100644
--- a/spec/ruby/core/range/shared/cover.rb
+++ b/spec/ruby/core/range/shared/cover.rb
@@ -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
diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb
index cdf66e4565..818207974a 100644
--- a/spec/ruby/core/range/step_spec.rb
+++ b/spec/ruby/core/range/step_spec.rb
@@ -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
diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb
index b89a28c149..b451921c66 100644
--- a/spec/ruby/core/string/split_spec.rb
+++ b/spec/ruby/core/string/split_spec.rb
@@ -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
diff --git a/spec/ruby/core/struct/to_h_spec.rb b/spec/ruby/core/struct/to_h_spec.rb
index ddfbfbca61..b5f4e40701 100644
--- a/spec/ruby/core/struct/to_h_spec.rb
+++ b/spec/ruby/core/struct/to_h_spec.rb
@@ -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
diff --git a/spec/ruby/core/tracepoint/eval_script_spec.rb b/spec/ruby/core/tracepoint/eval_script_spec.rb
new file mode 100644
index 0000000000..8a153156d1
--- /dev/null
+++ b/spec/ruby/core/tracepoint/eval_script_spec.rb
@@ -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
diff --git a/spec/ruby/core/tracepoint/instruction_sequence_spec.rb b/spec/ruby/core/tracepoint/instruction_sequence_spec.rb
new file mode 100644
index 0000000000..50a9cd5722
--- /dev/null
+++ b/spec/ruby/core/tracepoint/instruction_sequence_spec.rb
@@ -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