diff options
Diffstat (limited to 'spec/ruby/core/enumerator')
41 files changed, 784 insertions, 421 deletions
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb index c8d91ebaec..bd243fa0b5 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb @@ -1,11 +1,16 @@ 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 +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 + + context "with beginless" do + it "returns nil as begin of the sequence" do + (..10).step(1).begin.should == nil + (...10).step(1).begin.should == nil 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 index d7edf3a21f..d4fff3e01f 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/each_spec.rb @@ -1,19 +1,17 @@ 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 +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 "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 + it "returns self" do + @seq.each { |item| }.should equal(@seq) end end diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb index 5a436e8167..05429cac3e 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb @@ -1,11 +1,16 @@ 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 +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 + + context "with endless" do + it "returns nil as end of the sequence" do + (1..).step(1).end.should == nil + (1...).step(1).end.should == nil 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 index 7895f98047..77eed02d8b 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/eq_spec.rb @@ -1,20 +1,18 @@ 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) +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) + (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) + # 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 + ((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 diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb index 5be189e993..021fe7d90f 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb @@ -1,19 +1,17 @@ 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).should_not.exclude_end? - 10.step(1).should_not.exclude_end? - end +describe "Enumerator::ArithmeticSequence#exclude_end?" do + context "when created using Numeric#step" do + it "always returns false" do + 1.step(10).should_not.exclude_end? + 10.step(1).should_not.exclude_end? end + end - context "when created using Range#step" do - it "mirrors range.exclude_end?" do - (1...10).step.should.exclude_end? - (1..10).step.should_not.exclude_end? - end + context "when created using Range#step" do + it "mirrors range.exclude_end?" do + (1...10).step.should.exclude_end? + (1..10).step.should_not.exclude_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 index 43c520d1f0..ccd02be020 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/first_spec.rb @@ -1,11 +1,9 @@ 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 +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 diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb index 236f845f41..bdb308074b 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/hash_spec.rb @@ -1,22 +1,20 @@ 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) +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.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 + (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 + # 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 + ((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 diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb index 21e64a6b58..b73b49d272 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/inspect_spec.rb @@ -1,22 +1,20 @@ 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 +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))" + 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 + (1...10).step.inspect.should == "((1...10).step)" + (1...10).step(3).inspect.should == "((1...10).step(3))" 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 index ebb20090fc..31f982b7c4 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/last_spec.rb @@ -1,11 +1,9 @@ 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 +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 diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb index 7227581fb9..2015983826 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/new_spec.rb @@ -1,19 +1,17 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::ArithmeticSequence.new" do - it "is not defined" do - -> { - Enumerator::ArithmeticSequence.new - }.should raise_error(NoMethodError) - end +describe "Enumerator::ArithmeticSequence.new" do + it "is not defined" do + -> { + Enumerator::ArithmeticSequence.new + }.should raise_error(NoMethodError) end +end - describe "Enumerator::ArithmeticSequence.allocate" do - it "is not defined" do - -> { - Enumerator::ArithmeticSequence.allocate - }.should raise_error(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence') - end +describe "Enumerator::ArithmeticSequence.allocate" do + it "is not defined" do + -> { + Enumerator::ArithmeticSequence.allocate + }.should raise_error(TypeError, 'allocator undefined for Enumerator::ArithmeticSequence') end end diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb index 00403b0238..7e03edd961 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/size_spec.rb @@ -1,19 +1,17 @@ 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 +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 + 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 diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb index 8b00fd4309..c1f2d9173f 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb @@ -1,13 +1,11 @@ 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 +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.step(10).step.should == 1 - 1.step(10, 3).step.should == 3 - end + 1.step(10).step.should == 1 + 1.step(10, 3).step.should == 3 end end diff --git a/spec/ruby/core/enumerator/chain/each_spec.rb b/spec/ruby/core/enumerator/chain/each_spec.rb index ab4d355f22..cc93cbac60 100644 --- a/spec/ruby/core/enumerator/chain/each_spec.rb +++ b/spec/ruby/core/enumerator/chain/each_spec.rb @@ -1,17 +1,15 @@ 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 constituents as needed" do - a = EnumerableSpecs::EachCounter.new(:a, :b) - b = EnumerableSpecs::EachCounter.new(:c, :d) +describe "Enumerator::Chain#each" do + it "calls each on its constituents 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] + 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 diff --git a/spec/ruby/core/enumerator/chain/initialize_spec.rb b/spec/ruby/core/enumerator/chain/initialize_spec.rb index e5aa32fd02..daa30351d7 100644 --- a/spec/ruby/core/enumerator/chain/initialize_spec.rb +++ b/spec/ruby/core/enumerator/chain/initialize_spec.rb @@ -1,33 +1,31 @@ require_relative '../../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator::Chain#initialize" do - before :each do - @uninitialized = Enumerator::Chain.allocate - end +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 "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 "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 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 + 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 - -> { - @uninitialized.freeze.send(:initialize) - }.should raise_error(RuntimeError) - end + describe "on frozen instance" do + it "raises a FrozenError" do + -> { + @uninitialized.freeze.send(:initialize) + }.should raise_error(FrozenError) end end end diff --git a/spec/ruby/core/enumerator/chain/inspect_spec.rb b/spec/ruby/core/enumerator/chain/inspect_spec.rb index a644d88c6f..9b5a442b75 100644 --- a/spec/ruby/core/enumerator/chain/inspect_spec.rb +++ b/spec/ruby/core/enumerator/chain/inspect_spec.rb @@ -1,16 +1,18 @@ 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 +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 - 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 + it "returns a not initialized representation if #initialized is not called yet" do + Enumerator::Chain.allocate.inspect.should == "#<Enumerator::Chain: uninitialized>" end end diff --git a/spec/ruby/core/enumerator/chain/rewind_spec.rb b/spec/ruby/core/enumerator/chain/rewind_spec.rb index 951b364f07..5f51ce2cf1 100644 --- a/spec/ruby/core/enumerator/chain/rewind_spec.rb +++ b/spec/ruby/core/enumerator/chain/rewind_spec.rb @@ -1,53 +1,51 @@ 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 - @second = mock('obj') - @second.should_receive(:each).any_number_of_times.and_yield - @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 {} - -> { @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) - -> { @enum.each {} }.should raise_error(RuntimeError) - @enum.rewind - end +describe "Enumerator::Chain#rewind" do + before(:each) do + @obj = mock('obj') + @obj.should_receive(:each).any_number_of_times.and_yield + @second = mock('obj') + @second.should_receive(:each).any_number_of_times.and_yield + @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 {} + -> { @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) + -> { @enum.each {} }.should raise_error(RuntimeError) + @enum.rewind end end diff --git a/spec/ruby/core/enumerator/chain/size_spec.rb b/spec/ruby/core/enumerator/chain/size_spec.rb index 42c31ac10b..d85b88ee8b 100644 --- a/spec/ruby/core/enumerator/chain/size_spec.rb +++ b/spec/ruby/core/enumerator/chain/size_spec.rb @@ -1,24 +1,22 @@ 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 +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) - 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 + 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 diff --git a/spec/ruby/core/enumerator/each_spec.rb b/spec/ruby/core/enumerator/each_spec.rb index 99ac3120af..3af16e5587 100644 --- a/spec/ruby/core/enumerator/each_spec.rb +++ b/spec/ruby/core/enumerator/each_spec.rb @@ -10,41 +10,41 @@ describe "Enumerator#each" do @enum_with_arguments = object_each_with_arguments.to_enum(:each_with_arguments, :arg0, :arg1, :arg2) - @enum_with_yielder = Enumerator.new {|y| y.yield :ok} + @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] + [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 } + 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] + 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 } + each.to_enum(:peach).each { |e| e } end it "calls the method given in the constructor until it's exhausted" do each = mock('peach') each.should_receive(:peach).and_yield(1).and_yield(2).and_yield(3) acc = [] - each.to_enum(:peach).each {|e| acc << e } - acc.should == [1,2,3] + each.to_enum(:peach).each { |e| acc << e } + acc.should == [1, 2, 3] end it "raises a NoMethodError if the object doesn't respond to #each" do diff --git a/spec/ruby/core/enumerator/generator/initialize_spec.rb b/spec/ruby/core/enumerator/generator/initialize_spec.rb index f75c7d6f26..acc1174253 100644 --- a/spec/ruby/core/enumerator/generator/initialize_spec.rb +++ b/spec/ruby/core/enumerator/generator/initialize_spec.rb @@ -17,10 +17,10 @@ describe "Enumerator::Generator#initialize" do end describe "on frozen instance" do - it "raises a RuntimeError" do + it "raises a FrozenError" do -> { @uninitialized.freeze.send(:initialize) {} - }.should raise_error(RuntimeError) + }.should raise_error(FrozenError) end end end diff --git a/spec/ruby/core/enumerator/initialize_spec.rb b/spec/ruby/core/enumerator/initialize_spec.rb index 217af1d3bc..5e0256ca46 100644 --- a/spec/ruby/core/enumerator/initialize_spec.rb +++ b/spec/ruby/core/enumerator/initialize_spec.rb @@ -11,14 +11,6 @@ describe "Enumerator#initialize" do Enumerator.should have_private_instance_method(:initialize, false) end - ruby_version_is ''...'3.0' do - it "returns self when given an object" do - suppress_warning do - @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) - end - end - end - it "returns self when given a block" do @uninitialized.send(:initialize) {}.should equal(@uninitialized) end @@ -56,10 +48,10 @@ describe "Enumerator#initialize" do end describe "on frozen instance" do - it "raises a RuntimeError" do + it "raises a FrozenError" do -> { @uninitialized.freeze.send(:initialize) {} - }.should raise_error(RuntimeError) + }.should raise_error(FrozenError) end end end diff --git a/spec/ruby/core/enumerator/inspect_spec.rb b/spec/ruby/core/enumerator/inspect_spec.rb index 3bcf07e754..7e97864246 100644 --- a/spec/ruby/core/enumerator/inspect_spec.rb +++ b/spec/ruby/core/enumerator/inspect_spec.rb @@ -14,4 +14,9 @@ describe "Enumerator#inspect" do (1..3).each.each_slice(2).inspect.should == "#<Enumerator: #<Enumerator: 1..3:each>:each_slice(2)>" end end + + it "returns a not initialized representation if #initialized is not called yet" do + Enumerator.allocate.inspect.should == "#<Enumerator: uninitialized>" + Enumerator::Lazy.allocate.inspect.should == "#<Enumerator::Lazy: uninitialized>" + end end diff --git a/spec/ruby/core/enumerator/lazy/compact_spec.rb b/spec/ruby/core/enumerator/lazy/compact_spec.rb new file mode 100644 index 0000000000..e678bc71eb --- /dev/null +++ b/spec/ruby/core/enumerator/lazy/compact_spec.rb @@ -0,0 +1,16 @@ +require_relative '../../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is '3.1' do + describe "Enumerator::Lazy#compact" do + it 'returns array without nil elements' do + arr = [1, nil, 3, false, 5].to_enum.lazy.compact + arr.should be_an_instance_of(Enumerator::Lazy) + arr.force.should == [1, 3, false, 5] + end + + it "sets #size to nil" do + Enumerator::Lazy.new(Object.new, 100) {}.compact.size.should == nil + end + end +end diff --git a/spec/ruby/core/enumerator/lazy/eager_spec.rb b/spec/ruby/core/enumerator/lazy/eager_spec.rb index 30ba2dfe0e..592da4fd8c 100644 --- a/spec/ruby/core/enumerator/lazy/eager_spec.rb +++ b/spec/ruby/core/enumerator/lazy/eager_spec.rb @@ -1,29 +1,27 @@ require_relative '../../../spec_helper' -ruby_version_is "2.7" do - describe "Enumerator::Lazy#eager" do - it "returns a non-lazy Enumerator converted from the lazy enumerator" do - enum = [1, 2, 3].lazy +describe "Enumerator::Lazy#eager" do + it "returns a non-lazy Enumerator converted from the lazy enumerator" do + enum = [1, 2, 3].lazy - enum.class.should == Enumerator::Lazy - enum.eager.class.should == Enumerator - end + enum.class.should == Enumerator::Lazy + enum.eager.class.should == Enumerator + end - it "does not enumerate an enumerator" do - ScratchPad.record [] + it "does not enumerate an enumerator" do + ScratchPad.record [] - sequence = [1, 2, 3] - enum_lazy = Enumerator::Lazy.new(sequence) do |yielder, value| - yielder << value - ScratchPad << value - end + sequence = [1, 2, 3] + enum_lazy = Enumerator::Lazy.new(sequence) do |yielder, value| + yielder << value + ScratchPad << value + end - ScratchPad.recorded.should == [] - enum = enum_lazy.eager - ScratchPad.recorded.should == [] + ScratchPad.recorded.should == [] + enum = enum_lazy.eager + ScratchPad.recorded.should == [] - enum.map { |i| i }.should == [1, 2, 3] - ScratchPad.recorded.should == [1, 2, 3] - end + enum.map { |i| i }.should == [1, 2, 3] + ScratchPad.recorded.should == [1, 2, 3] end end diff --git a/spec/ruby/core/enumerator/lazy/filter_map_spec.rb b/spec/ruby/core/enumerator/lazy/filter_map_spec.rb index 3480af0865..99dd59cebe 100644 --- a/spec/ruby/core/enumerator/lazy/filter_map_spec.rb +++ b/spec/ruby/core/enumerator/lazy/filter_map_spec.rb @@ -3,14 +3,12 @@ require_relative '../../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "2.7" do - describe "Enumerator::Lazy#filter_map" do - it "maps only truthy results" do - (1..Float::INFINITY).lazy.filter_map { |i| i if i.odd? }.first(4).should == [1, 3, 5, 7] - end +describe "Enumerator::Lazy#filter_map" do + it "maps only truthy results" do + (1..Float::INFINITY).lazy.filter_map { |i| i if i.odd? }.first(4).should == [1, 3, 5, 7] + end - it "does not map false results" do - (1..Float::INFINITY).lazy.filter_map { |i| i.odd? ? i : false }.first(4).should == [1, 3, 5, 7] - end + it "does not map false results" do + (1..Float::INFINITY).lazy.filter_map { |i| i.odd? ? i : false }.first(4).should == [1, 3, 5, 7] end end diff --git a/spec/ruby/core/enumerator/lazy/filter_spec.rb b/spec/ruby/core/enumerator/lazy/filter_spec.rb index 2ababa69cc..43128241e0 100644 --- a/spec/ruby/core/enumerator/lazy/filter_spec.rb +++ b/spec/ruby/core/enumerator/lazy/filter_spec.rb @@ -1,8 +1,6 @@ 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 +describe "Enumerator::Lazy#filter" do + it_behaves_like :enumerator_lazy_select, :filter end diff --git a/spec/ruby/core/enumerator/lazy/initialize_spec.rb b/spec/ruby/core/enumerator/lazy/initialize_spec.rb index f23018d010..e1e0b1d608 100644 --- a/spec/ruby/core/enumerator/lazy/initialize_spec.rb +++ b/spec/ruby/core/enumerator/lazy/initialize_spec.rb @@ -56,8 +56,8 @@ describe "Enumerator::Lazy#initialize" do end describe "on frozen instance" do - it "raises a RuntimeError" do - -> { @uninitialized.freeze.send(:initialize, @receiver) {} }.should raise_error(RuntimeError) + it "raises a FrozenError" do + -> { @uninitialized.freeze.send(:initialize, @receiver) {} }.should raise_error(FrozenError) end end end diff --git a/spec/ruby/core/enumerator/lazy/lazy_spec.rb b/spec/ruby/core/enumerator/lazy/lazy_spec.rb index cde9b31066..0fb104e25a 100644 --- a/spec/ruby/core/enumerator/lazy/lazy_spec.rb +++ b/spec/ruby/core/enumerator/lazy/lazy_spec.rb @@ -16,6 +16,10 @@ describe "Enumerator::Lazy" do ] lazy_methods += [:chunk_while, :uniq] + ruby_version_is '3.1' do + lazy_methods += [:compact] + end + Enumerator::Lazy.instance_methods(false).should include(*lazy_methods) end end diff --git a/spec/ruby/core/enumerator/lazy/with_index_spec.rb b/spec/ruby/core/enumerator/lazy/with_index_spec.rb new file mode 100644 index 0000000000..a6b5c38777 --- /dev/null +++ b/spec/ruby/core/enumerator/lazy/with_index_spec.rb @@ -0,0 +1,36 @@ +# -*- encoding: us-ascii -*- + +require_relative '../../../spec_helper' +require_relative 'fixtures/classes' + +describe "Enumerator::Lazy#with_index" do + it "enumerates with an index" do + (0..Float::INFINITY).lazy.with_index.map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]] + end + + it "enumerates with an index starting at a given offset" do + (0..Float::INFINITY).lazy.with_index(3).map { |i, idx| [i, idx] }.first(3).should == [[0, 3], [1, 4], [2, 5]] + end + + it "enumerates with an index starting at 0 when offset is nil" do + (0..Float::INFINITY).lazy.with_index(nil).map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]] + end + + it "raises TypeError when offset does not convert to Integer" do + -> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should raise_error(TypeError) + end + + it "enumerates with a given block" do + result = [] + (0..Float::INFINITY).lazy.with_index { |i, idx| result << [i * 2, idx] }.first(3) + result.should == [[0,0],[2,1],[4,2]] + end + + it "resets after a new call to each" do + enum = (0..2).lazy.with_index.map { |i, idx| [i, idx] } + result = [] + enum.each { |i, idx| result << [i, idx] } + enum.each { |i, idx| result << [i, idx] } + result.should == [[0,0], [1,1], [2,2], [0,0], [1,1], [2,2]] + end +end diff --git a/spec/ruby/core/enumerator/new_spec.rb b/spec/ruby/core/enumerator/new_spec.rb index 5cc0b3ff2e..671912224f 100644 --- a/spec/ruby/core/enumerator/new_spec.rb +++ b/spec/ruby/core/enumerator/new_spec.rb @@ -2,51 +2,8 @@ require_relative '../../spec_helper' describe "Enumerator.new" do context "no block given" do - ruby_version_is '3.0' do - it "raises" do - -> { Enumerator.new(1, :upto, 3) }.should raise_error(ArgumentError) - end - end - - ruby_version_is ''...'3.0' do - it "creates a new custom enumerator with the given object, iterator and arguments" do - enum = suppress_warning { 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 = suppress_warning { Enumerator.new(1, :upto, 3) } - enum.respond_to?(:each).should == true - end - - it "creates a new custom enumerator that runs correctly" do - suppress_warning { Enumerator.new(1, :upto, 3) }.map{ |x| x }.should == [1,2,3] - end - - it "aliases the second argument to :each" do - suppress_warning { Enumerator.new(1..2) }.to_a.should == - suppress_warning { Enumerator.new(1..2, :each) }.to_a - end - - it "doesn't check for the presence of the iterator method" do - suppress_warning { 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 = suppress_warning { Enumerator.new(StrangeEach.new) } - enum.to_a.should == [:foo] - class StrangeEach - def each - yield :bar - end - end - enum.to_a.should == [:bar] - end + it "raises" do + -> { Enumerator.new(1, :upto, 3) }.should raise_error(ArgumentError) end end @@ -77,14 +34,12 @@ describe "Enumerator.new" do enum.take(3).should == [1, 2, 3] end - ruby_version_is "2.7" do - it "defines iteration with block, yielder argument and treating it as a proc" do - enum = Enumerator.new do |yielder| - "a\nb\nc".each_line(&yielder) - end - - enum.to_a.should == ["a\n", "b\n", "c"] + it "defines iteration with block, yielder argument and treating it as a proc" do + enum = Enumerator.new do |yielder| + "a\nb\nc".each_line(&yielder) end + + enum.to_a.should == ["a\n", "b\n", "c"] end describe 'yielded values' do diff --git a/spec/ruby/core/enumerator/plus_spec.rb b/spec/ruby/core/enumerator/plus_spec.rb index c9bae08b04..755be5b4eb 100644 --- a/spec/ruby/core/enumerator/plus_spec.rb +++ b/spec/ruby/core/enumerator/plus_spec.rb @@ -1,35 +1,33 @@ require_relative '../../spec_helper' -ruby_version_is "2.6" do - describe "Enumerator#+" do - before :each do - ScratchPad.record [] - end +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 } + 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 = one + two + three - chain.should be_an_instance_of(Enumerator::Chain) - chain.each { |item| ScratchPad << item } - ScratchPad.recorded.should == [1, 2, 3] - end + 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" } + it "calls #each on each argument" do + enum = Enumerator.new { |y| y << "one" } - obj1 = mock("obj1") - obj1.should_receive(:each).once.and_yield("two") + obj1 = mock("obj1") + obj1.should_receive(:each).once.and_yield("two") - obj2 = mock("obj2") - obj2.should_receive(:each).once.and_yield("three") + 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 + chain = enum + obj1 + obj2 + chain.each { |item| ScratchPad << item } + ScratchPad.recorded.should == ["one", "two", "three"] end end diff --git a/spec/ruby/core/enumerator/produce_spec.rb b/spec/ruby/core/enumerator/produce_spec.rb index f6f1dcd429..c69fb49303 100644 --- a/spec/ruby/core/enumerator/produce_spec.rb +++ b/spec/ruby/core/enumerator/produce_spec.rb @@ -1,36 +1,34 @@ require_relative '../../spec_helper' -ruby_version_is "2.7" do - describe "Enumerator.produce" do - it "creates an infinite enumerator" do - enum = Enumerator.produce(0) { |prev| prev + 1 } - enum.take(5).should == [0, 1, 2, 3, 4] - end - - it "terminates iteration when block raises StopIteration exception" do - enum = Enumerator.produce(0) do | prev| - raise StopIteration if prev >= 2 - prev + 1 - end +describe "Enumerator.produce" do + it "creates an infinite enumerator" do + enum = Enumerator.produce(0) { |prev| prev + 1 } + enum.take(5).should == [0, 1, 2, 3, 4] + end - enum.to_a.should == [0, 1, 2] + it "terminates iteration when block raises StopIteration exception" do + enum = Enumerator.produce(0) do | prev| + raise StopIteration if prev >= 2 + prev + 1 end - context "when initial value skipped" do - it "uses nil instead" do - ScratchPad.record [] - enum = Enumerator.produce { |prev| ScratchPad << prev; (prev || 0) + 1 } + enum.to_a.should == [0, 1, 2] + end + + context "when initial value skipped" do + it "uses nil instead" do + ScratchPad.record [] + enum = Enumerator.produce { |prev| ScratchPad << prev; (prev || 0) + 1 } - enum.take(3).should == [1, 2, 3] - ScratchPad.recorded.should == [nil, 1, 2] - end + enum.take(3).should == [1, 2, 3] + ScratchPad.recorded.should == [nil, 1, 2] + end - it "starts enumerable from result of first block call" do - array = "a\nb\nc\nd".lines - lines = Enumerator.produce { array.shift }.take_while { |s| s } + it "starts enumerable from result of first block call" do + array = "a\nb\nc\nd".lines + lines = Enumerator.produce { array.shift }.take_while { |s| s } - lines.should == ["a\n", "b\n", "c\n", "d"] - end + lines.should == ["a\n", "b\n", "c\n", "d"] end end end diff --git a/spec/ruby/core/enumerator/product/each_spec.rb b/spec/ruby/core/enumerator/product/each_spec.rb new file mode 100644 index 0000000000..cabeb9d93a --- /dev/null +++ b/spec/ruby/core/enumerator/product/each_spec.rb @@ -0,0 +1,73 @@ +require_relative '../../../spec_helper' +require_relative '../../enumerable/shared/enumeratorized' + +ruby_version_is "3.2" do + describe "Enumerator::Product#each" do + it_behaves_like :enumeratorized_with_origin_size, :each, Enumerator::Product.new([1, 2], [:a, :b]) + + it "yields each element of Cartesian product of enumerators" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + acc = [] + enum.each { |e| acc << e } + acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "calls #each_entry method on enumerators" do + object1 = Object.new + def object1.each_entry + yield 1 + yield 2 + end + + object2 = Object.new + def object2.each_entry + yield :a + yield :b + end + + enum = Enumerator::Product.new(object1, object2) + acc = [] + enum.each { |e| acc << e } + acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "raises a NoMethodError if the object doesn't respond to #each_entry" do + -> { + Enumerator::Product.new(Object.new).each {} + }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/) + end + + it "returns enumerator if not given a block" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.each.should.kind_of?(Enumerator) + + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "returns self if given a block" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.each {}.should.equal?(enum) + end + + it "doesn't accept arguments" do + Enumerator::Product.instance_method(:each).arity.should == 0 + end + + it "yields each element to a block that takes multiple arguments" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + + acc = [] + enum.each { |x, y| acc << x } + acc.should == [1, 1, 2, 2] + + acc = [] + enum.each { |x, y| acc << y } + acc.should == [:a, :b, :a, :b] + + acc = [] + enum.each { |x, y, z| acc << z } + acc.should == [nil, nil, nil, nil] + end + end +end diff --git a/spec/ruby/core/enumerator/product/initialize_copy_spec.rb b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb new file mode 100644 index 0000000000..46e8421322 --- /dev/null +++ b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb @@ -0,0 +1,54 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#initialize_copy" do + it "replaces content of the receiver with content of the other object" do + enum = Enumerator::Product.new([true, false]) + enum2 = Enumerator::Product.new([1, 2], [:a, :b]) + + enum.send(:initialize_copy, enum2) + enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "returns self" do + enum = Enumerator::Product.new([true, false]) + enum2 = Enumerator::Product.new([1, 2], [:a, :b]) + + enum.send(:initialize_copy, enum2).should.equal?(enum) + end + + it "is a private method" do + Enumerator::Product.should have_private_instance_method(:initialize_copy, false) + end + + it "does nothing if the argument is the same as the receiver" do + enum = Enumerator::Product.new(1..2) + enum.send(:initialize_copy, enum).should.equal?(enum) + + enum.freeze + enum.send(:initialize_copy, enum).should.equal?(enum) + end + + it "raises FrozenError if the receiver is frozen" do + enum = Enumerator::Product.new(1..2) + enum2 = Enumerator::Product.new(3..4) + + -> { enum.freeze.send(:initialize_copy, enum2) }.should raise_error(FrozenError) + end + + it "raises TypeError if the objects are of different class" do + enum = Enumerator::Product.new(1..2) + enum2 = Class.new(Enumerator::Product).new(3..4) + + -> { enum.send(:initialize_copy, enum2) }.should raise_error(TypeError, 'initialize_copy should take same class object') + -> { enum2.send(:initialize_copy, enum) }.should raise_error(TypeError, 'initialize_copy should take same class object') + end + + it "raises ArgumentError if the argument is not initialized yet" do + enum = Enumerator::Product.new(1..2) + enum2 = Enumerator::Product.allocate + + -> { enum.send(:initialize_copy, enum2) }.should raise_error(ArgumentError, 'uninitialized product') + end + end +end diff --git a/spec/ruby/core/enumerator/product/initialize_spec.rb b/spec/ruby/core/enumerator/product/initialize_spec.rb new file mode 100644 index 0000000000..4b60564240 --- /dev/null +++ b/spec/ruby/core/enumerator/product/initialize_spec.rb @@ -0,0 +1,33 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#initialize" do + before :each do + @uninitialized = Enumerator::Product.allocate + end + + it "is a private method" do + Enumerator::Product.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_entry" do + @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) + end + + describe "on frozen instance" do + it "raises a FrozenError" do + -> { + @uninitialized.freeze.send(:initialize, 0..1) + }.should raise_error(FrozenError) + end + end + end +end diff --git a/spec/ruby/core/enumerator/product/inspect_spec.rb b/spec/ruby/core/enumerator/product/inspect_spec.rb new file mode 100644 index 0000000000..1ea8e9c49b --- /dev/null +++ b/spec/ruby/core/enumerator/product/inspect_spec.rb @@ -0,0 +1,22 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#inspect" do + it "returns a String including enumerators" do + enum = Enumerator::Product.new([1, 2], [:a, :b]) + enum.inspect.should == "#<Enumerator::Product: [[1, 2], [:a, :b]]>" + end + + it "represents a recursive element with '[...]'" do + enum = [1, 2] + enum_recursive = Enumerator::Product.new(enum) + + enum << enum_recursive + enum_recursive.inspect.should == "#<Enumerator::Product: [[1, 2, #<Enumerator::Product: ...>]]>" + end + + it "returns a not initialized representation if #initialized is not called yet" do + Enumerator::Product.allocate.inspect.should == "#<Enumerator::Product: uninitialized>" + end + end +end diff --git a/spec/ruby/core/enumerator/product/rewind_spec.rb b/spec/ruby/core/enumerator/product/rewind_spec.rb new file mode 100644 index 0000000000..e8ee730239 --- /dev/null +++ b/spec/ruby/core/enumerator/product/rewind_spec.rb @@ -0,0 +1,64 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#rewind" do + before :each do + @enum = Enumerator::Product.new([1, 2].each.to_enum, [:a, :b].each.to_enum) + end + + it "resets the enumerator to its initial state" do + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + @enum.rewind + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "returns self" do + @enum.rewind.should.equal? @enum + end + + it "has no effect on a new enumerator" do + @enum.rewind + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "has no effect if called multiple, consecutive times" do + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + @enum.rewind + @enum.rewind + @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] + end + + it "calls the enclosed object's rewind method if one exists" do + obj = mock('rewinder') + enum = Enumerator::Product.new(obj.to_enum) + + obj.should_receive(:rewind) + enum.rewind + end + + it "does nothing if the object doesn't have a #rewind method" do + obj = mock('rewinder') + enum = Enumerator::Product.new(obj.to_enum) + + enum.rewind.should == enum + end + + it "calls a rewind method on each enumerable in direct order" do + ScratchPad.record [] + + object1 = Object.new + def object1.rewind; ScratchPad << :object1; end + + object2 = Object.new + def object2.rewind; ScratchPad << :object2; end + + object3 = Object.new + def object3.rewind; ScratchPad << :object3; end + + enum = Enumerator::Product.new(object1, object2, object3) + enum.rewind + + ScratchPad.recorded.should == [:object1, :object2, :object3] + end + end +end diff --git a/spec/ruby/core/enumerator/product/size_spec.rb b/spec/ruby/core/enumerator/product/size_spec.rb new file mode 100644 index 0000000000..46958b1a22 --- /dev/null +++ b/spec/ruby/core/enumerator/product/size_spec.rb @@ -0,0 +1,56 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator::Product#size" do + it "returns the total size of the enumerator product calculated by multiplying the sizes of enumerables in the product" do + product = Enumerator::Product.new(1..2, 1..3, 1..4) + product.size.should == 24 # 2 * 3 * 4 + end + + it "returns nil if any enumerable reports its size as nil" do + enum = Object.new + def enum.size; nil; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns Float::INFINITY if any enumerable reports its size as Float::INFINITY" do + enum = Object.new + def enum.size; Float::INFINITY; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == Float::INFINITY + end + + it "returns nil if any enumerable reports its size as Float::NAN" do + enum = Object.new + def enum.size; Float::NAN; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns nil if any enumerable doesn't respond to #size" do + enum = Object.new + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns nil if any enumerable reports a not-convertible to Integer" do + enum = Object.new + def enum.size; :symbol; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + + it "returns nil if any enumerable reports a non-Integer but convertible to Integer size" do + enum = Object.new + def enum.size; 1.0; end + + product = Enumerator::Product.new(1..2, enum) + product.size.should == nil + end + end +end diff --git a/spec/ruby/core/enumerator/product_spec.rb b/spec/ruby/core/enumerator/product_spec.rb new file mode 100644 index 0000000000..0acca6690e --- /dev/null +++ b/spec/ruby/core/enumerator/product_spec.rb @@ -0,0 +1,93 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.2" do + describe "Enumerator.product" do + it "returns a Cartesian product of enumerators" do + enum = Enumerator.product(1..2, ["A", "B"]) + enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]] + end + + it "accepts a list of enumerators of any length" do + enum = Enumerator.product(1..2) + enum.to_a.should == [[1], [2]] + + enum = Enumerator.product(1..2, ["A"]) + enum.to_a.should == [[1, "A"], [2, "A"]] + + enum = Enumerator.product(1..2, ["A"], ["B"]) + enum.to_a.should == [[1, "A", "B"], [2, "A", "B"]] + + enum = Enumerator.product(2..3, ["A"], ["B"], ["C"]) + enum.to_a.should == [[2, "A", "B", "C"], [3, "A", "B", "C"]] + end + + it "returns an enumerator with an empty array when no arguments passed" do + enum = Enumerator.product + enum.to_a.should == [[]] + end + + it "returns an instance of Enumerator::Product" do + enum = Enumerator.product + enum.class.should == Enumerator::Product + end + + it "accepts infinite enumerators and returns infinite enumerator" do + enum = Enumerator.product(1.., ["A", "B"]) + enum.take(5).should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"]] + enum.size.should == Float::INFINITY + end + + it "accepts a block" do + elems = [] + enum = Enumerator.product(1..2, ["X", "Y"]) { elems << _1 } + + elems.should == [[1, "X"], [1, "Y"], [2, "X"], [2, "Y"]] + end + + it "returns nil when a block passed" do + Enumerator.product(1..2) {}.should == nil + end + + # https://bugs.ruby-lang.org/issues/19829 + it "reject keyword arguments" do + -> { + Enumerator.product(1..3, foo: 1, bar: 2) + }.should raise_error(ArgumentError, "unknown keywords: :foo, :bar") + end + + it "calls only #each_entry method on arguments" do + object = Object.new + def object.each_entry + yield 1 + yield 2 + end + + enum = Enumerator.product(object, ["A", "B"]) + enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]] + end + + it "raises NoMethodError when argument doesn't respond to #each_entry" do + -> { + Enumerator.product(Object.new).to_a + }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/) + end + + it "calls #each_entry lazily" do + Enumerator.product(Object.new).should be_kind_of(Enumerator) + end + + it "iterates through consuming enumerator elements only once" do + a = [1, 2, 3] + i = 0 + + enum = Enumerator.new do |y| + while i < a.size + y << a[i] + i += 1 + end + end + + Enumerator.product(['a', 'b'], enum).to_a.should == [["a", 1], ["a", 2], ["a", 3]] + end + end +end diff --git a/spec/ruby/core/enumerator/rewind_spec.rb b/spec/ruby/core/enumerator/rewind_spec.rb index a105f2c619..6ba0edf174 100644 --- a/spec/ruby/core/enumerator/rewind_spec.rb +++ b/spec/ruby/core/enumerator/rewind_spec.rb @@ -14,7 +14,7 @@ describe "Enumerator#rewind" do end it "returns self" do - @enum.rewind.should == @enum + @enum.rewind.should.equal? @enum end it "has no effect on a new enumerator" do @@ -49,7 +49,7 @@ describe "Enumerator#rewind" do obj = mock('rewinder') enum = obj.to_enum obj.should_receive(:each).at_most(1) - -> { enum.rewind.should == enum }.should_not raise_error + enum.rewind.should == enum end end diff --git a/spec/ruby/core/enumerator/yielder/append_spec.rb b/spec/ruby/core/enumerator/yielder/append_spec.rb index 7f7059774d..a36e5d64b6 100644 --- a/spec/ruby/core/enumerator/yielder/append_spec.rb +++ b/spec/ruby/core/enumerator/yielder/append_spec.rb @@ -23,25 +23,13 @@ describe "Enumerator::Yielder#<<" do end context "when multiple arguments passed" do - ruby_version_is '' ... '2.6' do - it "yields the arguments list to the block" do - ary = [] - y = Enumerator::Yielder.new { |*x| ary << x } - y.<<(1, 2) - - ary.should == [[1, 2]] - end - end + it "raises an ArgumentError" do + ary = [] + y = Enumerator::Yielder.new { |*x| ary << x } - ruby_version_is '2.6' do - it "raises an ArgumentError" do - ary = [] - y = Enumerator::Yielder.new { |*x| ary << x } - - -> { - y.<<(1, 2) - }.should raise_error(ArgumentError, /wrong number of arguments/) - end + -> { + y.<<(1, 2) + }.should raise_error(ArgumentError, /wrong number of arguments/) end end end diff --git a/spec/ruby/core/enumerator/yielder/to_proc_spec.rb b/spec/ruby/core/enumerator/yielder/to_proc_spec.rb index 0ed1645853..1d3681ab50 100644 --- a/spec/ruby/core/enumerator/yielder/to_proc_spec.rb +++ b/spec/ruby/core/enumerator/yielder/to_proc_spec.rb @@ -1,18 +1,16 @@ require_relative '../../../spec_helper' -ruby_version_is "2.7" do - describe "Enumerator::Yielder#to_proc" do - it "returns a Proc object that takes an argument and yields it to the block" do - ScratchPad.record [] - y = Enumerator::Yielder.new { |*args| ScratchPad << args; "foobar" } +describe "Enumerator::Yielder#to_proc" do + it "returns a Proc object that takes an argument and yields it to the block" do + ScratchPad.record [] + y = Enumerator::Yielder.new { |*args| ScratchPad << args; "foobar" } - callable = y.to_proc - callable.class.should == Proc + callable = y.to_proc + callable.class.should == Proc - result = callable.call(1, 2) - ScratchPad.recorded.should == [[1, 2]] + result = callable.call(1, 2) + ScratchPad.recorded.should == [[1, 2]] - result.should == "foobar" - end + result.should == "foobar" end end |