diff options
Diffstat (limited to 'spec/ruby/core/array/shared')
-rw-r--r-- | spec/ruby/core/array/shared/clone.rb | 24 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/collect.rb | 63 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/index.rb | 4 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/inspect.rb | 32 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/intersection.rb | 3 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb | 25 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/join.rb | 85 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/keep_if.rb | 35 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/select.rb | 3 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/slice.rb | 455 | ||||
-rw-r--r-- | spec/ruby/core/array/shared/unshift.rb | 18 |
11 files changed, 507 insertions, 240 deletions
diff --git a/spec/ruby/core/array/shared/clone.rb b/spec/ruby/core/array/shared/clone.rb index 3c17b1f10f..035b45ec99 100644 --- a/spec/ruby/core/array/shared/clone.rb +++ b/spec/ruby/core/array/shared/clone.rb @@ -17,28 +17,4 @@ describe :array_clone, shared: true do b.should == a b.__id__.should_not == a.__id__ end - - ruby_version_is ''...'2.7' do - it "copies taint status from the original" do - a = [1, 2, 3, 4] - b = [1, 2, 3, 4] - a.taint - aa = a.send @method - bb = b.send @method - - aa.should.tainted? - bb.should_not.tainted? - end - - it "copies untrusted status from the original" do - a = [1, 2, 3, 4] - b = [1, 2, 3, 4] - a.untrust - aa = a.send @method - bb = b.send @method - - aa.should.untrusted? - bb.should_not.untrusted? - end - end end diff --git a/spec/ruby/core/array/shared/collect.rb b/spec/ruby/core/array/shared/collect.rb index d84432734a..030302ced6 100644 --- a/spec/ruby/core/array/shared/collect.rb +++ b/spec/ruby/core/array/shared/collect.rb @@ -1,4 +1,5 @@ require_relative '../../enumerable/shared/enumeratorized' +require_relative '../shared/iterable_and_tolerating_size_increasing' describe :array_collect, shared: true do it "returns a copy of array with each element replaced by the value returned by block" do @@ -42,24 +43,12 @@ describe :array_collect, shared: true do }.should raise_error(ArgumentError) end - ruby_version_is ''...'2.7' do - it "does not copy tainted status" do - a = [1, 2, 3] - a.taint - a.send(@method){|x| x}.tainted?.should be_false - end - - it "does not copy untrusted status" do - a = [1, 2, 3] - a.untrust - a.send(@method){|x| x}.untrusted?.should be_false - end - end - before :all do @object = [1, 2, 3, 4] end it_should_behave_like :enumeratorized_with_origin_size + + it_should_behave_like :array_iterable_and_tolerating_size_increasing end describe :array_collect_b, shared: true do @@ -96,23 +85,6 @@ describe :array_collect_b, shared: true do a.should == ["1!", "2!", "3!"] end - ruby_version_is ''...'2.7' do - it "keeps tainted status" do - a = [1, 2, 3] - a.taint - a.tainted?.should be_true - a.send(@method){|x| x} - a.tainted?.should be_true - end - - it "keeps untrusted status" do - a = [1, 2, 3] - a.untrust - a.send(@method){|x| x} - a.untrusted?.should be_true - end - end - describe "when frozen" do it "raises a FrozenError" do -> { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(FrozenError) @@ -133,8 +105,37 @@ describe :array_collect_b, shared: true do end end + it "does not truncate the array is the block raises an exception" do + a = [1, 2, 3] + begin + a.send(@method) { raise StandardError, 'Oops' } + rescue + end + + a.should == [1, 2, 3] + end + + it "only changes elements before error is raised, keeping the element which raised an error." do + a = [1, 2, 3, 4] + begin + a.send(@method) do |e| + case e + when 1 then -1 + when 2 then -2 + when 3 then raise StandardError, 'Oops' + else 0 + end + end + rescue StandardError + end + + a.should == [-1, -2, 3, 4] + end + before :all do @object = [1, 2, 3, 4] end it_should_behave_like :enumeratorized_with_origin_size + + it_should_behave_like :array_iterable_and_tolerating_size_increasing end diff --git a/spec/ruby/core/array/shared/index.rb b/spec/ruby/core/array/shared/index.rb index a9896554f2..a4a0adbab6 100644 --- a/spec/ruby/core/array/shared/index.rb +++ b/spec/ruby/core/array/shared/index.rb @@ -1,3 +1,5 @@ +require_relative '../shared/iterable_and_tolerating_size_increasing' + describe :array_index, shared: true do it "returns the index of the first element == to object" do x = mock('3') @@ -34,4 +36,6 @@ describe :array_index, shared: true do [].send(@method).should be_an_instance_of(Enumerator) end end + + it_should_behave_like :array_iterable_and_tolerating_size_increasing end diff --git a/spec/ruby/core/array/shared/inspect.rb b/spec/ruby/core/array/shared/inspect.rb index 736f8d946b..af5128c645 100644 --- a/spec/ruby/core/array/shared/inspect.rb +++ b/spec/ruby/core/array/shared/inspect.rb @@ -19,7 +19,7 @@ describe :array_inspect, shared: true do end it "does not call #to_s on a String returned from #inspect" do - str = "abc" + str = +"abc" str.should_not_receive(:to_s) [str].send(@method).should == '["abc"]' @@ -64,32 +64,6 @@ describe :array_inspect, shared: true do ArraySpecs.empty_recursive_array.send(@method).should == "[[...]]" end - ruby_version_is ''...'2.7' do - it "taints the result if the Array is non-empty and tainted" do - [1, 2].taint.send(@method).tainted?.should be_true - end - - it "does not taint the result if the Array is tainted but empty" do - [].taint.send(@method).tainted?.should be_false - end - - it "taints the result if an element is tainted" do - ["str".taint].send(@method).tainted?.should be_true - end - - it "untrusts the result if the Array is untrusted" do - [1, 2].untrust.send(@method).untrusted?.should be_true - end - - it "does not untrust the result if the Array is untrusted but empty" do - [].untrust.send(@method).untrusted?.should be_false - end - - it "untrusts the result if an element is untrusted" do - ["str".untrust].send(@method).untrusted?.should be_true - end - end - describe "with encoding" do before :each do @default_external_encoding = Encoding.default_external @@ -124,8 +98,8 @@ describe :array_inspect, shared: true do end it "does not raise if inspected result is not default external encoding" do - utf_16be = mock("utf_16be") - utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE)) + utf_16be = mock(+"utf_16be") + utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE)) [utf_16be].send(@method).should == '["utf_16be \u3042"]' end diff --git a/spec/ruby/core/array/shared/intersection.rb b/spec/ruby/core/array/shared/intersection.rb index 49849b08c2..0b4166ab63 100644 --- a/spec/ruby/core/array/shared/intersection.rb +++ b/spec/ruby/core/array/shared/intersection.rb @@ -11,7 +11,8 @@ describe :array_intersection, shared: true do end it "creates an array with elements in order they are first encountered" do - [ 1, 2, 3, 2, 5 ].send(@method, [ 5, 2, 3, 4 ]).should == [2, 3, 5] + [ 1, 2, 3, 2, 5, 6, 7, 8 ].send(@method, [ 5, 2, 3, 4 ]).should == [2, 3, 5] # array > other + [ 5, 2, 3, 4 ].send(@method, [ 1, 2, 3, 2, 5, 6, 7, 8 ]).should == [5, 2, 3] # array < other end it "does not modify the original Array" do diff --git a/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb b/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb new file mode 100644 index 0000000000..3e73bad44b --- /dev/null +++ b/spec/ruby/core/array/shared/iterable_and_tolerating_size_increasing.rb @@ -0,0 +1,25 @@ +describe :array_iterable_and_tolerating_size_increasing, shared: true do + before do + @value_to_return ||= -> _ { nil } + end + + it "tolerates increasing an array size during iteration" do + # The goal is to trigger potential reallocation of internal array storage, so we: + # - use elements of different types, starting with the less generic (Integer) + # - add reasonably big number of new elements (~ 100) + array = [1, 2, 3] # to test some methods we need several uniq elements + array_to_join = [:a, :b, :c] + (4..100).to_a + + ScratchPad.record [] + i = 0 + + array.send(@method) do |e| + ScratchPad << e + array << array_to_join[i] if i < array_to_join.size + i += 1 + @value_to_return.call(e) + end + + ScratchPad.recorded.should == [1, 2, 3] + array_to_join + end +end diff --git a/spec/ruby/core/array/shared/join.rb b/spec/ruby/core/array/shared/join.rb index c443d9a628..507b13e3c8 100644 --- a/spec/ruby/core/array/shared/join.rb +++ b/spec/ruby/core/array/shared/join.rb @@ -58,36 +58,6 @@ describe :array_join_with_default_separator, shared: true do -> { ArraySpecs.empty_recursive_array.send(@method) }.should raise_error(ArgumentError) end - ruby_version_is ''...'2.7' do - it "taints the result if the Array is tainted and non-empty" do - [1, 2].taint.send(@method).tainted?.should be_true - end - - it "does not taint the result if the Array is tainted but empty" do - [].taint.send(@method).tainted?.should be_false - end - - it "taints the result if the result of coercing an element is tainted" do - s = mock("taint") - s.should_receive(:to_s).and_return("str".taint) - [s].send(@method).tainted?.should be_true - end - - it "untrusts the result if the Array is untrusted and non-empty" do - [1, 2].untrust.send(@method).untrusted?.should be_true - end - - it "does not untrust the result if the Array is untrusted but empty" do - [].untrust.send(@method).untrusted?.should be_false - end - - it "untrusts the result if the result of coercing an element is untrusted" do - s = mock("untrust") - s.should_receive(:to_s).and_return("str".untrust) - [s].send(@method).untrusted?.should be_true - end - end - it "uses the first encoding when other strings are compatible" do ary1 = ArraySpecs.array_with_7bit_utf8_and_usascii_strings ary2 = ArraySpecs.array_with_usascii_and_7bit_utf8_strings @@ -114,17 +84,16 @@ describe :array_join_with_default_separator, shared: true do -> { ary_utf8_bad_binary.send(@method) }.should raise_error(EncodingError) end - ruby_version_is "2.7" do - context "when $, is not nil" do - before do - suppress_warning do - $, = '*' - end + context "when $, is not nil" do + before do + suppress_warning do + $, = '*' end + end - it "warns" do - -> { [].join }.should complain(/warning: \$, is set to non-nil value/) - end + it "warns" do + -> { [].join }.should complain(/warning: \$, is set to non-nil value/) + -> { [].join(nil) }.should complain(/warning: \$, is set to non-nil value/) end end end @@ -140,42 +109,4 @@ describe :array_join_with_string_separator, shared: true do [1, [2, [3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6" [1, [2, ArraySpecs::MyArray[3, 4], 5], 6].send(@method, ":").should == "1:2:3:4:5:6" end - - ruby_version_is ''...'2.7' do - describe "with a tainted separator" do - before :each do - @sep = ":".taint - end - - it "does not taint the result if the array is empty" do - [].send(@method, @sep).tainted?.should be_false - end - - it "does not taint the result if the array has only one element" do - [1].send(@method, @sep).tainted?.should be_false - end - - it "taints the result if the array has two or more elements" do - [1, 2].send(@method, @sep).tainted?.should be_true - end - end - - describe "with an untrusted separator" do - before :each do - @sep = ":".untrust - end - - it "does not untrust the result if the array is empty" do - [].send(@method, @sep).untrusted?.should be_false - end - - it "does not untrust the result if the array has only one element" do - [1].send(@method, @sep).untrusted?.should be_false - end - - it "untrusts the result if the array has two or more elements" do - [1, 2].send(@method, @sep).untrusted?.should be_true - end - end - end end diff --git a/spec/ruby/core/array/shared/keep_if.rb b/spec/ruby/core/array/shared/keep_if.rb index f26aff028c..43a047c0a7 100644 --- a/spec/ruby/core/array/shared/keep_if.rb +++ b/spec/ruby/core/array/shared/keep_if.rb @@ -1,4 +1,5 @@ require_relative '../../enumerable/shared/enumeratorized' +require_relative '../shared/iterable_and_tolerating_size_increasing' describe :keep_if, shared: true do it "deletes elements for which the block returns a false value" do @@ -56,5 +57,39 @@ describe :keep_if, shared: true do -> { @frozen.send(@method) { false } }.should raise_error(FrozenError) end end + + it "raises a FrozenError on a frozen array only during iteration if called without a block" do + enum = @frozen.send(@method) + -> { enum.each {} }.should raise_error(FrozenError) + end + end + + it "does not truncate the array is the block raises an exception" do + a = [1, 2, 3] + begin + a.send(@method) { raise StandardError, 'Oops' } + rescue + end + + a.should == [1, 2, 3] end + + it "only changes elements before error is raised, keeping the element which raised an error." do + a = [1, 2, 3, 4] + begin + a.send(@method) do |e| + case e + when 2 then false + when 3 then raise StandardError, 'Oops' + else true + end + end + rescue StandardError + end + + a.should == [1, 3, 4] + end + + @value_to_return = -> _ { true } + it_should_behave_like :array_iterable_and_tolerating_size_increasing end diff --git a/spec/ruby/core/array/shared/select.rb b/spec/ruby/core/array/shared/select.rb index 09101e8ab5..9c2cbf76c4 100644 --- a/spec/ruby/core/array/shared/select.rb +++ b/spec/ruby/core/array/shared/select.rb @@ -2,11 +2,14 @@ require_relative '../../../spec_helper' require_relative '../fixtures/classes' require_relative '../shared/enumeratorize' require_relative '../shared/keep_if' +require_relative '../shared/iterable_and_tolerating_size_increasing' require_relative '../../enumerable/shared/enumeratorized' describe :array_select, shared: true do it_should_behave_like :enumeratorize + it_should_behave_like :array_iterable_and_tolerating_size_increasing + before :each do @object = [1,2,3] end diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb index 6818badeda..d2866970a5 100644 --- a/spec/ruby/core/array/shared/slice.rb +++ b/spec/ruby/core/array/shared/slice.rb @@ -397,56 +397,28 @@ describe :array_slice, shared: true do @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] end - ruby_version_is ''...'3.0' do - it "returns a subclass instance with [n, m]" do - @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray) - end - - it "returns a subclass instance with [-n, m]" do - @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray) - end - - it "returns a subclass instance with [n..m]" do - @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray) - end - - it "returns a subclass instance with [n...m]" do - @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray) - end - - it "returns a subclass instance with [-n..-m]" do - @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray) - end - - it "returns a subclass instance with [-n...-m]" do - @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray) - end + it "returns a Array instance with [n, m]" do + @array.send(@method, 0, 2).should be_an_instance_of(Array) end - ruby_version_is '3.0' do - it "returns a Array instance with [n, m]" do - @array.send(@method, 0, 2).should be_an_instance_of(Array) - end - - it "returns a Array instance with [-n, m]" do - @array.send(@method, -3, 2).should be_an_instance_of(Array) - end + it "returns a Array instance with [-n, m]" do + @array.send(@method, -3, 2).should be_an_instance_of(Array) + end - it "returns a Array instance with [n..m]" do - @array.send(@method, 1..3).should be_an_instance_of(Array) - end + it "returns a Array instance with [n..m]" do + @array.send(@method, 1..3).should be_an_instance_of(Array) + end - it "returns a Array instance with [n...m]" do - @array.send(@method, 1...3).should be_an_instance_of(Array) - end + it "returns a Array instance with [n...m]" do + @array.send(@method, 1...3).should be_an_instance_of(Array) + end - it "returns a Array instance with [-n..-m]" do - @array.send(@method, -3..-1).should be_an_instance_of(Array) - end + it "returns a Array instance with [-n..-m]" do + @array.send(@method, -3..-1).should be_an_instance_of(Array) + end - it "returns a Array instance with [-n...-m]" do - @array.send(@method, -3...-1).should be_an_instance_of(Array) - end + it "returns a Array instance with [-n...-m]" do + @array.send(@method, -3...-1).should be_an_instance_of(Array) end it "returns an empty array when m == n with [m...n]" do @@ -517,44 +489,371 @@ describe :array_slice, shared: true do end it "raises a RangeError if passed a range with a bound that is too large" do - -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError) - -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError) - end - - ruby_version_is "2.6" do - it "can accept endless ranges" do - a = [0, 1, 2, 3, 4, 5] - a.send(@method, eval("(2..)")).should == [2, 3, 4, 5] - a.send(@method, eval("(2...)")).should == [2, 3, 4, 5] - a.send(@method, eval("(-2..)")).should == [4, 5] - a.send(@method, eval("(-2...)")).should == [4, 5] - a.send(@method, eval("(9..)")).should == nil - a.send(@method, eval("(9...)")).should == nil - a.send(@method, eval("(-9..)")).should == nil - a.send(@method, eval("(-9...)")).should == nil - end + array = [1, 2, 3, 4, 5, 6] + -> { array.send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError) + -> { array.send(@method, 0..bignum_value) }.should raise_error(RangeError) + end + + it "can accept endless ranges" do + a = [0, 1, 2, 3, 4, 5] + a.send(@method, eval("(2..)")).should == [2, 3, 4, 5] + a.send(@method, eval("(2...)")).should == [2, 3, 4, 5] + a.send(@method, eval("(-2..)")).should == [4, 5] + a.send(@method, eval("(-2...)")).should == [4, 5] + a.send(@method, eval("(9..)")).should == nil + a.send(@method, eval("(9...)")).should == nil + a.send(@method, eval("(-9..)")).should == nil + a.send(@method, eval("(-9...)")).should == nil end - ruby_version_is "2.7" do - it "can accept beginless ranges" do - a = [0, 1, 2, 3, 4, 5] - a.send(@method, eval("(..3)")).should == [0, 1, 2, 3] - a.send(@method, eval("(...3)")).should == [0, 1, 2] - a.send(@method, eval("(..-3)")).should == [0, 1, 2, 3] - a.send(@method, eval("(...-3)")).should == [0, 1, 2] - a.send(@method, eval("(..0)")).should == [0] - a.send(@method, eval("(...0)")).should == [] - a.send(@method, eval("(..9)")).should == [0, 1, 2, 3, 4, 5] - a.send(@method, eval("(...9)")).should == [0, 1, 2, 3, 4, 5] - a.send(@method, eval("(..-9)")).should == [] - a.send(@method, eval("(...-9)")).should == [] + describe "can be sliced with Enumerator::ArithmeticSequence" do + before :each do + @array = [0, 1, 2, 3, 4, 5] end - it "can accept nil...nil ranges" do - a = [0, 1, 2, 3, 4, 5] - a.send(@method, eval("(nil...nil)")).should == a - a.send(@method, eval("(...nil)")).should == a - a.send(@method, eval("(nil..)")).should == a + it "has endless range and positive steps" do + @array.send(@method, eval("(0..).step(1)")).should == [0, 1, 2, 3, 4, 5] + @array.send(@method, eval("(0..).step(2)")).should == [0, 2, 4] + @array.send(@method, eval("(0..).step(10)")).should == [0] + + @array.send(@method, eval("(2..).step(1)")).should == [2, 3, 4, 5] + @array.send(@method, eval("(2..).step(2)")).should == [2, 4] + @array.send(@method, eval("(2..).step(10)")).should == [2] + + @array.send(@method, eval("(-3..).step(1)")).should == [3, 4, 5] + @array.send(@method, eval("(-3..).step(2)")).should == [3, 5] + @array.send(@method, eval("(-3..).step(10)")).should == [3] + end + + it "has beginless range and positive steps" do + # end with zero index + @array.send(@method, (..0).step(1)).should == [0] + @array.send(@method, (...0).step(1)).should == [] + + @array.send(@method, (..0).step(2)).should == [0] + @array.send(@method, (...0).step(2)).should == [] + + @array.send(@method, (..0).step(10)).should == [0] + @array.send(@method, (...0).step(10)).should == [] + + # end with positive index + @array.send(@method, (..3).step(1)).should == [0, 1, 2, 3] + @array.send(@method, (...3).step(1)).should == [0, 1, 2] + + @array.send(@method, (..3).step(2)).should == [0, 2] + @array.send(@method, (...3).step(2)).should == [0, 2] + + @array.send(@method, (..3).step(10)).should == [0] + @array.send(@method, (...3).step(10)).should == [0] + + # end with negative index + @array.send(@method, (..-2).step(1)).should == [0, 1, 2, 3, 4,] + @array.send(@method, (...-2).step(1)).should == [0, 1, 2, 3] + + @array.send(@method, (..-2).step(2)).should == [0, 2, 4] + @array.send(@method, (...-2).step(2)).should == [0, 2] + + @array.send(@method, (..-2).step(10)).should == [0] + @array.send(@method, (...-2).step(10)).should == [0] end + + it "has endless range and negative steps" do + @array.send(@method, eval("(0..).step(-1)")).should == [0] + @array.send(@method, eval("(0..).step(-2)")).should == [0] + @array.send(@method, eval("(0..).step(-10)")).should == [0] + + @array.send(@method, eval("(2..).step(-1)")).should == [2, 1, 0] + @array.send(@method, eval("(2..).step(-2)")).should == [2, 0] + + @array.send(@method, eval("(-3..).step(-1)")).should == [3, 2, 1, 0] + @array.send(@method, eval("(-3..).step(-2)")).should == [3, 1] + end + + it "has closed range and positive steps" do + # start and end with 0 + @array.send(@method, eval("(0..0).step(1)")).should == [0] + @array.send(@method, eval("(0...0).step(1)")).should == [] + + @array.send(@method, eval("(0..0).step(2)")).should == [0] + @array.send(@method, eval("(0...0).step(2)")).should == [] + + @array.send(@method, eval("(0..0).step(10)")).should == [0] + @array.send(@method, eval("(0...0).step(10)")).should == [] + + # start and end with positive index + @array.send(@method, eval("(1..3).step(1)")).should == [1, 2, 3] + @array.send(@method, eval("(1...3).step(1)")).should == [1, 2] + + @array.send(@method, eval("(1..3).step(2)")).should == [1, 3] + @array.send(@method, eval("(1...3).step(2)")).should == [1] + + @array.send(@method, eval("(1..3).step(10)")).should == [1] + @array.send(@method, eval("(1...3).step(10)")).should == [1] + + # start with positive index, end with negative index + @array.send(@method, eval("(1..-2).step(1)")).should == [1, 2, 3, 4] + @array.send(@method, eval("(1...-2).step(1)")).should == [1, 2, 3] + + @array.send(@method, eval("(1..-2).step(2)")).should == [1, 3] + @array.send(@method, eval("(1...-2).step(2)")).should == [1, 3] + + @array.send(@method, eval("(1..-2).step(10)")).should == [1] + @array.send(@method, eval("(1...-2).step(10)")).should == [1] + + # start with negative index, end with positive index + @array.send(@method, eval("(-4..4).step(1)")).should == [2, 3, 4] + @array.send(@method, eval("(-4...4).step(1)")).should == [2, 3] + + @array.send(@method, eval("(-4..4).step(2)")).should == [2, 4] + @array.send(@method, eval("(-4...4).step(2)")).should == [2] + + @array.send(@method, eval("(-4..4).step(10)")).should == [2] + @array.send(@method, eval("(-4...4).step(10)")).should == [2] + + # start with negative index, end with negative index + @array.send(@method, eval("(-4..-2).step(1)")).should == [2, 3, 4] + @array.send(@method, eval("(-4...-2).step(1)")).should == [2, 3] + + @array.send(@method, eval("(-4..-2).step(2)")).should == [2, 4] + @array.send(@method, eval("(-4...-2).step(2)")).should == [2] + + @array.send(@method, eval("(-4..-2).step(10)")).should == [2] + @array.send(@method, eval("(-4...-2).step(10)")).should == [2] + end + + it "has closed range and negative steps" do + # start and end with 0 + @array.send(@method, eval("(0..0).step(-1)")).should == [0] + @array.send(@method, eval("(0...0).step(-1)")).should == [] + + @array.send(@method, eval("(0..0).step(-2)")).should == [0] + @array.send(@method, eval("(0...0).step(-2)")).should == [] + + @array.send(@method, eval("(0..0).step(-10)")).should == [0] + @array.send(@method, eval("(0...0).step(-10)")).should == [] + + # start and end with positive index + @array.send(@method, eval("(1..3).step(-1)")).should == [] + @array.send(@method, eval("(1...3).step(-1)")).should == [] + + @array.send(@method, eval("(1..3).step(-2)")).should == [] + @array.send(@method, eval("(1...3).step(-2)")).should == [] + + @array.send(@method, eval("(1..3).step(-10)")).should == [] + @array.send(@method, eval("(1...3).step(-10)")).should == [] + + # start with positive index, end with negative index + @array.send(@method, eval("(1..-2).step(-1)")).should == [] + @array.send(@method, eval("(1...-2).step(-1)")).should == [] + + @array.send(@method, eval("(1..-2).step(-2)")).should == [] + @array.send(@method, eval("(1...-2).step(-2)")).should == [] + + @array.send(@method, eval("(1..-2).step(-10)")).should == [] + @array.send(@method, eval("(1...-2).step(-10)")).should == [] + + # start with negative index, end with positive index + @array.send(@method, eval("(-4..4).step(-1)")).should == [] + @array.send(@method, eval("(-4...4).step(-1)")).should == [] + + @array.send(@method, eval("(-4..4).step(-2)")).should == [] + @array.send(@method, eval("(-4...4).step(-2)")).should == [] + + @array.send(@method, eval("(-4..4).step(-10)")).should == [] + @array.send(@method, eval("(-4...4).step(-10)")).should == [] + + # start with negative index, end with negative index + @array.send(@method, eval("(-4..-2).step(-1)")).should == [] + @array.send(@method, eval("(-4...-2).step(-1)")).should == [] + + @array.send(@method, eval("(-4..-2).step(-2)")).should == [] + @array.send(@method, eval("(-4...-2).step(-2)")).should == [] + + @array.send(@method, eval("(-4..-2).step(-10)")).should == [] + @array.send(@method, eval("(-4...-2).step(-10)")).should == [] + end + + it "has inverted closed range and positive steps" do + # start and end with positive index + @array.send(@method, eval("(3..1).step(1)")).should == [] + @array.send(@method, eval("(3...1).step(1)")).should == [] + + @array.send(@method, eval("(3..1).step(2)")).should == [] + @array.send(@method, eval("(3...1).step(2)")).should == [] + + @array.send(@method, eval("(3..1).step(10)")).should == [] + @array.send(@method, eval("(3...1).step(10)")).should == [] + + # start with negative index, end with positive index + @array.send(@method, eval("(-2..1).step(1)")).should == [] + @array.send(@method, eval("(-2...1).step(1)")).should == [] + + @array.send(@method, eval("(-2..1).step(2)")).should == [] + @array.send(@method, eval("(-2...1).step(2)")).should == [] + + @array.send(@method, eval("(-2..1).step(10)")).should == [] + @array.send(@method, eval("(-2...1).step(10)")).should == [] + + # start with positive index, end with negative index + @array.send(@method, eval("(4..-4).step(1)")).should == [] + @array.send(@method, eval("(4...-4).step(1)")).should == [] + + @array.send(@method, eval("(4..-4).step(2)")).should == [] + @array.send(@method, eval("(4...-4).step(2)")).should == [] + + @array.send(@method, eval("(4..-4).step(10)")).should == [] + @array.send(@method, eval("(4...-4).step(10)")).should == [] + + # start with negative index, end with negative index + @array.send(@method, eval("(-2..-4).step(1)")).should == [] + @array.send(@method, eval("(-2...-4).step(1)")).should == [] + + @array.send(@method, eval("(-2..-4).step(2)")).should == [] + @array.send(@method, eval("(-2...-4).step(2)")).should == [] + + @array.send(@method, eval("(-2..-4).step(10)")).should == [] + @array.send(@method, eval("(-2...-4).step(10)")).should == [] + end + + it "has range with bounds outside of array" do + # end is equal to array's length + @array.send(@method, (0..6).step(1)).should == [0, 1, 2, 3, 4, 5] + -> { @array.send(@method, (0..6).step(2)) }.should raise_error(RangeError) + + # end is greater than length with positive steps + @array.send(@method, (1..6).step(2)).should == [1, 3, 5] + @array.send(@method, (2..7).step(2)).should == [2, 4] + -> { @array.send(@method, (2..8).step(2)) }.should raise_error(RangeError) + + # begin is greater than length with negative steps + @array.send(@method, (6..1).step(-2)).should == [5, 3, 1] + @array.send(@method, (7..2).step(-2)).should == [5, 3] + -> { @array.send(@method, (8..2).step(-2)) }.should raise_error(RangeError) + end + + it "has endless range with start outside of array's bounds" do + @array.send(@method, eval("(6..).step(1)")).should == [] + @array.send(@method, eval("(7..).step(1)")).should == nil + + @array.send(@method, eval("(6..).step(2)")).should == [] + -> { @array.send(@method, eval("(7..).step(2)")) }.should raise_error(RangeError) + end + end + + it "can accept beginless ranges" do + a = [0, 1, 2, 3, 4, 5] + a.send(@method, (..3)).should == [0, 1, 2, 3] + a.send(@method, (...3)).should == [0, 1, 2] + a.send(@method, (..-3)).should == [0, 1, 2, 3] + a.send(@method, (...-3)).should == [0, 1, 2] + a.send(@method, (..0)).should == [0] + a.send(@method, (...0)).should == [] + a.send(@method, (..9)).should == [0, 1, 2, 3, 4, 5] + a.send(@method, (...9)).should == [0, 1, 2, 3, 4, 5] + a.send(@method, (..-9)).should == [] + a.send(@method, (...-9)).should == [] + end + + ruby_version_is "3.2" do + describe "can be sliced with Enumerator::ArithmeticSequence" do + it "with infinite/inverted ranges and negative steps" do + @array = [0, 1, 2, 3, 4, 5] + @array.send(@method, (2..).step(-1)).should == [2, 1, 0] + @array.send(@method, (2..).step(-2)).should == [2, 0] + @array.send(@method, (2..).step(-3)).should == [2] + @array.send(@method, (2..).step(-4)).should == [2] + + @array.send(@method, (-3..).step(-1)).should == [3, 2, 1, 0] + @array.send(@method, (-3..).step(-2)).should == [3, 1] + @array.send(@method, (-3..).step(-3)).should == [3, 0] + @array.send(@method, (-3..).step(-4)).should == [3] + @array.send(@method, (-3..).step(-5)).should == [3] + + @array.send(@method, (..0).step(-1)).should == [5, 4, 3, 2, 1, 0] + @array.send(@method, (..0).step(-2)).should == [5, 3, 1] + @array.send(@method, (..0).step(-3)).should == [5, 2] + @array.send(@method, (..0).step(-4)).should == [5, 1] + @array.send(@method, (..0).step(-5)).should == [5, 0] + @array.send(@method, (..0).step(-6)).should == [5] + @array.send(@method, (..0).step(-7)).should == [5] + + @array.send(@method, (...0).step(-1)).should == [5, 4, 3, 2, 1] + @array.send(@method, (...0).step(-2)).should == [5, 3, 1] + @array.send(@method, (...0).step(-3)).should == [5, 2] + @array.send(@method, (...0).step(-4)).should == [5, 1] + @array.send(@method, (...0).step(-5)).should == [5] + @array.send(@method, (...0).step(-6)).should == [5] + + @array.send(@method, (...1).step(-1)).should == [5, 4, 3, 2] + @array.send(@method, (...1).step(-2)).should == [5, 3] + @array.send(@method, (...1).step(-3)).should == [5, 2] + @array.send(@method, (...1).step(-4)).should == [5] + @array.send(@method, (...1).step(-5)).should == [5] + + @array.send(@method, (..-5).step(-1)).should == [5, 4, 3, 2, 1] + @array.send(@method, (..-5).step(-2)).should == [5, 3, 1] + @array.send(@method, (..-5).step(-3)).should == [5, 2] + @array.send(@method, (..-5).step(-4)).should == [5, 1] + @array.send(@method, (..-5).step(-5)).should == [5] + @array.send(@method, (..-5).step(-6)).should == [5] + + @array.send(@method, (...-5).step(-1)).should == [5, 4, 3, 2] + @array.send(@method, (...-5).step(-2)).should == [5, 3] + @array.send(@method, (...-5).step(-3)).should == [5, 2] + @array.send(@method, (...-5).step(-4)).should == [5] + @array.send(@method, (...-5).step(-5)).should == [5] + + @array.send(@method, (4..1).step(-1)).should == [4, 3, 2, 1] + @array.send(@method, (4..1).step(-2)).should == [4, 2] + @array.send(@method, (4..1).step(-3)).should == [4, 1] + @array.send(@method, (4..1).step(-4)).should == [4] + @array.send(@method, (4..1).step(-5)).should == [4] + + @array.send(@method, (4...1).step(-1)).should == [4, 3, 2] + @array.send(@method, (4...1).step(-2)).should == [4, 2] + @array.send(@method, (4...1).step(-3)).should == [4] + @array.send(@method, (4...1).step(-4)).should == [4] + + @array.send(@method, (-2..1).step(-1)).should == [4, 3, 2, 1] + @array.send(@method, (-2..1).step(-2)).should == [4, 2] + @array.send(@method, (-2..1).step(-3)).should == [4, 1] + @array.send(@method, (-2..1).step(-4)).should == [4] + @array.send(@method, (-2..1).step(-5)).should == [4] + + @array.send(@method, (-2...1).step(-1)).should == [4, 3, 2] + @array.send(@method, (-2...1).step(-2)).should == [4, 2] + @array.send(@method, (-2...1).step(-3)).should == [4] + @array.send(@method, (-2...1).step(-4)).should == [4] + + @array.send(@method, (4..-5).step(-1)).should == [4, 3, 2, 1] + @array.send(@method, (4..-5).step(-2)).should == [4, 2] + @array.send(@method, (4..-5).step(-3)).should == [4, 1] + @array.send(@method, (4..-5).step(-4)).should == [4] + @array.send(@method, (4..-5).step(-5)).should == [4] + + @array.send(@method, (4...-5).step(-1)).should == [4, 3, 2] + @array.send(@method, (4...-5).step(-2)).should == [4, 2] + @array.send(@method, (4...-5).step(-3)).should == [4] + @array.send(@method, (4...-5).step(-4)).should == [4] + + @array.send(@method, (-2..-5).step(-1)).should == [4, 3, 2, 1] + @array.send(@method, (-2..-5).step(-2)).should == [4, 2] + @array.send(@method, (-2..-5).step(-3)).should == [4, 1] + @array.send(@method, (-2..-5).step(-4)).should == [4] + @array.send(@method, (-2..-5).step(-5)).should == [4] + + @array.send(@method, (-2...-5).step(-1)).should == [4, 3, 2] + @array.send(@method, (-2...-5).step(-2)).should == [4, 2] + @array.send(@method, (-2...-5).step(-3)).should == [4] + @array.send(@method, (-2...-5).step(-4)).should == [4] + end + end + end + + it "can accept nil...nil ranges" do + a = [0, 1, 2, 3, 4, 5] + a.send(@method, eval("(nil...nil)")).should == a + a.send(@method, (...nil)).should == a + a.send(@method, eval("(nil..)")).should == a end end diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb index fc82e19e2a..4941e098f6 100644 --- a/spec/ruby/core/array/shared/unshift.rb +++ b/spec/ruby/core/array/shared/unshift.rb @@ -22,6 +22,11 @@ describe :array_unshift, shared: true do a.should == [3, 4] end + it "returns self" do + a = [1, 2, 3] + a.send(@method, "a").should.equal?(a) + end + it "quietly ignores unshifting nothing" do [].send(@method).should == [] end @@ -43,4 +48,17 @@ describe :array_unshift, shared: true do it "raises a FrozenError on a frozen array when the array would not be modified" do -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError) end + + # https://github.com/oracle/truffleruby/issues/2772 + it "doesn't rely on Array#[]= so it can be overridden" do + subclass = Class.new(Array) do + def []=(*) + raise "[]= is called" + end + end + + array = subclass.new + array.send(@method, 1) + array.should == [1] + end end |