diff options
Diffstat (limited to 'spec/ruby/core/range')
-rw-r--r-- | spec/ruby/core/range/bsearch_spec.rb | 44 | ||||
-rw-r--r-- | spec/ruby/core/range/case_compare_spec.rb | 6 | ||||
-rw-r--r-- | spec/ruby/core/range/clone_spec.rb | 26 | ||||
-rw-r--r-- | spec/ruby/core/range/cover_spec.rb | 4 | ||||
-rw-r--r-- | spec/ruby/core/range/dup_spec.rb | 4 | ||||
-rw-r--r-- | spec/ruby/core/range/frozen_spec.rb | 34 | ||||
-rw-r--r-- | spec/ruby/core/range/include_spec.rb | 4 | ||||
-rw-r--r-- | spec/ruby/core/range/initialize_spec.rb | 15 | ||||
-rw-r--r-- | spec/ruby/core/range/last_spec.rb | 6 | ||||
-rw-r--r-- | spec/ruby/core/range/max_spec.rb | 18 | ||||
-rw-r--r-- | spec/ruby/core/range/minmax_spec.rb | 24 | ||||
-rw-r--r-- | spec/ruby/core/range/new_spec.rb | 8 | ||||
-rw-r--r-- | spec/ruby/core/range/shared/cover_and_include.rb | 1 | ||||
-rw-r--r-- | spec/ruby/core/range/size_spec.rb | 87 | ||||
-rw-r--r-- | spec/ruby/core/range/step_spec.rb | 52 |
15 files changed, 218 insertions, 115 deletions
diff --git a/spec/ruby/core/range/bsearch_spec.rb b/spec/ruby/core/range/bsearch_spec.rb index 9c93671d85..5254ab756c 100644 --- a/spec/ruby/core/range/bsearch_spec.rb +++ b/spec/ruby/core/range/bsearch_spec.rb @@ -9,22 +9,30 @@ describe "Range#bsearch" do it_behaves_like :enumeratorized_with_unknown_size, :bsearch, (1..3) it "raises a TypeError if the block returns an Object" do - -> { (0..1).bsearch { Object.new } }.should raise_error(TypeError) + -> { (0..1).bsearch { Object.new } }.should raise_error(TypeError, "wrong argument type Object (must be numeric, true, false or nil)") end - it "raises a TypeError if the block returns a String" do - -> { (0..1).bsearch { "1" } }.should raise_error(TypeError) + it "raises a TypeError if the block returns a String and boundaries are Integer values" do + -> { (0..1).bsearch { "1" } }.should raise_error(TypeError, "wrong argument type String (must be numeric, true, false or nil)") + end + + it "raises a TypeError if the block returns a String and boundaries are Float values" do + -> { (0.0..1.0).bsearch { "1" } }.should raise_error(TypeError, "wrong argument type String (must be numeric, true, false or nil)") end it "raises a TypeError if the Range has Object values" do value = mock("range bsearch") r = Range.new value, value - -> { r.bsearch { true } }.should raise_error(TypeError) + -> { r.bsearch { true } }.should raise_error(TypeError, "can't do binary search for MockObject") end it "raises a TypeError if the Range has String values" do - -> { ("a".."e").bsearch { true } }.should raise_error(TypeError) + -> { ("a".."e").bsearch { true } }.should raise_error(TypeError, "can't do binary search for String") + end + + it "raises TypeError when non-Numeric begin/end and block not passed" do + -> { ("a".."e").bsearch }.should raise_error(TypeError, "can't do binary search for String") end context "with Integer values" do @@ -94,6 +102,10 @@ describe "Range#bsearch" do (4..2).bsearch { 0 }.should == nil (4..2).bsearch { -1 }.should == nil end + + it "returns enumerator when block not passed" do + (0...3).bsearch.kind_of?(Enumerator).should == true + end end context "with Float values" do @@ -156,7 +168,6 @@ describe "Range#bsearch" do it "returns nil if the block returns greater than zero for every element" do (0.3..3.0).bsearch { |x| x <=> -1 }.should be_nil - end it "returns nil if the block never returns zero" do @@ -213,6 +224,10 @@ describe "Range#bsearch" do (0...inf).bsearch { |x| x >= Float::MAX ? 0 : 1 }.should == Float::MAX end end + + it "returns enumerator when block not passed" do + (0.1...2.3).bsearch.kind_of?(Enumerator).should == true + end end context "with endless ranges and Integer values" do @@ -250,6 +265,10 @@ describe "Range#bsearch" do [1, 2, 3].should include(result) end end + + it "returns enumerator when block not passed" do + eval("(-2..)").bsearch.kind_of?(Enumerator).should == true + end end context "with endless ranges and Float values" do @@ -327,8 +346,11 @@ describe "Range#bsearch" do eval("(0.0...)").bsearch { 0 }.should != inf end end - end + it "returns enumerator when block not passed" do + eval("(0.1..)").bsearch.kind_of?(Enumerator).should == true + end + end context "with beginless ranges and Integer values" do context "with a block returning true or false" do @@ -361,6 +383,10 @@ describe "Range#bsearch" do [1, 2, 3].should include(result) end end + + it "returns enumerator when block not passed" do + (..10).bsearch.kind_of?(Enumerator).should == true + end end context "with beginless ranges and Float values" do @@ -432,5 +458,9 @@ describe "Range#bsearch" do (...inf).bsearch { |x| 3 - x }.should == 3 end end + + it "returns enumerator when block not passed" do + (..-0.1).bsearch.kind_of?(Enumerator).should == true + end end end diff --git a/spec/ruby/core/range/case_compare_spec.rb b/spec/ruby/core/range/case_compare_spec.rb index 4a3faa3163..65878aaabe 100644 --- a/spec/ruby/core/range/case_compare_spec.rb +++ b/spec/ruby/core/range/case_compare_spec.rb @@ -10,4 +10,10 @@ describe "Range#===" do it_behaves_like :range_cover_and_include, :=== it_behaves_like :range_cover, :=== + + ruby_bug "#19533", "3.2"..."3.3" do + it "returns true on any value if begin and end are both nil" do + (nil..nil).should === 1 + end + end end diff --git a/spec/ruby/core/range/clone_spec.rb b/spec/ruby/core/range/clone_spec.rb new file mode 100644 index 0000000000..cf6ce74da0 --- /dev/null +++ b/spec/ruby/core/range/clone_spec.rb @@ -0,0 +1,26 @@ +require_relative '../../spec_helper' + +describe "Range#clone" do + it "duplicates the range" do + original = (1..3) + copy = original.clone + copy.begin.should == 1 + copy.end.should == 3 + copy.should_not.exclude_end? + copy.should_not.equal? original + + original = ("a"..."z") + copy = original.clone + copy.begin.should == "a" + copy.end.should == "z" + copy.should.exclude_end? + copy.should_not.equal? original + end + + it "maintains the frozen state" do + (1..2).clone.frozen?.should == (1..2).frozen? + (1..).clone.frozen?.should == (1..).frozen? + Range.new(1, 2).clone.frozen?.should == Range.new(1, 2).frozen? + Class.new(Range).new(1, 2).clone.frozen?.should == Class.new(Range).new(1, 2).frozen? + end +end diff --git a/spec/ruby/core/range/cover_spec.rb b/spec/ruby/core/range/cover_spec.rb index fa881607e9..eb7cddc967 100644 --- a/spec/ruby/core/range/cover_spec.rb +++ b/spec/ruby/core/range/cover_spec.rb @@ -7,4 +7,8 @@ describe "Range#cover?" do it_behaves_like :range_cover_and_include, :cover? it_behaves_like :range_cover, :cover? it_behaves_like :range_cover_subrange, :cover? + + it "covers U+9995 in the range U+0999..U+9999" do + ("\u{999}".."\u{9999}").cover?("\u{9995}").should be_true + end end diff --git a/spec/ruby/core/range/dup_spec.rb b/spec/ruby/core/range/dup_spec.rb index 976d4fd1d0..fab3c3f1b2 100644 --- a/spec/ruby/core/range/dup_spec.rb +++ b/spec/ruby/core/range/dup_spec.rb @@ -2,10 +2,12 @@ require_relative '../../spec_helper' describe "Range#dup" do it "duplicates the range" do - copy = (1..3).dup + original = (1..3) + copy = original.dup copy.begin.should == 1 copy.end.should == 3 copy.should_not.exclude_end? + copy.should_not.equal?(original) copy = ("a"..."z").dup copy.begin.should == "a" diff --git a/spec/ruby/core/range/frozen_spec.rb b/spec/ruby/core/range/frozen_spec.rb index 298ffc87cb..8dab5e5339 100644 --- a/spec/ruby/core/range/frozen_spec.rb +++ b/spec/ruby/core/range/frozen_spec.rb @@ -2,26 +2,24 @@ require_relative '../../spec_helper' # There is no Range#frozen? method but this feels like the best place for these specs describe "Range#frozen?" do - ruby_version_is "3.0" do - it "is true for literal ranges" do - (1..2).should.frozen? - (1..).should.frozen? - (..1).should.frozen? - end + it "is true for literal ranges" do + (1..2).should.frozen? + (1..).should.frozen? + (..1).should.frozen? + end - it "is true for Range.new" do - Range.new(1, 2).should.frozen? - Range.new(1, nil).should.frozen? - Range.new(nil, 1).should.frozen? - end + it "is true for Range.new" do + Range.new(1, 2).should.frozen? + Range.new(1, nil).should.frozen? + Range.new(nil, 1).should.frozen? + end - it "is false for instances of a subclass of Range" do - sub_range = Class.new(Range).new(1, 2) - sub_range.should_not.frozen? - end + it "is false for instances of a subclass of Range" do + sub_range = Class.new(Range).new(1, 2) + sub_range.should_not.frozen? + end - it "is false for Range.allocate" do - Range.allocate.should_not.frozen? - end + it "is false for Range.allocate" do + Range.allocate.should_not.frozen? end end diff --git a/spec/ruby/core/range/include_spec.rb b/spec/ruby/core/range/include_spec.rb index b2c7a54545..277de205d1 100644 --- a/spec/ruby/core/range/include_spec.rb +++ b/spec/ruby/core/range/include_spec.rb @@ -7,4 +7,8 @@ require_relative 'shared/cover' describe "Range#include?" do it_behaves_like :range_cover_and_include, :include? it_behaves_like :range_include, :include? + + it "does not include U+9995 in the range U+0999..U+9999" do + ("\u{999}".."\u{9999}").include?("\u{9995}").should be_false + end end diff --git a/spec/ruby/core/range/initialize_spec.rb b/spec/ruby/core/range/initialize_spec.rb index 8a6ca65daa..c653caf0c6 100644 --- a/spec/ruby/core/range/initialize_spec.rb +++ b/spec/ruby/core/range/initialize_spec.rb @@ -27,18 +27,9 @@ describe "Range#initialize" do -> { @range.send(:initialize, 1, 3, 5, 7, 9) }.should raise_error(ArgumentError) end - ruby_version_is ""..."3.0" do - it "raises a NameError if called on an already initialized Range" do - -> { (0..1).send(:initialize, 1, 3) }.should raise_error(NameError) - -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(NameError) - end - end - - ruby_version_is "3.0" do - it "raises a FrozenError if called on an already initialized Range" do - -> { (0..1).send(:initialize, 1, 3) }.should raise_error(FrozenError) - -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(FrozenError) - end + it "raises a FrozenError if called on an already initialized Range" do + -> { (0..1).send(:initialize, 1, 3) }.should raise_error(FrozenError) + -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(FrozenError) end it "raises an ArgumentError if arguments don't respond to <=>" do diff --git a/spec/ruby/core/range/last_spec.rb b/spec/ruby/core/range/last_spec.rb index d7ef776b42..6698686dd5 100644 --- a/spec/ruby/core/range/last_spec.rb +++ b/spec/ruby/core/range/last_spec.rb @@ -8,6 +8,12 @@ describe "Range#last" do (1..5).last(3).should == [3, 4, 5] end + ruby_bug '#18994', '2.7'...'3.2' do + it "returns the specified number if elements for single element inclusive range" do + (1..1).last(1).should == [1] + end + end + it "returns an empty array for an empty Range" do (0...0).last(2).should == [] end diff --git a/spec/ruby/core/range/max_spec.rb b/spec/ruby/core/range/max_spec.rb index 6c9ada2a3c..a3bbc31e7d 100644 --- a/spec/ruby/core/range/max_spec.rb +++ b/spec/ruby/core/range/max_spec.rb @@ -50,17 +50,15 @@ describe "Range#max" do -> { eval("(1..)").max }.should raise_error(RangeError) end - ruby_version_is "3.0" do - it "returns the end point for beginless ranges" do - (..1).max.should == 1 - (..1.0).max.should == 1.0 - end + it "returns the end point for beginless ranges" do + (..1).max.should == 1 + (..1.0).max.should == 1.0 + end - it "raises for an exclusive beginless range" do - -> { - (...1).max - }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value') - end + it "raises for an exclusive beginless range" do + -> { + (...1).max + }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value') end end diff --git a/spec/ruby/core/range/minmax_spec.rb b/spec/ruby/core/range/minmax_spec.rb index b2b4fd61a1..6651ae3726 100644 --- a/spec/ruby/core/range/minmax_spec.rb +++ b/spec/ruby/core/range/minmax_spec.rb @@ -86,24 +86,22 @@ describe 'Range#minmax' do /cannot get the maximum of beginless range with custom comparison method|cannot get the minimum of beginless range/) end - ruby_bug "#17014", ""..."3.0" do - it 'should return nil pair if beginning and end are equal without iterating the range' do - @x.should_not_receive(:succ) + it 'should return nil pair if beginning and end are equal without iterating the range' do + @x.should_not_receive(:succ) - (@x...@x).minmax.should == [nil, nil] - end + (@x...@x).minmax.should == [nil, nil] + end - it 'should return nil pair if beginning is greater than end without iterating the range' do - @y.should_not_receive(:succ) + it 'should return nil pair if beginning is greater than end without iterating the range' do + @y.should_not_receive(:succ) - (@y...@x).minmax.should == [nil, nil] - end + (@y...@x).minmax.should == [nil, nil] + end - it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do - @x.should_receive(:succ).once.and_return(@y) + it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do + @x.should_receive(:succ).once.and_return(@y) - (@x...@y).minmax.should == [@x, @x] - end + (@x...@y).minmax.should == [@x, @x] end it 'should return the minimum and maximum values for a numeric range' do diff --git a/spec/ruby/core/range/new_spec.rb b/spec/ruby/core/range/new_spec.rb index 85e99babff..3cab887799 100644 --- a/spec/ruby/core/range/new_spec.rb +++ b/spec/ruby/core/range/new_spec.rb @@ -65,5 +65,13 @@ describe "Range.new" do range_exclude.should_not == range_include end + + it "creates a frozen range if the class is Range.class" do + Range.new(1, 2).should.frozen? + end + + it "does not create a frozen range if the class is not Range.class" do + Class.new(Range).new(1, 2).should_not.frozen? + end end end diff --git a/spec/ruby/core/range/shared/cover_and_include.rb b/spec/ruby/core/range/shared/cover_and_include.rb index 7028afaa89..f36a2cef8b 100644 --- a/spec/ruby/core/range/shared/cover_and_include.rb +++ b/spec/ruby/core/range/shared/cover_and_include.rb @@ -57,7 +57,6 @@ describe :range_cover_and_include, shared: true do it "returns true if argument is less than the last value of the range and greater than the first value" do (20..30).send(@method, 28).should be_true ('e'..'h').send(@method, 'g').should be_true - ("\u{999}".."\u{9999}").send @method, "\u{9995}" end it "returns true if argument is sole element in the range" do diff --git a/spec/ruby/core/range/size_spec.rb b/spec/ruby/core/range/size_spec.rb index 5462a1a5e1..a1fe3ce17d 100644 --- a/spec/ruby/core/range/size_spec.rb +++ b/spec/ruby/core/range/size_spec.rb @@ -4,41 +4,94 @@ describe "Range#size" do it "returns the number of elements in the range" do (1..16).size.should == 16 (1...16).size.should == 15 - - (1.0..16.0).size.should == 16 - (1.0...16.0).size.should == 15 - (1.0..15.9).size.should == 15 - (1.1..16.0).size.should == 15 - (1.1..15.9).size.should == 15 end it "returns 0 if last is less than first" do (16..0).size.should == 0 - (16.0..0.0).size.should == 0 - (Float::INFINITY..0).size.should == 0 end it 'returns Float::INFINITY for increasing, infinite ranges' do (0..Float::INFINITY).size.should == Float::INFINITY - (-Float::INFINITY..0).size.should == Float::INFINITY - (-Float::INFINITY..Float::INFINITY).size.should == Float::INFINITY end it 'returns Float::INFINITY for endless ranges if the start is numeric' do eval("(1..)").size.should == Float::INFINITY - eval("(0.5...)").size.should == Float::INFINITY end it 'returns nil for endless ranges if the start is not numeric' do eval("('z'..)").size.should == nil - eval("([]...)").size.should == nil end - it 'returns Float::INFINITY for all beginless ranges' do - (..1).size.should == Float::INFINITY - (...0.5).size.should == Float::INFINITY - (..nil).size.should == Float::INFINITY - (...'o').size.should == Float::INFINITY + ruby_version_is ""..."3.2" do + it 'returns Float::INFINITY for all beginless ranges' do + (..1).size.should == Float::INFINITY + (...0.5).size.should == Float::INFINITY + (..nil).size.should == Float::INFINITY + (...'o').size.should == Float::INFINITY + end + end + + ruby_version_is "3.2"..."3.4" do + it 'returns Float::INFINITY for all beginless ranges if the end is numeric' do + (..1).size.should == Float::INFINITY + (...0.5).size.should == Float::INFINITY + end + + it 'returns nil for all beginless ranges if the end is not numeric' do + (...'o').size.should == nil + end + + it 'returns nil if the start and the end is both nil' do + (nil..nil).size.should == nil + end + end + + ruby_version_is ""..."3.4" do + it "returns the number of elements in the range" do + (1.0..16.0).size.should == 16 + (1.0...16.0).size.should == 15 + (1.0..15.9).size.should == 15 + (1.1..16.0).size.should == 15 + (1.1..15.9).size.should == 15 + end + + it "returns 0 if last is less than first" do + (16.0..0.0).size.should == 0 + (Float::INFINITY..0).size.should == 0 + end + + it 'returns Float::INFINITY for increasing, infinite ranges' do + (-Float::INFINITY..0).size.should == Float::INFINITY + (-Float::INFINITY..Float::INFINITY).size.should == Float::INFINITY + end + + it 'returns Float::INFINITY for endless ranges if the start is numeric' do + eval("(0.5...)").size.should == Float::INFINITY + end + + it 'returns nil for endless ranges if the start is not numeric' do + eval("([]...)").size.should == nil + end + end + + ruby_version_is "3.4" do + it 'raises TypeError if a range is not iterable' do + -> { (1.0..16.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.0...16.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.0..15.9).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.1..16.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (1.1..15.9).size }.should raise_error(TypeError, /can't iterate from/) + -> { (16.0..0.0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (-Float::INFINITY..0).size }.should raise_error(TypeError, /can't iterate from/) + -> { (-Float::INFINITY..Float::INFINITY).size }.should raise_error(TypeError, /can't iterate from/) + -> { (..1).size }.should raise_error(TypeError, /can't iterate from/) + -> { (...0.5).size }.should raise_error(TypeError, /can't iterate from/) + -> { (..nil).size }.should raise_error(TypeError, /can't iterate from/) + -> { (...'o').size }.should raise_error(TypeError, /can't iterate from/) + -> { eval("(0.5...)").size }.should raise_error(TypeError, /can't iterate from/) + -> { eval("([]...)").size }.should raise_error(TypeError, /can't iterate from/) + end end it "returns nil if first and last are not Numeric" do diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb index 61ddc5205d..64ea3de4ed 100644 --- a/spec/ruby/core/range/step_spec.rb +++ b/spec/ruby/core/range/step_spec.rb @@ -377,48 +377,21 @@ describe "Range#step" do end describe "when no block is given" do - ruby_version_is "3.0" do - it "raises an ArgumentError if step is 0" do - -> { (-1..1).step(0) }.should raise_error(ArgumentError) - end + it "raises an ArgumentError if step is 0" do + -> { (-1..1).step(0) }.should raise_error(ArgumentError) end describe "returned Enumerator" do describe "size" do - ruby_version_is ""..."3.0" do - it "raises a TypeError if step does not respond to #to_int" do - obj = mock("Range#step non-integer") - enum = (1..2).step(obj) - -> { enum.size }.should raise_error(TypeError) - end - - it "raises a TypeError if #to_int does not return an Integer" do - obj = mock("Range#step non-integer") - obj.should_receive(:to_int).and_return("1") - enum = (1..2).step(obj) - - -> { enum.size }.should raise_error(TypeError) - end + it "raises a TypeError if step does not respond to #to_int" do + obj = mock("Range#step non-integer") + -> { (1..2).step(obj) }.should raise_error(TypeError) end - ruby_version_is "3.0" do - it "raises a TypeError if step does not respond to #to_int" do - obj = mock("Range#step non-integer") - -> { (1..2).step(obj) }.should raise_error(TypeError) - end - - it "raises a TypeError if #to_int does not return an Integer" do - obj = mock("Range#step non-integer") - obj.should_receive(:to_int).and_return("1") - -> { (1..2).step(obj) }.should raise_error(TypeError) - end - end - - ruby_version_is ""..."3.0" do - it "returns Float::INFINITY for zero step" do - (-1..1).step(0).size.should == Float::INFINITY - (-1..1).step(0.0).size.should == Float::INFINITY - end + it "raises a TypeError if #to_int does not return an Integer" do + obj = mock("Range#step non-integer") + obj.should_receive(:to_int).and_return("1") + -> { (1..2).step(obj) }.should raise_error(TypeError) end it "returns the ceil of range size divided by the number of steps" do @@ -474,10 +447,14 @@ describe "Range#step" do end end + # We use .take below to ensure the enumerator works + # because that's an Enumerable method and so it uses the Enumerator behavior + # not just a method overridden in Enumerator::ArithmeticSequence. describe "type" 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 + (1..10).step(3).take(4).should == [1, 4, 7, 10] end end @@ -490,10 +467,12 @@ describe "Range#step" do context "when range is endless" do it "returns an instance of Enumerator::ArithmeticSequence when begin is numeric" do (1..).step.class.should == Enumerator::ArithmeticSequence + (1..).step(2).take(3).should == [1, 3, 5] end it "returns an instance of Enumerator when begin is not numeric" do ("a"..).step.class.should == Enumerator + ("a"..).step(2).take(3).should == %w[a c e] end end @@ -506,6 +485,7 @@ describe "Range#step" do context "when begin and end are not numerics" do it "returns an instance of Enumerator" do ("a".."z").step.class.should == Enumerator + ("a".."z").step(3).take(4).should == %w[a d g j] end end end |