diff options
Diffstat (limited to 'spec/ruby/core/enumerable')
70 files changed, 1352 insertions, 733 deletions
diff --git a/spec/ruby/core/enumerable/all_spec.rb b/spec/ruby/core/enumerable/all_spec.rb index 9e40315baa..160cd52628 100644 --- a/spec/ruby/core/enumerable/all_spec.rb +++ b/spec/ruby/core/enumerable/all_spec.rb @@ -1,73 +1,67 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#all?" do - before :each do @enum = EnumerableSpecs::Numerous.new @empty = EnumerableSpecs::Empty.new() - @enum1 = [0, 1, 2, -1] - @enum2 = [nil, false, true] + @enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1) + @enum2 = EnumerableSpecs::Numerous.new(nil, false, true) end it "always returns true on empty enumeration" do - @empty.all?.should == true + @empty.should.all? @empty.all? { nil }.should == true - [].all?.should == true + [].should.all? [].all? { false }.should == true - {}.all?.should == true + {}.should.all? {}.all? { nil }.should == true end + it "raises an ArgumentError when more than 1 argument is provided" do + -> { @enum.all?(1, 2, 3) }.should raise_error(ArgumentError) + -> { [].all?(1, 2, 3) }.should raise_error(ArgumentError) + -> { {}.all?(1, 2, 3) }.should raise_error(ArgumentError) + end + it "does not hide exceptions out of #each" do - lambda { + -> { EnumerableSpecs::ThrowingEach.new.all? }.should raise_error(RuntimeError) - lambda { + -> { EnumerableSpecs::ThrowingEach.new.all? { false } }.should raise_error(RuntimeError) end describe "with no block" do it "returns true if no elements are false or nil" do - @enum.all?.should == true - @enum1.all?.should == true - @enum2.all?.should == false + @enum.should.all? + @enum1.should.all? + @enum2.should_not.all? - EnumerableSpecs::Numerous.new('a','b','c').all?.should == true - EnumerableSpecs::Numerous.new(0, "x", true).all?.should == true + EnumerableSpecs::Numerous.new('a','b','c').should.all? + EnumerableSpecs::Numerous.new(0, "x", true).should.all? end it "returns false if there are false or nil elements" do - EnumerableSpecs::Numerous.new(false).all?.should == false - EnumerableSpecs::Numerous.new(false, false).all?.should == false + EnumerableSpecs::Numerous.new(false).should_not.all? + EnumerableSpecs::Numerous.new(false, false).should_not.all? - EnumerableSpecs::Numerous.new(nil).all?.should == false - EnumerableSpecs::Numerous.new(nil, nil).all?.should == false + EnumerableSpecs::Numerous.new(nil).should_not.all? + EnumerableSpecs::Numerous.new(nil, nil).should_not.all? - EnumerableSpecs::Numerous.new(1, nil, 2).all?.should == false - EnumerableSpecs::Numerous.new(0, "x", false, true).all?.should == false - @enum2.all?.should == false + EnumerableSpecs::Numerous.new(1, nil, 2).should_not.all? + EnumerableSpecs::Numerous.new(0, "x", false, true).should_not.all? + @enum2.should_not.all? end it "gathers whole arrays as elements when each yields multiple" do - # This spec doesn't spec what it says it does multi = EnumerableSpecs::YieldsMultiWithFalse.new multi.all?.should be_true end - - ruby_version_is "2.5" do - describe "given a pattern argument" do - # This spec should be replaced by more extensive ones - it "returns true iff all match that pattern" do - @enum.all?(Integer).should == true - @enum2.all?(NilClass).should == false - end - end - end end describe "with block" do @@ -110,21 +104,84 @@ describe "Enumerable#all?" do end it "does not hide exceptions out of the block" do - lambda { + -> { @enum.all? { raise "from block" } }.should raise_error(RuntimeError) end it "gathers initial args as elements when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new - multi.all? {|e| !(Array === e) }.should be_true + yielded = [] + multi.all? { |e| yielded << e }.should == true + yielded.should == [1, 3, 6] end it "yields multiple arguments when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new yielded = [] - multi.all? {|e, i| yielded << [e, i] } - yielded.should == [[1, 2], [3, 4], [6, 7]] + multi.all? { |*args| yielded << args }.should == true + yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]] + end + end + + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 } + @enum1.all?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + end + + it "always returns true on empty enumeration" do + @empty.all?(Integer).should == true + [].all?(Integer).should == true + {}.all?(NilClass).should == true + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.all?(Integer) + }.should raise_error(RuntimeError) + end + + it "returns true if the pattern never returns false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| 42 } + @enum.all?(pattern).should == true + + [1, 42, 3].all?(pattern).should == true + + pattern = EnumerableSpecs::Pattern.new { |x| Array === x } + {a: 1, b: 2}.all?(pattern).should == true + end + + it "returns false if the pattern ever returns false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 } + @enum1.all?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3, -1].all?(pattern).should == false + + pattern = EnumerableSpecs::Pattern.new { |x| x[1] >= 0 } + {a: 1, b: -1}.all?(pattern).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.all?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { true } + multi.all?(pattern).should == true + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] + end + + it "ignores the block if there is an argument" do + -> { + EnumerableSpecs::Numerous.new(1, 2, 3, 4, 5).all?(String) { true }.should == false + }.should complain(/given block not used/) end end end diff --git a/spec/ruby/core/enumerable/any_spec.rb b/spec/ruby/core/enumerable/any_spec.rb index edf7e36519..243f8735d5 100644 --- a/spec/ruby/core/enumerable/any_spec.rb +++ b/spec/ruby/core/enumerable/any_spec.rb @@ -1,70 +1,61 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#any?" do before :each do @enum = EnumerableSpecs::Numerous.new - @empty = EnumerableSpecs::Empty.new() - @enum1 = [0, 1, 2, -1] - @enum2 = [nil, false, true] + @empty = EnumerableSpecs::Empty.new + @enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1) + @enum2 = EnumerableSpecs::Numerous.new(nil, false, true) end it "always returns false on empty enumeration" do - @empty.any?.should == false + @empty.should_not.any? @empty.any? { nil }.should == false - [].any?.should == false + [].should_not.any? [].any? { false }.should == false - {}.any?.should == false + {}.should_not.any? {}.any? { nil }.should == false end it "raises an ArgumentError when more than 1 argument is provided" do - lambda { @enum.any?(1, 2, 3) }.should raise_error(ArgumentError) - lambda { [].any?(1, 2, 3) }.should raise_error(ArgumentError) - lambda { {}.any?(1, 2, 3) }.should raise_error(ArgumentError) - end - - ruby_version_is ""..."2.5" do - it "raises an ArgumentError when any arguments provided" do - lambda { @enum.any?(Proc.new {}) }.should raise_error(ArgumentError) - lambda { @enum.any?(nil) }.should raise_error(ArgumentError) - lambda { @empty.any?(1) }.should raise_error(ArgumentError) - lambda { @enum1.any?(1) {} }.should raise_error(ArgumentError) - end + -> { @enum.any?(1, 2, 3) }.should raise_error(ArgumentError) + -> { [].any?(1, 2, 3) }.should raise_error(ArgumentError) + -> { {}.any?(1, 2, 3) }.should raise_error(ArgumentError) end it "does not hide exceptions out of #each" do - lambda { + -> { EnumerableSpecs::ThrowingEach.new.any? }.should raise_error(RuntimeError) - lambda { + -> { EnumerableSpecs::ThrowingEach.new.any? { false } }.should raise_error(RuntimeError) end describe "with no block" do it "returns true if any element is not false or nil" do - @enum.any?.should == true - @enum1.any?.should == true - @enum2.any?.should == true - EnumerableSpecs::Numerous.new(true).any?.should == true - EnumerableSpecs::Numerous.new('a','b','c').any?.should == true - EnumerableSpecs::Numerous.new('a','b','c', nil).any?.should == true - EnumerableSpecs::Numerous.new(1, nil, 2).any?.should == true - EnumerableSpecs::Numerous.new(1, false).any?.should == true - EnumerableSpecs::Numerous.new(false, nil, 1, false).any?.should == true - EnumerableSpecs::Numerous.new(false, 0, nil).any?.should == true + @enum.should.any? + @enum1.should.any? + @enum2.should.any? + EnumerableSpecs::Numerous.new(true).should.any? + EnumerableSpecs::Numerous.new('a','b','c').should.any? + EnumerableSpecs::Numerous.new('a','b','c', nil).should.any? + EnumerableSpecs::Numerous.new(1, nil, 2).should.any? + EnumerableSpecs::Numerous.new(1, false).should.any? + EnumerableSpecs::Numerous.new(false, nil, 1, false).should.any? + EnumerableSpecs::Numerous.new(false, 0, nil).should.any? end it "returns false if all elements are false or nil" do - EnumerableSpecs::Numerous.new(false).any?.should == false - EnumerableSpecs::Numerous.new(false, false).any?.should == false - EnumerableSpecs::Numerous.new(nil).any?.should == false - EnumerableSpecs::Numerous.new(nil, nil).any?.should == false - EnumerableSpecs::Numerous.new(nil, false, nil).any?.should == false + EnumerableSpecs::Numerous.new(false).should_not.any? + EnumerableSpecs::Numerous.new(false, false).should_not.any? + EnumerableSpecs::Numerous.new(nil).should_not.any? + EnumerableSpecs::Numerous.new(nil, nil).should_not.any? + EnumerableSpecs::Numerous.new(nil, false, nil).should_not.any? end it "gathers whole arrays as elements when each yields multiple" do @@ -86,7 +77,7 @@ describe "Enumerable#any?" do @enum2.any? { |i| i == nil }.should == true end - it "any? should return false if the block never returns other than false or nil" do + it "returns false if the block never returns other than false or nil" do @enum.any? { false }.should == false @enum.any? { nil }.should == false @@ -127,99 +118,83 @@ describe "Enumerable#any?" do end it "does not hide exceptions out of the block" do - lambda { + -> { @enum.any? { raise "from block" } }.should raise_error(RuntimeError) end it "gathers initial args as elements when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new - multi.any? {|e| e == 1 }.should be_true + yielded = [] + multi.any? { |e| yielded << e; false }.should == false + yielded.should == [1, 3, 6] end it "yields multiple arguments when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new yielded = [] - multi.any? {|e, i| yielded << [e, i] } - yielded.should == [[1, 2]] + multi.any? { |*args| yielded << args; false }.should == false + yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]] end - end - ruby_version_is "2.5" do - describe 'when given a pattern argument' do - class EnumerableSpecs::Pattern - attr_reader :yielded - def initialize(&block) - @block = block - @yielded = [] - end - def ===(*args) - @yielded << args - @block.call(*args) - end - end - - it "calls `===` on the pattern the return value " do - pattern = EnumerableSpecs::Pattern.new { |x| x == 2 } - @enum1.any?(pattern).should == true - pattern.yielded.should == [[0], [1], [2]] - end - - it "ignores block" do - @enum2.any?(NilClass) { raise }.should == true - [1, 2, nil].any?(NilClass) { raise }.should == true - {a: 1}.any?(Array) { raise }.should == true - end - - it "always returns false on empty enumeration" do - @empty.any?(Integer).should == false - [].any?(Integer).should == false - {}.any?(NilClass).should == false - end - - it "does not hide exceptions out of #each" do - lambda { - EnumerableSpecs::ThrowingEach.new.any?(Integer) - }.should raise_error(RuntimeError) - end - - it "returns true if the pattern ever returns a truthy value" do - @enum2.any?(NilClass).should == true - pattern = EnumerableSpecs::Pattern.new { |x| 42 } - @enum.any?(pattern).should == true - - [1, 42, 3].any?(pattern).should == true - - pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] } - {a: 1, b: 2}.any?(pattern).should == true - end - - it "any? should return false if the block never returns other than false or nil" do - pattern = EnumerableSpecs::Pattern.new { |x| nil } - @enum1.any?(pattern).should == false - pattern.yielded.should == [[0], [1], [2], [-1]] - - [1, 2, 3].any?(pattern).should == false - {a: 1}.any?(pattern).should == false - end - - it "does not hide exceptions out of the block" do - pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } - lambda { - @enum.any?(pattern) - }.should raise_error(RuntimeError) - end - - it "calls the pattern with gathered array when yielded with multiple arguments" do - pattern = EnumerableSpecs::Pattern.new { false } - EnumerableSpecs::YieldsMixed2.new.any?(pattern).should == false - pattern.yielded.should == EnumerableSpecs::YieldsMixed2.gathered_yields.map { |x| [x] } - - pattern = EnumerableSpecs::Pattern.new { false } - {a: 1, b: 2}.any?(pattern).should == false - pattern.yielded.should == [[[:a, 1]], [[:b, 2]]] - end + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x == 2 } + @enum1.any?(pattern).should == true + pattern.yielded.should == [[0], [1], [2]] + end + + it "always returns false on empty enumeration" do + @empty.any?(Integer).should == false + [].any?(Integer).should == false + {}.any?(NilClass).should == false + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.any?(Integer) + }.should raise_error(RuntimeError) + end + + it "returns true if the pattern ever returns a truthy value" do + @enum2.any?(NilClass).should == true + pattern = EnumerableSpecs::Pattern.new { |x| 42 } + @enum.any?(pattern).should == true + + [1, 42, 3].any?(pattern).should == true + + pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] } + {a: 1, b: 2}.any?(pattern).should == true + end + + it "returns false if the block never returns other than false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| nil } + @enum1.any?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3].any?(pattern).should == false + {a: 1}.any?(pattern).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.any?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { false } + multi.any?(pattern).should == false + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] + end + + it "ignores the block if there is an argument" do + -> { + EnumerableSpecs::Numerous.new(1, 2, 3, 4, 5).any?(String) { true }.should == false + }.should complain(/given block not used/) end end end diff --git a/spec/ruby/core/enumerable/chain_spec.rb b/spec/ruby/core/enumerable/chain_spec.rb new file mode 100644 index 0000000000..5e2105d294 --- /dev/null +++ b/spec/ruby/core/enumerable/chain_spec.rb @@ -0,0 +1,23 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +describe "Enumerable#chain" do + before :each do + ScratchPad.record [] + end + + it "returns a chain of self and provided enumerables" do + one = EnumerableSpecs::Numerous.new(1) + two = EnumerableSpecs::Numerous.new(2, 3) + three = EnumerableSpecs::Numerous.new(4, 5, 6) + + chain = one.chain(two, three) + + chain.each { |item| ScratchPad << item } + ScratchPad.recorded.should == [1, 2, 3, 4, 5, 6] + end + + it "returns an Enumerator::Chain if given a block" do + EnumerableSpecs::Numerous.new.chain.should be_an_instance_of(Enumerator::Chain) + end +end diff --git a/spec/ruby/core/enumerable/chunk_spec.rb b/spec/ruby/core/enumerable/chunk_spec.rb index 9d658010e1..ed6304307f 100644 --- a/spec/ruby/core/enumerable/chunk_spec.rb +++ b/spec/ruby/core/enumerable/chunk_spec.rb @@ -1,26 +1,16 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#chunk" do before do ScratchPad.record [] end - ruby_version_is ""..."2.4" do - it "raises an ArgumentError if called without a block" do - lambda do - EnumerableSpecs::Numerous.new.chunk - end.should raise_error(ArgumentError) - end - end - - ruby_version_is "2.4" do - it "returns an Enumerator if called without a block" do - chunk = EnumerableSpecs::Numerous.new(1, 2, 3, 1, 2).chunk - chunk.should be_an_instance_of(Enumerator) - result = chunk.with_index {|elt, i| elt - i }.to_a - result.should == [[1, [1, 2, 3]], [-2, [1, 2]]] - end + it "returns an Enumerator if called without a block" do + chunk = EnumerableSpecs::Numerous.new(1, 2, 3, 1, 2).chunk + chunk.should be_an_instance_of(Enumerator) + result = chunk.with_index {|elt, i| elt - i }.to_a + result.should == [[1, [1, 2, 3]], [-2, [1, 2]]] end it "returns an Enumerator if given a block" do @@ -39,12 +29,22 @@ describe "Enumerable#chunk" do result.should == [[1, [1, 2]], [0, [3]], [1, [2]], [0, [3]], [1, [2, 1]]] end + it "returns a partitioned Array of values" do + e = EnumerableSpecs::Numerous.new(1,2,3) + e.chunk { |x| x > 2 }.map(&:last).should == [[1, 2], [3]] + end + it "returns elements for which the block returns :_alone in separate Arrays" do e = EnumerableSpecs::Numerous.new(1, 2, 3, 2, 1) result = e.chunk { |x| x < 2 && :_alone }.to_a result.should == [[:_alone, [1]], [false, [2, 3, 2]], [:_alone, [1]]] end + it "yields Arrays as a single argument to a rest argument" do + e = EnumerableSpecs::Numerous.new([1, 2]) + result = e.chunk { |*x| x.should == [[1,2]] }.to_a + end + it "does not return elements for which the block returns :_separator" do e = EnumerableSpecs::Numerous.new(1, 2, 3, 3, 2, 1) result = e.chunk { |x| x == 2 ? :_separator : 1 }.to_a @@ -59,37 +59,14 @@ describe "Enumerable#chunk" do it "raises a RuntimeError if the block returns a Symbol starting with an underscore other than :_alone or :_separator" do e = EnumerableSpecs::Numerous.new(1, 2, 3, 2, 1) - lambda { e.chunk { |x| :_arbitrary }.to_a }.should raise_error(RuntimeError) + -> { e.chunk { |x| :_arbitrary }.to_a }.should raise_error(RuntimeError) end - ruby_version_is ""..."2.3" do - describe "with [initial_state]" do - it "yields an element and an object value-equal but not identical to the object passed to #chunk" do - e = EnumerableSpecs::Numerous.new(1) - value = "value" - - e.chunk(value) do |x, v| - x.should == 1 - v.should == value - v.should_not equal(value) - end.to_a - end - - it "does not yield the object passed to #chunk if it is nil" do - e = EnumerableSpecs::Numerous.new(1) - e.chunk(nil) { |*x| ScratchPad << x }.to_a - ScratchPad.recorded.should == [[1]] - end - end - end - - ruby_version_is "2.3" do - it "does not accept arguments" do - e = EnumerableSpecs::Numerous.new(1, 2, 3) - lambda { - e.chunk(1) {} - }.should raise_error(ArgumentError) - end + it "does not accept arguments" do + e = EnumerableSpecs::Numerous.new(1, 2, 3) + -> { + e.chunk(1) {} + }.should raise_error(ArgumentError) end it 'returned Enumerator size returns nil' do diff --git a/spec/ruby/core/enumerable/chunk_while_spec.rb b/spec/ruby/core/enumerable/chunk_while_spec.rb index a5cbdc3348..26bcc983db 100644 --- a/spec/ruby/core/enumerable/chunk_while_spec.rb +++ b/spec/ruby/core/enumerable/chunk_while_spec.rb @@ -1,44 +1,42 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' -ruby_version_is "2.3" do - describe "Enumerable#chunk_while" do - before :each do - ary = [10, 9, 7, 6, 4, 3, 2, 1] - @enum = EnumerableSpecs::Numerous.new(*ary) - @result = @enum.chunk_while { |i, j| i - 1 == j } - @enum_length = ary.length - end +describe "Enumerable#chunk_while" do + before :each do + ary = [10, 9, 7, 6, 4, 3, 2, 1] + @enum = EnumerableSpecs::Numerous.new(*ary) + @result = @enum.chunk_while { |i, j| i - 1 == j } + @enum_length = ary.length + end - context "when given a block" do - it "returns an enumerator" do - @result.should be_an_instance_of(Enumerator) - end + context "when given a block" do + it "returns an enumerator" do + @result.should be_an_instance_of(Enumerator) + end - it "splits chunks between adjacent elements i and j where the block returns false" do - @result.to_a.should == [[10, 9], [7, 6], [4, 3, 2, 1]] - end + it "splits chunks between adjacent elements i and j where the block returns false" do + @result.to_a.should == [[10, 9], [7, 6], [4, 3, 2, 1]] + end - it "calls the block for length of the receiver enumerable minus one times" do - times_called = 0 - @enum.chunk_while do |i, j| - times_called += 1 - i - 1 == j - end.to_a - times_called.should == (@enum_length - 1) - end + it "calls the block for length of the receiver enumerable minus one times" do + times_called = 0 + @enum.chunk_while do |i, j| + times_called += 1 + i - 1 == j + end.to_a + times_called.should == (@enum_length - 1) end + end - context "when not given a block" do - it "raises an ArgumentError" do - lambda { @enum.chunk_while }.should raise_error(ArgumentError) - end + context "when not given a block" do + it "raises an ArgumentError" do + -> { @enum.chunk_while }.should raise_error(ArgumentError) end + end - context "on a single-element array" do - it "ignores the block and returns an enumerator that yields [element]" do - [1].chunk_while {|x| x.even?}.to_a.should == [[1]] - end + context "on a single-element array" do + it "ignores the block and returns an enumerator that yields [element]" do + [1].chunk_while {|x| x.even?}.to_a.should == [[1]] end end end diff --git a/spec/ruby/core/enumerable/collect_concat_spec.rb b/spec/ruby/core/enumerable/collect_concat_spec.rb index 6f21012060..59317cfe34 100644 --- a/spec/ruby/core/enumerable/collect_concat_spec.rb +++ b/spec/ruby/core/enumerable/collect_concat_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/collect_concat', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/collect_concat' describe "Enumerable#collect_concat" do - it_behaves_like(:enumerable_collect_concat , :collect_concat) + it_behaves_like :enumerable_collect_concat, :collect_concat end diff --git a/spec/ruby/core/enumerable/collect_spec.rb b/spec/ruby/core/enumerable/collect_spec.rb index a830eef9f7..cfa2895cce 100644 --- a/spec/ruby/core/enumerable/collect_spec.rb +++ b/spec/ruby/core/enumerable/collect_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/collect', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/collect' describe "Enumerable#collect" do - it_behaves_like(:enumerable_collect , :collect) + it_behaves_like :enumerable_collect, :collect end diff --git a/spec/ruby/core/enumerable/compact_spec.rb b/spec/ruby/core/enumerable/compact_spec.rb new file mode 100644 index 0000000000..1895430c4e --- /dev/null +++ b/spec/ruby/core/enumerable/compact_spec.rb @@ -0,0 +1,9 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +describe "Enumerable#compact" do + it 'returns array without nil elements' do + arr = EnumerableSpecs::Numerous.new(nil, 1, 2, nil, true) + arr.compact.should == [1, 2, true] + end +end diff --git a/spec/ruby/core/enumerable/count_spec.rb b/spec/ruby/core/enumerable/count_spec.rb index 9d1e08f3a9..50a1c8e1a4 100644 --- a/spec/ruby/core/enumerable/count_spec.rb +++ b/spec/ruby/core/enumerable/count_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#count" do before :each do diff --git a/spec/ruby/core/enumerable/cycle_spec.rb b/spec/ruby/core/enumerable/cycle_spec.rb index 9089a94963..487086cba3 100644 --- a/spec/ruby/core/enumerable/cycle_spec.rb +++ b/spec/ruby/core/enumerable/cycle_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumeratorized' describe "Enumerable#cycle" do describe "passed no argument or nil" do @@ -71,12 +71,12 @@ describe "Enumerable#cycle" do it "raises a TypeError when the passed n cannot be coerced to Integer" do enum = EnumerableSpecs::Numerous.new - lambda{ enum.cycle("cat"){} }.should raise_error(TypeError) + ->{ enum.cycle("cat"){} }.should raise_error(TypeError) end it "raises an ArgumentError if more arguments are passed" do enum = EnumerableSpecs::Numerous.new - lambda{ enum.cycle(1, 2) {} }.should raise_error(ArgumentError) + ->{ enum.cycle(1, 2) {} }.should raise_error(ArgumentError) end it "gathers whole arrays as elements when each yields multiple" do diff --git a/spec/ruby/core/enumerable/detect_spec.rb b/spec/ruby/core/enumerable/detect_spec.rb index f69e456052..6959aadc44 100644 --- a/spec/ruby/core/enumerable/detect_spec.rb +++ b/spec/ruby/core/enumerable/detect_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/find', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/find' describe "Enumerable#detect" do - it_behaves_like(:enumerable_find , :detect) + it_behaves_like :enumerable_find, :detect end diff --git a/spec/ruby/core/enumerable/drop_spec.rb b/spec/ruby/core/enumerable/drop_spec.rb index 4013a639ce..423cc0088b 100644 --- a/spec/ruby/core/enumerable/drop_spec.rb +++ b/spec/ruby/core/enumerable/drop_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#drop" do before :each do @@ -7,13 +7,13 @@ describe "Enumerable#drop" do end it "requires exactly one argument" do - lambda{ @enum.drop{} }.should raise_error(ArgumentError) - lambda{ @enum.drop(1, 2){} }.should raise_error(ArgumentError) + ->{ @enum.drop{} }.should raise_error(ArgumentError) + ->{ @enum.drop(1, 2){} }.should raise_error(ArgumentError) end describe "passed a number n as an argument" do it "raises ArgumentError if n < 0" do - lambda{ @enum.drop(-1) }.should raise_error(ArgumentError) + ->{ @enum.drop(-1) }.should raise_error(ArgumentError) end it "tries to convert n to an Integer using #to_int" do @@ -35,8 +35,8 @@ describe "Enumerable#drop" do end it "raises a TypeError when the passed n cannot be coerced to Integer" do - lambda{ @enum.drop("hat") }.should raise_error(TypeError) - lambda{ @enum.drop(nil) }.should raise_error(TypeError) + ->{ @enum.drop("hat") }.should raise_error(TypeError) + ->{ @enum.drop(nil) }.should raise_error(TypeError) end end diff --git a/spec/ruby/core/enumerable/drop_while_spec.rb b/spec/ruby/core/enumerable/drop_while_spec.rb index 731b9588e4..636c3d284a 100644 --- a/spec/ruby/core/enumerable/drop_while_spec.rb +++ b/spec/ruby/core/enumerable/drop_while_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#drop_while" do before :each do diff --git a/spec/ruby/core/enumerable/each_cons_spec.rb b/spec/ruby/core/enumerable/each_cons_spec.rb index 6720199bc3..ed77741862 100644 --- a/spec/ruby/core/enumerable/each_cons_spec.rb +++ b/spec/ruby/core/enumerable/each_cons_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumeratorized' describe "Enumerable#each_cons" do before :each do @@ -10,24 +10,24 @@ describe "Enumerable#each_cons" do it "passes element groups to the block" do acc = [] - @enum.each_cons(3){|g| acc << g}.should be_nil + @enum.each_cons(3){|g| acc << g} acc.should == @in_threes end it "raises an ArgumentError if there is not a single parameter > 0" do - lambda{ @enum.each_cons(0){} }.should raise_error(ArgumentError) - lambda{ @enum.each_cons(-2){} }.should raise_error(ArgumentError) - lambda{ @enum.each_cons{} }.should raise_error(ArgumentError) - lambda{ @enum.each_cons(2,2){} }.should raise_error(ArgumentError) - lambda{ @enum.each_cons(0) }.should raise_error(ArgumentError) - lambda{ @enum.each_cons(-2) }.should raise_error(ArgumentError) - lambda{ @enum.each_cons }.should raise_error(ArgumentError) - lambda{ @enum.each_cons(2,2) }.should raise_error(ArgumentError) + ->{ @enum.each_cons(0){} }.should raise_error(ArgumentError) + ->{ @enum.each_cons(-2){} }.should raise_error(ArgumentError) + ->{ @enum.each_cons{} }.should raise_error(ArgumentError) + ->{ @enum.each_cons(2,2){} }.should raise_error(ArgumentError) + ->{ @enum.each_cons(0) }.should raise_error(ArgumentError) + ->{ @enum.each_cons(-2) }.should raise_error(ArgumentError) + ->{ @enum.each_cons }.should raise_error(ArgumentError) + ->{ @enum.each_cons(2,2) }.should raise_error(ArgumentError) end it "tries to convert n to an Integer using #to_int" do acc = [] - @enum.each_cons(3.3){|g| acc << g}.should == nil + @enum.each_cons(3.3){|g| acc << g} acc.should == @in_threes obj = mock('to_int') @@ -56,6 +56,10 @@ describe "Enumerable#each_cons" do multi.each_cons(2).to_a.should == [[[1, 2], [3, 4, 5]], [[3, 4, 5], [6, 7, 8, 9]]] end + it "returns self when a block is given" do + @enum.each_cons(3){}.should == @enum + end + describe "when no block is given" do it "returns an enumerator" do e = @enum.each_cons(3) diff --git a/spec/ruby/core/enumerable/each_entry_spec.rb b/spec/ruby/core/enumerable/each_entry_spec.rb index 05d181a998..edf00f3137 100644 --- a/spec/ruby/core/enumerable/each_entry_spec.rb +++ b/spec/ruby/core/enumerable/each_entry_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#each_entry" do before :each do @@ -27,8 +27,8 @@ describe "Enumerable#each_entry" do end it "raises an ArgumentError when extra arguments" do - lambda { @enum.each_entry("one").to_a }.should raise_error(ArgumentError) - lambda { @enum.each_entry("one"){}.to_a }.should raise_error(ArgumentError) + -> { @enum.each_entry("one").to_a }.should raise_error(ArgumentError) + -> { @enum.each_entry("one"){}.to_a }.should raise_error(ArgumentError) end it "passes extra arguments to #each" do diff --git a/spec/ruby/core/enumerable/each_slice_spec.rb b/spec/ruby/core/enumerable/each_slice_spec.rb index 62503fe206..47b8c9ba33 100644 --- a/spec/ruby/core/enumerable/each_slice_spec.rb +++ b/spec/ruby/core/enumerable/each_slice_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumeratorized' describe "Enumerable#each_slice" do before :each do @@ -10,24 +10,24 @@ describe "Enumerable#each_slice" do it "passes element groups to the block" do acc = [] - @enum.each_slice(3){|g| acc << g}.should be_nil + @enum.each_slice(3){|g| acc << g} acc.should == @sliced end it "raises an ArgumentError if there is not a single parameter > 0" do - lambda{ @enum.each_slice(0){} }.should raise_error(ArgumentError) - lambda{ @enum.each_slice(-2){} }.should raise_error(ArgumentError) - lambda{ @enum.each_slice{} }.should raise_error(ArgumentError) - lambda{ @enum.each_slice(2,2){} }.should raise_error(ArgumentError) - lambda{ @enum.each_slice(0) }.should raise_error(ArgumentError) - lambda{ @enum.each_slice(-2) }.should raise_error(ArgumentError) - lambda{ @enum.each_slice }.should raise_error(ArgumentError) - lambda{ @enum.each_slice(2,2) }.should raise_error(ArgumentError) + ->{ @enum.each_slice(0){} }.should raise_error(ArgumentError) + ->{ @enum.each_slice(-2){} }.should raise_error(ArgumentError) + ->{ @enum.each_slice{} }.should raise_error(ArgumentError) + ->{ @enum.each_slice(2,2){} }.should raise_error(ArgumentError) + ->{ @enum.each_slice(0) }.should raise_error(ArgumentError) + ->{ @enum.each_slice(-2) }.should raise_error(ArgumentError) + ->{ @enum.each_slice }.should raise_error(ArgumentError) + ->{ @enum.each_slice(2,2) }.should raise_error(ArgumentError) end it "tries to convert n to an Integer using #to_int" do acc = [] - @enum.each_slice(3.3){|g| acc << g}.should == nil + @enum.each_slice(3.3){|g| acc << g} acc.should == @sliced obj = mock('to_int') @@ -57,6 +57,10 @@ describe "Enumerable#each_slice" do e.to_a.should == @sliced end + it "returns self when a block is given" do + @enum.each_slice(3){}.should == @enum + end + it "gathers whole arrays as elements when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new multi.each_slice(2).to_a.should == [[[1, 2], [3, 4, 5]], [[6, 7, 8, 9]]] diff --git a/spec/ruby/core/enumerable/each_with_index_spec.rb b/spec/ruby/core/enumerable/each_with_index_spec.rb index 9884e71167..122e88eab7 100644 --- a/spec/ruby/core/enumerable/each_with_index_spec.rb +++ b/spec/ruby/core/enumerable/each_with_index_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#each_with_index" do diff --git a/spec/ruby/core/enumerable/each_with_object_spec.rb b/spec/ruby/core/enumerable/each_with_object_spec.rb index 13a7c1c66d..35665e7019 100644 --- a/spec/ruby/core/enumerable/each_with_object_spec.rb +++ b/spec/ruby/core/enumerable/each_with_object_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#each_with_object" do before :each do diff --git a/spec/ruby/core/enumerable/entries_spec.rb b/spec/ruby/core/enumerable/entries_spec.rb index 94eceee713..2de4fc756a 100644 --- a/spec/ruby/core/enumerable/entries_spec.rb +++ b/spec/ruby/core/enumerable/entries_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/entries', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/entries' describe "Enumerable#entries" do - it_behaves_like(:enumerable_entries , :entries) + it_behaves_like :enumerable_entries, :entries end diff --git a/spec/ruby/core/enumerable/filter_map_spec.rb b/spec/ruby/core/enumerable/filter_map_spec.rb new file mode 100644 index 0000000000..aa4894230b --- /dev/null +++ b/spec/ruby/core/enumerable/filter_map_spec.rb @@ -0,0 +1,24 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +describe 'Enumerable#filter_map' do + before :each do + @numerous = EnumerableSpecs::Numerous.new(*(1..8).to_a) + end + + it 'returns an empty array if there are no elements' do + EnumerableSpecs::Empty.new.filter_map { true }.should == [] + end + + it 'returns an array with truthy results of passing each element to block' do + @numerous.filter_map { |i| i * 2 if i.even? }.should == [4, 8, 12, 16] + @numerous.filter_map { |i| i * 2 }.should == [2, 4, 6, 8, 10, 12, 14, 16] + @numerous.filter_map { 0 }.should == [0, 0, 0, 0, 0, 0, 0, 0] + @numerous.filter_map { false }.should == [] + @numerous.filter_map { nil }.should == [] + end + + it 'returns an enumerator when no block given' do + @numerous.filter_map.should be_an_instance_of(Enumerator) + end +end diff --git a/spec/ruby/core/enumerable/filter_spec.rb b/spec/ruby/core/enumerable/filter_spec.rb new file mode 100644 index 0000000000..1c3a7e9ff5 --- /dev/null +++ b/spec/ruby/core/enumerable/filter_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/find_all' + +describe "Enumerable#filter" do + it_behaves_like :enumerable_find_all, :filter +end diff --git a/spec/ruby/core/enumerable/find_all_spec.rb b/spec/ruby/core/enumerable/find_all_spec.rb index 3d587d7709..9cd635f247 100644 --- a/spec/ruby/core/enumerable/find_all_spec.rb +++ b/spec/ruby/core/enumerable/find_all_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/find_all', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/find_all' describe "Enumerable#find_all" do - it_behaves_like(:enumerable_find_all , :find_all) + it_behaves_like :enumerable_find_all, :find_all end diff --git a/spec/ruby/core/enumerable/find_index_spec.rb b/spec/ruby/core/enumerable/find_index_spec.rb index c118a61fcf..542660fe04 100644 --- a/spec/ruby/core/enumerable/find_index_spec.rb +++ b/spec/ruby/core/enumerable/find_index_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#find_index" do before :each do diff --git a/spec/ruby/core/enumerable/find_spec.rb b/spec/ruby/core/enumerable/find_spec.rb index 62e1194537..5ddebc05f8 100644 --- a/spec/ruby/core/enumerable/find_spec.rb +++ b/spec/ruby/core/enumerable/find_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/find', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/find' describe "Enumerable#find" do - it_behaves_like(:enumerable_find , :find) + it_behaves_like :enumerable_find, :find end diff --git a/spec/ruby/core/enumerable/first_spec.rb b/spec/ruby/core/enumerable/first_spec.rb index a85550ee3b..ed1ba599b4 100644 --- a/spec/ruby/core/enumerable/first_spec.rb +++ b/spec/ruby/core/enumerable/first_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/take', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/take' describe "Enumerable#first" do it "returns the first element" do @@ -19,7 +19,7 @@ describe "Enumerable#first" do it "raises a RangeError when passed a Bignum" do enum = EnumerableSpecs::Empty.new - lambda { enum.first(bignum_value) }.should raise_error(RangeError) + -> { enum.first(bignum_value) }.should raise_error(RangeError) end describe "when passed an argument" do diff --git a/spec/ruby/core/enumerable/fixtures/classes.rb b/spec/ruby/core/enumerable/fixtures/classes.rb index 26a8aff8e2..b5feafcfb7 100644 --- a/spec/ruby/core/enumerable/fixtures/classes.rb +++ b/spec/ruby/core/enumerable/fixtures/classes.rb @@ -38,12 +38,14 @@ module EnumerableSpecs class Empty include Enumerable def each + self end end class EmptyWithSize include Enumerable def each + self end def size 0 @@ -118,7 +120,7 @@ module EnumerableSpecs end end - class ArrayConvertable + class ArrayConvertible attr_accessor :called def initialize(*values) @values = values @@ -135,7 +137,7 @@ module EnumerableSpecs end end - class EnumConvertable + class EnumConvertible attr_accessor :called attr_accessor :sym def initialize(delegate) @@ -251,7 +253,7 @@ module EnumerableSpecs end end - class ComparableWithFixnum + class ComparableWithInteger include Comparable def initialize(num) @num = num @@ -328,4 +330,21 @@ module EnumerableSpecs EnumerableMapping.new(self, block) end end + + class Pattern + attr_reader :yielded + + def initialize(&block) + @block = block + @yielded = [] + end + + def ===(*args) + @yielded << args + @block.call(*args) + end + end + + class SetSubclass < Set + end end # EnumerableSpecs utility classes diff --git a/spec/ruby/core/enumerable/flat_map_spec.rb b/spec/ruby/core/enumerable/flat_map_spec.rb index aaddeed05d..bd07eab6c5 100644 --- a/spec/ruby/core/enumerable/flat_map_spec.rb +++ b/spec/ruby/core/enumerable/flat_map_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/collect_concat', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/collect_concat' describe "Enumerable#flat_map" do - it_behaves_like(:enumerable_collect_concat , :flat_map) + it_behaves_like :enumerable_collect_concat, :flat_map end diff --git a/spec/ruby/core/enumerable/grep_spec.rb b/spec/ruby/core/enumerable/grep_spec.rb index 777d5e538e..989358f01b 100644 --- a/spec/ruby/core/enumerable/grep_spec.rb +++ b/spec/ruby/core/enumerable/grep_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#grep" do before :each do @@ -29,6 +29,41 @@ describe "Enumerable#grep" do ary.grep(/a(b)a/) { $1 }.should == ["b", "b"] end + it "sets $~ in the block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep(/b/) { |e| + e.should == "abc" + $&.should == "b" + } + + # Set by the failed match of "def" + $~.should == nil + end + + it "does not set $~ when given no block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep(/b/).should == ["abc"] + $&.should == "z" + end + + it "does not modify Regexp.last_match without block" do + "z" =~ /z/ # Reset last match + ["abc", "def"].grep(/b/).should == ["abc"] + Regexp.last_match[0].should == "z" + end + + it "correctly handles non-string elements" do + 'set last match' =~ /set last (.*)/ + [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/).should == [:a, 'b', :c] + $1.should == 'match' + + o = Object.new + def o.to_str + 'hello' + end + [o].grep(/ll/).first.should.equal?(o) + end + describe "with a block" do before :each do @numerous = EnumerableSpecs::Numerous.new(*(0..9).to_a) diff --git a/spec/ruby/core/enumerable/grep_v_spec.rb b/spec/ruby/core/enumerable/grep_v_spec.rb index 05c43a43ef..ba19216968 100644 --- a/spec/ruby/core/enumerable/grep_v_spec.rb +++ b/spec/ruby/core/enumerable/grep_v_spec.rb @@ -1,43 +1,76 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) - -ruby_version_is "2.3" do - describe "Enumerable#grep_v" do - before :each do - @numerous = EnumerableSpecs::Numerous.new(*(0..9).to_a) - def (@odd_matcher = BasicObject.new).===(obj) - obj.odd? - end - end - - describe "without block" do - it "returns an Array of matched elements" do - @numerous.grep_v(@odd_matcher).should == [0, 2, 4, 6, 8] - end - - it "compares pattern with gathered array when yielded with multiple arguments" do - (unmatcher = Object.new).stub!(:===).and_return(false) - EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher).should == EnumerableSpecs::YieldsMixed2.gathered_yields - end - - it "raises an ArgumentError when not given a pattern" do - -> { @numerous.grep_v }.should raise_error(ArgumentError) - end - end - - describe "with block" do - it "returns an Array of matched elements that mapped by the block" do - @numerous.grep_v(@odd_matcher) { |n| n * 2 }.should == [0, 4, 8, 12, 16] - end - - it "calls the block with gathered array when yielded with multiple arguments" do - (unmatcher = Object.new).stub!(:===).and_return(false) - EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher){ |e| e }.should == EnumerableSpecs::YieldsMixed2.gathered_yields - end - - it "raises an ArgumentError when not given a pattern" do - -> { @numerous.grep_v { |e| e } }.should raise_error(ArgumentError) - end +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +describe "Enumerable#grep_v" do + before :each do + @numerous = EnumerableSpecs::Numerous.new(*(0..9).to_a) + def (@odd_matcher = BasicObject.new).===(obj) + obj.odd? + end + end + + it "sets $~ in the block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep_v(/e/) { |e| + e.should == "abc" + $~.should == nil + } + + # Set by the match of "def" + $&.should == "e" + end + + it "does not set $~ when given no block" do + "z" =~ /z/ # Reset $~ + ["abc", "def"].grep_v(/e/).should == ["abc"] + $&.should == "z" + end + + it "does not modify Regexp.last_match without block" do + "z" =~ /z/ # Reset last match + ["abc", "def"].grep_v(/e/).should == ["abc"] + Regexp.last_match[0].should == "z" + end + + it "correctly handles non-string elements" do + 'set last match' =~ /set last (.*)/ + [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/).should == ['z', 42, nil] + $1.should == 'match' + + o = Object.new + def o.to_str + 'hello' + end + [o].grep_v(/mm/).first.should.equal?(o) + end + + describe "without block" do + it "returns an Array of matched elements" do + @numerous.grep_v(@odd_matcher).should == [0, 2, 4, 6, 8] + end + + it "compares pattern with gathered array when yielded with multiple arguments" do + (unmatcher = Object.new).stub!(:===).and_return(false) + EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher).should == EnumerableSpecs::YieldsMixed2.gathered_yields + end + + it "raises an ArgumentError when not given a pattern" do + -> { @numerous.grep_v }.should raise_error(ArgumentError) + end + end + + describe "with block" do + it "returns an Array of matched elements that mapped by the block" do + @numerous.grep_v(@odd_matcher) { |n| n * 2 }.should == [0, 4, 8, 12, 16] + end + + it "calls the block with gathered array when yielded with multiple arguments" do + (unmatcher = Object.new).stub!(:===).and_return(false) + EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher){ |e| e }.should == EnumerableSpecs::YieldsMixed2.gathered_yields + end + + it "raises an ArgumentError when not given a pattern" do + -> { @numerous.grep_v { |e| e } }.should raise_error(ArgumentError) end end end diff --git a/spec/ruby/core/enumerable/group_by_spec.rb b/spec/ruby/core/enumerable/group_by_spec.rb index 3513512ebf..4fd1603819 100644 --- a/spec/ruby/core/enumerable/group_by_spec.rb +++ b/spec/ruby/core/enumerable/group_by_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#group_by" do it "returns a hash with values grouped according to the block" do @@ -33,13 +33,5 @@ describe "Enumerable#group_by" do [3, 4, 5] => [[3, 4, 5]] } end - it "returns a tainted hash if self is tainted" do - EnumerableSpecs::Empty.new.taint.group_by {}.tainted?.should be_true - end - - it "returns an untrusted hash if self is untrusted" do - EnumerableSpecs::Empty.new.untrust.group_by {}.untrusted?.should be_true - end - it_behaves_like :enumerable_enumeratorized_with_origin_size, :group_by end diff --git a/spec/ruby/core/enumerable/include_spec.rb b/spec/ruby/core/enumerable/include_spec.rb index 2cc0b6e83a..dab1b04451 100644 --- a/spec/ruby/core/enumerable/include_spec.rb +++ b/spec/ruby/core/enumerable/include_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/include', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/include' describe "Enumerable#include?" do - it_behaves_like(:enumerable_include, :include?) + it_behaves_like :enumerable_include, :include? end diff --git a/spec/ruby/core/enumerable/inject_spec.rb b/spec/ruby/core/enumerable/inject_spec.rb index 289a451552..e1fe216144 100644 --- a/spec/ruby/core/enumerable/inject_spec.rb +++ b/spec/ruby/core/enumerable/inject_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/inject', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/inject' describe "Enumerable#inject" do it_behaves_like :enumerable_inject, :inject diff --git a/spec/ruby/core/enumerable/lazy_spec.rb b/spec/ruby/core/enumerable/lazy_spec.rb index f989fb947e..9a9ead81a0 100644 --- a/spec/ruby/core/enumerable/lazy_spec.rb +++ b/spec/ruby/core/enumerable/lazy_spec.rb @@ -1,7 +1,7 @@ # -*- encoding: us-ascii -*- -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#lazy" do it "returns an instance of Enumerator::Lazy" do diff --git a/spec/ruby/core/enumerable/map_spec.rb b/spec/ruby/core/enumerable/map_spec.rb index b2ddf1eb9d..98a70781cf 100644 --- a/spec/ruby/core/enumerable/map_spec.rb +++ b/spec/ruby/core/enumerable/map_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/collect', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/collect' describe "Enumerable#map" do - it_behaves_like(:enumerable_collect , :map) + it_behaves_like :enumerable_collect, :map end diff --git a/spec/ruby/core/enumerable/max_by_spec.rb b/spec/ruby/core/enumerable/max_by_spec.rb index 4058cf0a40..ec1738ea3b 100644 --- a/spec/ruby/core/enumerable/max_by_spec.rb +++ b/spec/ruby/core/enumerable/max_by_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#max_by" do it "returns an enumerator if no block" do @@ -67,7 +67,7 @@ describe "Enumerable#max_by" do context "when n is negative" do it "raises an ArgumentError" do - lambda { @enum.max_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError) + -> { @enum.max_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError) end end end diff --git a/spec/ruby/core/enumerable/max_spec.rb b/spec/ruby/core/enumerable/max_spec.rb index e283a5d0e2..0c11ca0969 100644 --- a/spec/ruby/core/enumerable/max_spec.rb +++ b/spec/ruby/core/enumerable/max_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#max" do before :each do @@ -36,16 +36,16 @@ describe "Enumerable#max" do end it "raises a NoMethodError for elements without #<=>" do - lambda do + -> do EnumerableSpecs::EachDefiner.new(BasicObject.new, BasicObject.new).max end.should raise_error(NoMethodError) end it "raises an ArgumentError for incomparable elements" do - lambda do + -> do EnumerableSpecs::EachDefiner.new(11,"22").max end.should raise_error(ArgumentError) - lambda do + -> do EnumerableSpecs::EachDefiner.new(11,12,22,33).max{|a, b| nil} end.should raise_error(ArgumentError) end @@ -106,7 +106,7 @@ describe "Enumerable#max" do context "that is negative" do it "raises an ArgumentError" do - lambda { @e_ints.max(-1) }.should raise_error(ArgumentError) + -> { @e_ints.max(-1) }.should raise_error(ArgumentError) end end end diff --git a/spec/ruby/core/enumerable/member_spec.rb b/spec/ruby/core/enumerable/member_spec.rb index 862c949817..1fe3cebd28 100644 --- a/spec/ruby/core/enumerable/member_spec.rb +++ b/spec/ruby/core/enumerable/member_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/include', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/include' describe "Enumerable#member?" do - it_behaves_like(:enumerable_include, :member?) + it_behaves_like :enumerable_include, :member? end diff --git a/spec/ruby/core/enumerable/min_by_spec.rb b/spec/ruby/core/enumerable/min_by_spec.rb index 24fe995f09..3ff87e49d8 100644 --- a/spec/ruby/core/enumerable/min_by_spec.rb +++ b/spec/ruby/core/enumerable/min_by_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#min_by" do it "returns an enumerator if no block" do @@ -67,7 +67,7 @@ describe "Enumerable#min_by" do context "when n is negative" do it "raises an ArgumentError" do - lambda { @enum.min_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError) + -> { @enum.min_by(-1) { |i| i.to_s } }.should raise_error(ArgumentError) end end end diff --git a/spec/ruby/core/enumerable/min_spec.rb b/spec/ruby/core/enumerable/min_spec.rb index f56d0420c9..4b6ae248fa 100644 --- a/spec/ruby/core/enumerable/min_spec.rb +++ b/spec/ruby/core/enumerable/min_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#min" do before :each do @@ -36,16 +36,16 @@ describe "Enumerable#min" do end it "raises a NoMethodError for elements without #<=>" do - lambda do + -> do EnumerableSpecs::EachDefiner.new(BasicObject.new, BasicObject.new).min end.should raise_error(NoMethodError) end it "raises an ArgumentError for incomparable elements" do - lambda do + -> do EnumerableSpecs::EachDefiner.new(11,"22").min end.should raise_error(ArgumentError) - lambda do + -> do EnumerableSpecs::EachDefiner.new(11,12,22,33).min{|a, b| nil} end.should raise_error(ArgumentError) end @@ -110,7 +110,7 @@ describe "Enumerable#min" do context "that is negative" do it "raises an ArgumentError" do - lambda { @e_ints.min(-1) }.should raise_error(ArgumentError) + -> { @e_ints.min(-1) }.should raise_error(ArgumentError) end end end diff --git a/spec/ruby/core/enumerable/minmax_by_spec.rb b/spec/ruby/core/enumerable/minmax_by_spec.rb index c92eb381a4..a6a9249270 100644 --- a/spec/ruby/core/enumerable/minmax_by_spec.rb +++ b/spec/ruby/core/enumerable/minmax_by_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#minmax_by" do it "returns an enumerator if no block" do diff --git a/spec/ruby/core/enumerable/minmax_spec.rb b/spec/ruby/core/enumerable/minmax_spec.rb index 10bc9b68e4..f5f17ef079 100644 --- a/spec/ruby/core/enumerable/minmax_spec.rb +++ b/spec/ruby/core/enumerable/minmax_spec.rb @@ -1,41 +1,17 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative '../../shared/enumerable/minmax' describe "Enumerable#minmax" do before :each do @enum = EnumerableSpecs::Numerous.new(6, 4, 5, 10, 8) - + @empty_enum = EnumerableSpecs::Empty.new + @incomparable_enum = EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new) + @incompatible_enum = EnumerableSpecs::Numerous.new(11,"22") @strs = EnumerableSpecs::Numerous.new("333", "2", "60", "55555", "1010", "111") end - it "min should return the minimum element" do - @enum.minmax.should == [4, 10] - @strs.minmax.should == ["1010", "60" ] - end - - it "returns [nil, nil] for an empty Enumerable" do - EnumerableSpecs::Empty.new.minmax.should == [nil, nil] - end - - it "raises an ArgumentError when elements are incomparable" do - lambda do - EnumerableSpecs::Numerous.new(11,"22").minmax - end.should raise_error(ArgumentError) - lambda do - EnumerableSpecs::Numerous.new(11,12,22,33).minmax{|a, b| nil} - end.should raise_error(ArgumentError) - end - - it "raises a NoMethodError for elements without #<=>" do - lambda do - EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new).minmax - end.should raise_error(NoMethodError) - end - - it "returns the minimum when using a block rule" do - @enum.minmax {|a,b| b <=> a }.should == [10, 4] - @strs.minmax {|a,b| a.length <=> b.length }.should == ["2", "55555"] - end + it_behaves_like :enumerable_minmax, :minmax it "gathers whole arrays as elements when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new diff --git a/spec/ruby/core/enumerable/none_spec.rb b/spec/ruby/core/enumerable/none_spec.rb index 89472d6ee1..fb42f13386 100644 --- a/spec/ruby/core/enumerable/none_spec.rb +++ b/spec/ruby/core/enumerable/none_spec.rb @@ -1,68 +1,153 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#none?" do - it "returns true if none of the elements in self are true" do - e = EnumerableSpecs::Numerous.new(false, nil, false) - e.none?.should be_true + before :each do + @empty = EnumerableSpecs::Empty.new + @enum = EnumerableSpecs::Numerous.new + @enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1) + @enum2 = EnumerableSpecs::Numerous.new(nil, false, true) end - it "returns false if at least one of the elements in self are true" do - e = EnumerableSpecs::Numerous.new(false, nil, true, false) - e.none?.should be_false + it "always returns true on empty enumeration" do + @empty.should.none? + @empty.none? { true }.should == true end - it "gathers whole arrays as elements when each yields multiple" do - # This spec doesn't spec what it says it does - multi = EnumerableSpecs::YieldsMultiWithFalse.new - multi.none?.should be_false + it "raises an ArgumentError when more than 1 argument is provided" do + -> { @enum.none?(1, 2, 3) }.should raise_error(ArgumentError) + -> { [].none?(1, 2, 3) }.should raise_error(ArgumentError) + -> { {}.none?(1, 2, 3) }.should raise_error(ArgumentError) end - ruby_version_is "2.5" do - describe "given a pattern argument" do - # This spec should be replaced by more extensive ones - it "returns true iff none match that pattern" do - EnumerableSpecs::Numerous.new.none?(Float).should == true - [nil, false, true].none?(NilClass).should == false - end - end - end -end + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.none? + }.should raise_error(RuntimeError) -describe "Enumerable#none? with a block" do - before :each do - @e = EnumerableSpecs::Numerous.new(1,1,2,3,4) + -> { + EnumerableSpecs::ThrowingEach.new.none? { false } + }.should raise_error(RuntimeError) end - it "passes each element to the block in turn until it returns true" do - acc = [] - @e.none? {|e| acc << e; false } - acc.should == [1,1,2,3,4] - end + describe "with no block" do + it "returns true if none of the elements in self are true" do + e = EnumerableSpecs::Numerous.new(false, nil, false) + e.none?.should be_true + end - it "stops passing elements to the block when it returns true" do - acc = [] - @e.none? {|e| acc << e; e == 3 ? true : false } - acc.should == [1,1,2,3] - end + it "returns false if at least one of the elements in self are true" do + e = EnumerableSpecs::Numerous.new(false, nil, true, false) + e.none?.should be_false + end - it "returns true if the block never returns true" do - @e.none? {|e| false }.should be_true + it "gathers whole arrays as elements when each yields multiple" do + multi = EnumerableSpecs::YieldsMultiWithFalse.new + multi.none?.should be_false + end end - it "returns false if the block ever returns true" do - @e.none? {|e| e == 3 ? true : false }.should be_false - end + describe "with a block" do + before :each do + @e = EnumerableSpecs::Numerous.new(1,1,2,3,4) + end + + it "passes each element to the block in turn until it returns true" do + acc = [] + @e.none? {|e| acc << e; false } + acc.should == [1,1,2,3,4] + end + + it "stops passing elements to the block when it returns true" do + acc = [] + @e.none? {|e| acc << e; e == 3 ? true : false } + acc.should == [1,1,2,3] + end + + it "returns true if the block never returns true" do + @e.none? {|e| false }.should be_true + end + + it "returns false if the block ever returns true" do + @e.none? {|e| e == 3 ? true : false }.should be_false + end + + it "does not hide exceptions out of the block" do + -> { + @enum.none? { raise "from block" } + }.should raise_error(RuntimeError) + end + + it "gathers initial args as elements when each yields multiple" do + multi = EnumerableSpecs::YieldsMulti.new + yielded = [] + multi.none? { |e| yielded << e; false } + yielded.should == [1, 3, 6] + end - it "gathers initial args as elements when each yields multiple" do - multi = EnumerableSpecs::YieldsMulti.new - multi.none? {|e| e == [1, 2] }.should be_true + it "yields multiple arguments when each yields multiple" do + multi = EnumerableSpecs::YieldsMulti.new + yielded = [] + multi.none? { |*args| yielded << args; false } + yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]] + end end - it "yields multiple arguments when each yields multiple" do - multi = EnumerableSpecs::YieldsMulti.new - yielded = [] - multi.none? {|e, i| yielded << [e, i] } - yielded.should == [[1, 2]] + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x == 3 } + @enum1.none?(pattern).should == true + pattern.yielded.should == [[0], [1], [2], [-1]] + end + + it "always returns true on empty enumeration" do + @empty.none?(Integer).should == true + [].none?(Integer).should == true + {}.none?(NilClass).should == true + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.none?(Integer) + }.should raise_error(RuntimeError) + end + + it "returns true if the pattern never returns a truthy value" do + @enum2.none?(Integer).should == true + pattern = EnumerableSpecs::Pattern.new { |x| nil } + @enum.none?(pattern).should == true + + [1, 42, 3].none?(pattern).should == true + {a: 1, b: 2}.none?(pattern).should == true + end + + it "returns false if the pattern ever returns other than false or nil" do + pattern = EnumerableSpecs::Pattern.new { |x| x < 0 } + @enum1.none?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3, -1].none?(pattern).should == false + {a: 1}.none?(Array).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.none?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { false } + multi.none?(pattern).should == true + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] + end + + it "ignores the block if there is an argument" do + -> { + EnumerableSpecs::Numerous.new(1, 2, 3, 4, 5).none?(String) { true }.should == true + }.should complain(/given block not used/) + end end end diff --git a/spec/ruby/core/enumerable/one_spec.rb b/spec/ruby/core/enumerable/one_spec.rb index 5f118e3323..4bf8623d2e 100644 --- a/spec/ruby/core/enumerable/one_spec.rb +++ b/spec/ruby/core/enumerable/one_spec.rb @@ -1,8 +1,55 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#one?" do - describe "when passed a block" do + before :each do + @empty = EnumerableSpecs::Empty.new + @enum = EnumerableSpecs::Numerous.new + @enum1 = EnumerableSpecs::Numerous.new(0, 1, 2, -1) + @enum2 = EnumerableSpecs::Numerous.new(nil, false, true) + end + + it "always returns false on empty enumeration" do + @empty.should_not.one? + @empty.one? { true }.should == false + end + + it "raises an ArgumentError when more than 1 argument is provided" do + -> { @enum.one?(1, 2, 3) }.should raise_error(ArgumentError) + -> { [].one?(1, 2, 3) }.should raise_error(ArgumentError) + -> { {}.one?(1, 2, 3) }.should raise_error(ArgumentError) + end + + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.one? + }.should raise_error(RuntimeError) + + -> { + EnumerableSpecs::ThrowingEach.new.one? { false } + }.should raise_error(RuntimeError) + end + + describe "with no block" do + it "returns true if only one element evaluates to true" do + [false, nil, true].one?.should be_true + end + + it "returns false if two elements evaluate to true" do + [false, :value, nil, true].one?.should be_false + end + + it "returns false if all elements evaluate to false" do + [false, nil, false].one?.should be_false + end + + it "gathers whole arrays as elements when each yields multiple" do + multi = EnumerableSpecs::YieldsMultiWithSingleTrue.new + multi.one?.should be_false + end + end + + describe "with a block" do it "returns true if block returns true once" do [:a, :b, :c].one? { |s| s == :a }.should be_true end @@ -15,46 +62,93 @@ describe "Enumerable#one?" do [:a, :b, :c].one? { |s| s == :d }.should be_false end + it "does not hide exceptions out of the block" do + -> { + @enum.one? { raise "from block" } + }.should raise_error(RuntimeError) + end + it "gathers initial args as elements when each yields multiple" do - # This spec doesn't spec what it says it does multi = EnumerableSpecs::YieldsMulti.new - multi.one? {|e| e == 1 }.should be_true + yielded = [] + multi.one? { |e| yielded << e; false }.should == false + yielded.should == [1, 3, 6] end it "yields multiple arguments when each yields multiple" do multi = EnumerableSpecs::YieldsMulti.new yielded = [] - multi.one? {|e, i| yielded << [e, i] } - yielded.should == [[1, 2], [3, 4]] + multi.one? { |*args| yielded << args; false }.should == false + yielded.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]] end + end - ruby_version_is "2.5" do - describe "given a pattern argument" do - # This spec should be replaced by more extensive ones - it "returns true iff none match that pattern" do - EnumerableSpecs::Numerous.new.one?(Integer).should == false - [nil, false, true].one?(NilClass).should == true - end - end + describe 'when given a pattern argument' do + it "calls `===` on the pattern the return value " do + pattern = EnumerableSpecs::Pattern.new { |x| x == 1 } + @enum1.one?(pattern).should == true + pattern.yielded.should == [[0], [1], [2], [-1]] end - end - describe "when not passed a block" do - it "returns true if only one element evaluates to true" do - [false, nil, true].one?.should be_true + it "always returns false on empty enumeration" do + @empty.one?(Integer).should == false + [].one?(Integer).should == false + {}.one?(NilClass).should == false end - it "returns false if two elements evaluate to true" do - [false, :value, nil, true].one?.should be_false + it "does not hide exceptions out of #each" do + -> { + EnumerableSpecs::ThrowingEach.new.one?(Integer) + }.should raise_error(RuntimeError) end - it "returns false if all elements evaluate to false" do - [false, nil, false].one?.should be_false + it "returns true if the pattern returns a truthy value only once" do + @enum2.one?(NilClass).should == true + pattern = EnumerableSpecs::Pattern.new { |x| x == 2 } + @enum1.one?(pattern).should == true + + [1, 2, 42, 3].one?(pattern).should == true + + pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] } + {a: 1, b: 2}.one?(pattern).should == true end - it "gathers whole arrays as elements when each yields multiple" do - multi = EnumerableSpecs::YieldsMultiWithSingleTrue.new - multi.one?.should be_false + it "returns false if the pattern returns a truthy value more than once" do + pattern = EnumerableSpecs::Pattern.new { |x| !x } + @enum2.one?(pattern).should == false + pattern.yielded.should == [[nil], [false]] + + [1, 2, 3].one?(Integer).should == false + {a: 1, b: 2}.one?(Array).should == false + end + + it "returns false if the pattern never returns a truthy value" do + pattern = EnumerableSpecs::Pattern.new { |x| nil } + @enum1.one?(pattern).should == false + pattern.yielded.should == [[0], [1], [2], [-1]] + + [1, 2, 3].one?(pattern).should == false + {a: 1}.one?(pattern).should == false + end + + it "does not hide exceptions out of pattern#===" do + pattern = EnumerableSpecs::Pattern.new { raise "from pattern" } + -> { + @enum.one?(pattern) + }.should raise_error(RuntimeError) + end + + it "calls the pattern with gathered array when yielded with multiple arguments" do + multi = EnumerableSpecs::YieldsMulti.new + pattern = EnumerableSpecs::Pattern.new { false } + multi.one?(pattern).should == false + pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]] + end + + it "ignores the block if there is an argument" do + -> { + EnumerableSpecs::Numerous.new(1, 2, 3, 4, "5").one?(String) { false }.should == true + }.should complain(/given block not used/) end end end diff --git a/spec/ruby/core/enumerable/partition_spec.rb b/spec/ruby/core/enumerable/partition_spec.rb index 4319a9328f..d3d220b4b4 100644 --- a/spec/ruby/core/enumerable/partition_spec.rb +++ b/spec/ruby/core/enumerable/partition_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#partition" do it "returns two arrays, the first containing elements for which the block is true, the second containing the rest" do diff --git a/spec/ruby/core/enumerable/reduce_spec.rb b/spec/ruby/core/enumerable/reduce_spec.rb index 8afecb2a8e..bc8691c1b0 100644 --- a/spec/ruby/core/enumerable/reduce_spec.rb +++ b/spec/ruby/core/enumerable/reduce_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/inject', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/inject' describe "Enumerable#reduce" do it_behaves_like :enumerable_inject, :reduce diff --git a/spec/ruby/core/enumerable/reject_spec.rb b/spec/ruby/core/enumerable/reject_spec.rb index 3dbfb07067..0d86b49ea2 100644 --- a/spec/ruby/core/enumerable/reject_spec.rb +++ b/spec/ruby/core/enumerable/reject_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#reject" do it "returns an array of the elements for which block is false" do diff --git a/spec/ruby/core/enumerable/reverse_each_spec.rb b/spec/ruby/core/enumerable/reverse_each_spec.rb index 62c3c0daef..2b1c233488 100644 --- a/spec/ruby/core/enumerable/reverse_each_spec.rb +++ b/spec/ruby/core/enumerable/reverse_each_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#reverse_each" do it "traverses enum in reverse order and pass each element to block" do diff --git a/spec/ruby/core/enumerable/select_spec.rb b/spec/ruby/core/enumerable/select_spec.rb index b4da35c754..7fc61926f9 100644 --- a/spec/ruby/core/enumerable/select_spec.rb +++ b/spec/ruby/core/enumerable/select_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/find_all', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/find_all' describe "Enumerable#select" do - it_behaves_like(:enumerable_find_all , :select) + it_behaves_like :enumerable_find_all, :select end diff --git a/spec/ruby/core/enumerable/shared/collect.rb b/spec/ruby/core/enumerable/shared/collect.rb index f66c539904..6df1a616eb 100644 --- a/spec/ruby/core/enumerable/shared/collect.rb +++ b/spec/ruby/core/enumerable/shared/collect.rb @@ -1,4 +1,4 @@ -require File.expand_path('../enumerable_enumeratorized', __FILE__) +require_relative 'enumerable_enumeratorized' describe :enumerable_collect, shared: true do before :each do @@ -22,11 +22,86 @@ describe :enumerable_collect, shared: true do multi.send(@method) {|e| e}.should == [1,3,6] end + it "only yields increasing values for a Range" do + (1..0).send(@method) { |x| x }.should == [] + (1..1).send(@method) { |x| x }.should == [1] + (1..2).send(@method) { |x| x }.should == [1, 2] + end + it "returns an enumerator when no block given" do enum = EnumerableSpecs::Numerous.new.send(@method) enum.should be_an_instance_of(Enumerator) enum.each { |i| -i }.should == [-2, -5, -3, -6, -1, -4] end + it "reports the same arity as the given block" do + entries = [0, 1, 3, 4, 5, 6] + numerous = EnumerableSpecs::Numerous.new(*entries) + + def numerous.each(&block) + ScratchPad << block.arity + super + end + + numerous.send(@method) { |a, b| a % 2 }.should == [0, 1, 1, 0, 1, 0] + ScratchPad.recorded.should == [2] + ScratchPad.clear + ScratchPad.record [] + numerous.send(@method) { |i| i }.should == entries + ScratchPad.recorded.should == [1] + end + + it "yields an Array of 2 elements for a Hash when block arity is 1" do + c = Class.new do + def register(a) + ScratchPad << a + end + end + m = c.new.method(:register) + + ScratchPad.record [] + { 1 => 'a', 2 => 'b' }.map(&m) + ScratchPad.recorded.should == [[1, 'a'], [2, 'b']] + end + + it "yields 2 arguments for a Hash when block arity is 2" do + c = Class.new do + def register(a, b) + ScratchPad << [a, b] + end + end + m = c.new.method(:register) + + ScratchPad.record [] + { 1 => 'a', 2 => 'b' }.map(&m) + ScratchPad.recorded.should == [[1, 'a'], [2, 'b']] + end + + it "raises an error for a Hash when an arity enforcing block of arity >2 is passed in" do + c = Class.new do + def register(a, b, c) + end + end + m = c.new.method(:register) + + -> do + { 1 => 'a', 2 => 'b' }.map(&m) + end.should raise_error(ArgumentError) + end + + it "calls the each method on sub-classes" do + c = Class.new(Hash) do + def each + ScratchPad << 'in each' + super + end + end + h = c.new + h[1] = 'a' + ScratchPad.record [] + h.send(@method) { |k,v| v } + ScratchPad.recorded.should == ['in each'] + end + it_should_behave_like :enumerable_enumeratorized_with_origin_size end diff --git a/spec/ruby/core/enumerable/shared/collect_concat.rb b/spec/ruby/core/enumerable/shared/collect_concat.rb index 54e10692eb..ddd431baeb 100644 --- a/spec/ruby/core/enumerable/shared/collect_concat.rb +++ b/spec/ruby/core/enumerable/shared/collect_concat.rb @@ -1,4 +1,4 @@ -require File.expand_path('../enumerable_enumeratorized', __FILE__) +require_relative 'enumerable_enumeratorized' describe :enumerable_collect_concat, shared: true do it "yields elements to the block and flattens one level" do @@ -41,7 +41,7 @@ describe :enumerable_collect_concat, shared: true do obj = mock("to_ary defined") obj.should_receive(:to_ary).and_return("array") - lambda { [1, obj, 3].send(@method) { |i| i } }.should raise_error(TypeError) + -> { [1, obj, 3].send(@method) { |i| i } }.should raise_error(TypeError) end it "returns an enumerator when no block given" do diff --git a/spec/ruby/core/enumerable/shared/entries.rb b/spec/ruby/core/enumerable/shared/entries.rb index f52844cb45..e32eb23d2a 100644 --- a/spec/ruby/core/enumerable/shared/entries.rb +++ b/spec/ruby/core/enumerable/shared/entries.rb @@ -13,12 +13,4 @@ describe :enumerable_entries, shared: true do count.send(@method, :hello, "world").should == [1, 2, 3] count.arguments_passed.should == [:hello, "world"] end - - it "returns a tainted array if self is tainted" do - EnumerableSpecs::Empty.new.taint.send(@method).tainted?.should be_true - end - - it "returns an untrusted array if self is untrusted" do - EnumerableSpecs::Empty.new.untrust.send(@method).untrusted?.should be_true - end end diff --git a/spec/ruby/core/enumerable/shared/enumerable_enumeratorized.rb b/spec/ruby/core/enumerable/shared/enumerable_enumeratorized.rb index b03ce9ed4e..e2bbe18eda 100644 --- a/spec/ruby/core/enumerable/shared/enumerable_enumeratorized.rb +++ b/spec/ruby/core/enumerable/shared/enumerable_enumeratorized.rb @@ -1,4 +1,4 @@ -require File.expand_path('../enumeratorized', __FILE__) +require_relative 'enumeratorized' describe :enumerable_enumeratorized_with_unknown_size, shared: true do describe "Enumerable with size" do diff --git a/spec/ruby/core/enumerable/shared/find.rb b/spec/ruby/core/enumerable/shared/find.rb index 4cbbf07be0..61d63ba3d5 100644 --- a/spec/ruby/core/enumerable/shared/find.rb +++ b/spec/ruby/core/enumerable/shared/find.rb @@ -1,4 +1,4 @@ -require File.expand_path('../enumerable_enumeratorized', __FILE__) +require_relative 'enumerable_enumeratorized' describe :enumerable_find, shared: true do # #detect and #find are aliases, so we only need one function @@ -29,26 +29,30 @@ describe :enumerable_find, shared: true do end it "returns the value of the ifnone proc if the block is false" do - fail_proc = lambda { "cheeseburgers" } + fail_proc = -> { "cheeseburgers" } @numerous.send(@method, fail_proc) {|e| false }.should == "cheeseburgers" end it "doesn't call the ifnone proc if an element is found" do - fail_proc = lambda { raise "This shouldn't have been called" } + fail_proc = -> { raise "This shouldn't have been called" } @numerous.send(@method, fail_proc) {|e| e == @elements.first }.should == 2 end it "calls the ifnone proc only once when the block is false" do times = 0 - fail_proc = lambda { times += 1; raise if times > 1; "cheeseburgers" } + fail_proc = -> { times += 1; raise if times > 1; "cheeseburgers" } @numerous.send(@method, fail_proc) {|e| false }.should == "cheeseburgers" end it "calls the ifnone proc when there are no elements" do - fail_proc = lambda { "yay" } + fail_proc = -> { "yay" } @empty.send(@method, fail_proc) {|e| true}.should == "yay" end + it "ignores the ifnone argument when nil" do + @numerous.send(@method, nil) {|e| false }.should == nil + end + it "passes through the values yielded by #each_with_index" do [:a, :b].each_with_index.send(@method) { |x, i| ScratchPad << [x, i]; nil } ScratchPad.recorded.should == [[:a, 0], [:b, 1]] @@ -60,7 +64,7 @@ describe :enumerable_find, shared: true do it "passes the ifnone proc to the enumerator" do times = 0 - fail_proc = lambda { times += 1; raise if times > 1; "cheeseburgers" } + fail_proc = -> { times += 1; raise if times > 1; "cheeseburgers" } @numerous.send(@method, fail_proc).each {|e| false }.should == "cheeseburgers" end diff --git a/spec/ruby/core/enumerable/shared/find_all.rb b/spec/ruby/core/enumerable/shared/find_all.rb index 3e15c68e9f..1bbe71f372 100644 --- a/spec/ruby/core/enumerable/shared/find_all.rb +++ b/spec/ruby/core/enumerable/shared/find_all.rb @@ -1,4 +1,4 @@ -require File.expand_path('../enumerable_enumeratorized', __FILE__) +require_relative 'enumerable_enumeratorized' describe :enumerable_find_all, shared: true do before :each do diff --git a/spec/ruby/core/enumerable/shared/inject.rb b/spec/ruby/core/enumerable/shared/inject.rb index 12e0665dda..8fb7e98c2b 100644 --- a/spec/ruby/core/enumerable/shared/inject.rb +++ b/spec/ruby/core/enumerable/shared/inject.rb @@ -1,3 +1,5 @@ +require_relative '../../array/shared/iterable_and_tolerating_size_increasing' + describe :enumerable_inject, shared: true do it "with argument takes a block with an accumulator (with argument as initial value) and the current element. Value of block becomes new accumulator" do a = [] @@ -14,14 +16,65 @@ describe :enumerable_inject, shared: true do it "can take two argument" do EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-).should == 4 + EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, "-").should == 4 + + [1, 2, 3].send(@method, 10, :-).should == 4 + [1, 2, 3].send(@method, 10, "-").should == 4 + end + + it "converts non-Symbol method name argument to String with #to_str if two arguments" do + name = Object.new + def name.to_str; "-"; end + + EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, name).should == 4 + [1, 2, 3].send(@method, 10, name).should == 4 + end + + it "raises TypeError when the second argument is not Symbol or String and it cannot be converted to String if two arguments" do + -> { EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/) + -> { [1, 2, 3].send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/) end it "ignores the block if two arguments" do - EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-){ raise "we never get here"}.should == 4 + -> { + EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-) { raise "we never get here"}.should == 4 + }.should complain(/#{__FILE__}:#{__LINE__-1}: warning: given block not used/, verbose: true) + + -> { + [1, 2, 3].send(@method, 10, :-) { raise "we never get here"}.should == 4 + }.should complain(/#{__FILE__}:#{__LINE__-1}: warning: given block not used/, verbose: true) + end + + it "does not warn when given a Symbol with $VERBOSE true" do + -> { + [1, 2].send(@method, 0, :+) + [1, 2].send(@method, :+) + EnumerableSpecs::Numerous.new(1, 2).send(@method, 0, :+) + EnumerableSpecs::Numerous.new(1, 2).send(@method, :+) + }.should_not complain(verbose: true) end it "can take a symbol argument" do EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, :-).should == 4 + [10, 1, 2, 3].send(@method, :-).should == 4 + end + + it "can take a String argument" do + EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, "-").should == 4 + [10, 1, 2, 3].send(@method, "-").should == 4 + end + + it "converts non-Symbol method name argument to String with #to_str" do + name = Object.new + def name.to_str; "-"; end + + EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, name).should == 4 + [10, 1, 2, 3].send(@method, name).should == 4 + end + + it "raises TypeError when passed not Symbol or String method name argument and it cannot be converted to String" do + -> { EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/) + -> { [10, 1, 2, 3].send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/) end it "without argument takes a block with an accumulator (with first element as initial value) and the current element. Value of block becomes new accumulator" do @@ -30,10 +83,10 @@ describe :enumerable_inject, shared: true do a.should == [[2, 5], [5, 3], [3, 6], [6, 1], [1, 4]] end - it "gathers whole arrays as elements when each yields multiple" do - multi = EnumerableSpecs::YieldsMulti.new - multi.send(@method, []) {|acc, e| acc << e }.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]] - end + it "gathers whole arrays as elements when each yields multiple" do + multi = EnumerableSpecs::YieldsMulti.new + multi.send(@method, []) {|acc, e| acc << e }.should == [[1, 2], [3, 4, 5], [6, 7, 8, 9]] + end it "with inject arguments(legacy rubycon)" do # with inject argument @@ -50,7 +103,7 @@ describe :enumerable_inject, shared: true do it "without inject arguments(legacy rubycon)" do # no inject argument - EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| 999 } .should == 2 + EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| 999 }.should == 2 EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| acc }.should == 2 EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| x }.should == 2 @@ -60,10 +113,30 @@ describe :enumerable_inject, shared: true do EnumerableSpecs::EachDefiner.new('a','b','c').send(@method) {|result, i| i+result}.should == "cba" EnumerableSpecs::EachDefiner.new(3, 4, 5).send(@method) {|result, i| result*i}.should == 60 EnumerableSpecs::EachDefiner.new([1], 2, 'a','b').send(@method){|r,i| r<<i}.should == [1, 2, 'a', 'b'] - end it "returns nil when fails(legacy rubycon)" do EnumerableSpecs::EachDefiner.new().send(@method) {|acc,x| 999 }.should == nil end + + it "tolerates increasing a collection size during iterating Array" do + array = [:a, :b, :c] + ScratchPad.record [] + i = 0 + + array.send(@method, nil) do |_, e| + ScratchPad << e + array << i if i < 100 + i += 1 + end + + actual = ScratchPad.recorded + expected = [:a, :b, :c] + (0..99).to_a + actual.sort_by(&:to_s).should == expected.sort_by(&:to_s) + end + + it "raises an ArgumentError when no parameters or block is given" do + -> { [1,2].send(@method) }.should raise_error(ArgumentError) + -> { {one: 1, two: 2}.send(@method) }.should raise_error(ArgumentError) + end end diff --git a/spec/ruby/core/enumerable/shared/take.rb b/spec/ruby/core/enumerable/shared/take.rb index bf2536acda..ce2ace20fa 100644 --- a/spec/ruby/core/enumerable/shared/take.rb +++ b/spec/ruby/core/enumerable/shared/take.rb @@ -25,7 +25,7 @@ describe :enumerable_take, shared: true do end it "raises an ArgumentError when count is negative" do - lambda { @enum.send(@method, -1) }.should raise_error(ArgumentError) + -> { @enum.send(@method, -1) }.should raise_error(ArgumentError) end it "returns the entire array when count > length" do @@ -40,11 +40,11 @@ describe :enumerable_take, shared: true do end it "raises a TypeError if the passed argument is not numeric" do - lambda { @enum.send(@method, nil) }.should raise_error(TypeError) - lambda { @enum.send(@method, "a") }.should raise_error(TypeError) + -> { @enum.send(@method, nil) }.should raise_error(TypeError) + -> { @enum.send(@method, "a") }.should raise_error(TypeError) obj = mock("nonnumeric") - lambda { @enum.send(@method, obj) }.should raise_error(TypeError) + -> { @enum.send(@method, obj) }.should raise_error(TypeError) end it "gathers whole arrays as elements when each yields multiple" do diff --git a/spec/ruby/core/enumerable/slice_after_spec.rb b/spec/ruby/core/enumerable/slice_after_spec.rb index a199b9f1ed..0e46688db1 100644 --- a/spec/ruby/core/enumerable/slice_after_spec.rb +++ b/spec/ruby/core/enumerable/slice_after_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#slice_after" do before :each do @@ -41,14 +41,14 @@ describe "Enumerable#slice_after" do describe "and an argument" do it "raises an ArgumentError" do - lambda { @enum.slice_after(42) { |i| i == 6 } }.should raise_error(ArgumentError) + -> { @enum.slice_after(42) { |i| i == 6 } }.should raise_error(ArgumentError) end end end it "raises an ArgumentError when given an incorrect number of arguments" do - lambda { @enum.slice_after("one", "two") }.should raise_error(ArgumentError) - lambda { @enum.slice_after }.should raise_error(ArgumentError) + -> { @enum.slice_after("one", "two") }.should raise_error(ArgumentError) + -> { @enum.slice_after }.should raise_error(ArgumentError) end end diff --git a/spec/ruby/core/enumerable/slice_before_spec.rb b/spec/ruby/core/enumerable/slice_before_spec.rb index 1594372d32..f9b33f7b28 100644 --- a/spec/ruby/core/enumerable/slice_before_spec.rb +++ b/spec/ruby/core/enumerable/slice_before_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#slice_before" do before :each do @@ -40,39 +40,16 @@ describe "Enumerable#slice_before" do end end - ruby_version_is ""..."2.3" do - describe "and an argument" do - it "calls the block with a copy of that argument" do - arg = [:foo] - first = nil - e = @enum.slice_before(arg) do |i, init| - init.should == arg - init.should_not equal(arg) - first = init - i == 6 || i == 2 - end - e.should be_an_instance_of(Enumerator) - e.to_a.should == [[7], [6, 5, 4, 3], [2, 1]] - e = @enum.slice_before(arg) do |i, init| - init.should_not equal(first) - end - e.to_a - end - end - end - - ruby_version_is "2.3" do - it "does not accept arguments" do - lambda { - @enum.slice_before(1) {} - }.should raise_error(ArgumentError) - end + it "does not accept arguments" do + -> { + @enum.slice_before(1) {} + }.should raise_error(ArgumentError) end end it "raises an ArgumentError when given an incorrect number of arguments" do - lambda { @enum.slice_before("one", "two") }.should raise_error(ArgumentError) - lambda { @enum.slice_before }.should raise_error(ArgumentError) + -> { @enum.slice_before("one", "two") }.should raise_error(ArgumentError) + -> { @enum.slice_before }.should raise_error(ArgumentError) end describe "when an iterator method yields more than one value" do diff --git a/spec/ruby/core/enumerable/slice_when_spec.rb b/spec/ruby/core/enumerable/slice_when_spec.rb index 593e623b1b..6b8ea0923e 100644 --- a/spec/ruby/core/enumerable/slice_when_spec.rb +++ b/spec/ruby/core/enumerable/slice_when_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#slice_when" do before :each do @@ -39,7 +39,7 @@ describe "Enumerable#slice_when" do context "when not given a block" do it "raises an ArgumentError" do - lambda { @enum.slice_when }.should raise_error(ArgumentError) + -> { @enum.slice_when }.should raise_error(ArgumentError) end end diff --git a/spec/ruby/core/enumerable/sort_by_spec.rb b/spec/ruby/core/enumerable/sort_by_spec.rb index f7df8659a8..8fdd923fb4 100644 --- a/spec/ruby/core/enumerable/sort_by_spec.rb +++ b/spec/ruby/core/enumerable/sort_by_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#sort_by" do it "returns an array of elements ordered by the result of block" do @@ -32,5 +32,12 @@ describe "Enumerable#sort_by" do b.sort_by{ |x| -x }.should == [3, 2, 1] end + it "calls #each to iterate over the elements to be sorted" do + b = EnumerableSpecs::Numerous.new( 1, 2, 3 ) + b.should_receive(:each).once.and_yield(1).and_yield(2).and_yield(3) + b.should_not_receive :map + b.sort_by { |x| -x }.should == [3, 2, 1] + end + it_behaves_like :enumerable_enumeratorized_with_origin_size, :sort_by end diff --git a/spec/ruby/core/enumerable/sort_spec.rb b/spec/ruby/core/enumerable/sort_spec.rb index a39fa7ed34..6fc64f325e 100644 --- a/spec/ruby/core/enumerable/sort_spec.rb +++ b/spec/ruby/core/enumerable/sort_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#sort" do it "sorts by the natural order as defined by <=>" do @@ -14,7 +14,7 @@ describe "Enumerable#sort" do end it "raises a NoMethodError if elements do not define <=>" do - lambda do + -> do EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new, BasicObject.new).sort end.should raise_error(NoMethodError) end @@ -31,16 +31,16 @@ describe "Enumerable#sort" do it "compare values returned by block with 0" do EnumerableSpecs::Numerous.new.sort { |n, m| -(n+m) * (n <=> m) }.should == [6, 5, 4, 3, 2, 1] EnumerableSpecs::Numerous.new.sort { |n, m| - EnumerableSpecs::ComparableWithFixnum.new(-(n+m) * (n <=> m)) + EnumerableSpecs::ComparableWithInteger.new(-(n+m) * (n <=> m)) }.should == [6, 5, 4, 3, 2, 1] - lambda { + -> { EnumerableSpecs::Numerous.new.sort { |n, m| (n <=> m).to_s } }.should raise_error(ArgumentError) end it "raises an error if objects can't be compared" do a=EnumerableSpecs::Numerous.new(EnumerableSpecs::Uncomparable.new, EnumerableSpecs::Uncomparable.new) - lambda {a.sort}.should raise_error(ArgumentError) + -> {a.sort}.should raise_error(ArgumentError) end it "gathers whole arrays as elements when each yields multiple" do diff --git a/spec/ruby/core/enumerable/sum_spec.rb b/spec/ruby/core/enumerable/sum_spec.rb index 4881039a8d..2eb74db6ac 100644 --- a/spec/ruby/core/enumerable/sum_spec.rb +++ b/spec/ruby/core/enumerable/sum_spec.rb @@ -1,30 +1,50 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' -ruby_version_is '2.4' do - describe 'Enumerable#sum' do - before :each do - @enum = Object.new.to_enum - class << @enum - def each - yield 0 - yield(-1) - yield 2 - yield 2/3r - end +describe 'Enumerable#sum' do + before :each do + @enum = Object.new.to_enum + class << @enum + def each + yield 0 + yield(-1) + yield 2 + yield 2/3r end end + end - it 'returns amount of the elements with taking an argument as the initial value' do - @enum.sum(10).should == 35/3r - end + it 'returns amount of the elements with taking an argument as the initial value' do + @enum.sum(10).should == 35/3r + end - it 'gives 0 as a default argument' do - @enum.sum.should == 5/3r - end + it 'gives 0 as a default argument' do + @enum.sum.should == 5/3r + end - it 'takes a block to transform the elements' do + context 'with a block' do + it 'transforms the elements' do @enum.sum { |element| element * 2 }.should == 10/3r end + + it 'does not destructure array elements' do + class << @enum + def each + yield [1,2] + yield [3] + end + end + + @enum.sum(&:last).should == 5 + end + end + + # https://bugs.ruby-lang.org/issues/12217 + # https://github.com/ruby/ruby/blob/master/doc/ChangeLog/ChangeLog-2.4.0#L6208-L6214 + it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do + floats = [2.7800000000000002, 5.0, 2.5, 4.44, 3.89, 3.89, 4.44, 7.78, 5.0, 2.7800000000000002, 5.0, 2.5].to_enum + naive_sum = floats.reduce { |sum, e| sum + e } + naive_sum.should == 50.00000000000001 + floats.sum.should == 50.0 end end diff --git a/spec/ruby/core/enumerable/take_spec.rb b/spec/ruby/core/enumerable/take_spec.rb index 71bf77050c..41a7438330 100644 --- a/spec/ruby/core/enumerable/take_spec.rb +++ b/spec/ruby/core/enumerable/take_spec.rb @@ -1,10 +1,10 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/take', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/take' describe "Enumerable#take" do it "requires an argument" do - lambda{ EnumerableSpecs::Numerous.new.take}.should raise_error(ArgumentError) + ->{ EnumerableSpecs::Numerous.new.take}.should raise_error(ArgumentError) end describe "when passed an argument" do diff --git a/spec/ruby/core/enumerable/take_while_spec.rb b/spec/ruby/core/enumerable/take_while_spec.rb index 990d16209a..26db39ac4b 100644 --- a/spec/ruby/core/enumerable/take_while_spec.rb +++ b/spec/ruby/core/enumerable/take_while_spec.rb @@ -1,6 +1,6 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/enumerable_enumeratorized', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/enumerable_enumeratorized' describe "Enumerable#take_while" do before :each do diff --git a/spec/ruby/core/enumerable/tally_spec.rb b/spec/ruby/core/enumerable/tally_spec.rb new file mode 100644 index 0000000000..95c64c1294 --- /dev/null +++ b/spec/ruby/core/enumerable/tally_spec.rb @@ -0,0 +1,91 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +describe "Enumerable#tally" do + before :each do + ScratchPad.record [] + end + + it "returns a hash with counts according to the value" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally.should == { 'foo' => 2, 'bar' => 1, 'baz' => 1} + end + + it "returns a hash without default" do + hash = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz').tally + hash.default_proc.should be_nil + hash.default.should be_nil + end + + it "returns an empty hash for empty enumerables" do + EnumerableSpecs::Empty.new.tally.should == {} + end + + it "counts values as gathered array when yielded with multiple arguments" do + EnumerableSpecs::YieldsMixed2.new.tally.should == EnumerableSpecs::YieldsMixed2.gathered_yields.group_by(&:itself).transform_values(&:size) + end + + it "does not call given block" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally { |v| ScratchPad << v } + ScratchPad.recorded.should == [] + end +end + +describe "Enumerable#tally with a hash" do + before :each do + ScratchPad.record [] + end + + it "returns a hash with counts according to the value" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally({ 'foo' => 1 }).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1} + end + + it "returns the given hash" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + hash = { 'foo' => 1 } + enum.tally(hash).should equal(hash) + end + + it "calls #to_hash to convert argument to Hash implicitly if passed not a Hash" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + object = Object.new + def object.to_hash; { 'foo' => 1 }; end + enum.tally(object).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1} + end + + it "raises a FrozenError and does not update the given hash when the hash is frozen" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + hash = { 'foo' => 1 }.freeze + -> { enum.tally(hash) }.should raise_error(FrozenError) + hash.should == { 'foo' => 1 } + end + + it "raises a FrozenError even if enumerable is empty" do + enum = EnumerableSpecs::Numerous.new() + hash = { 'foo' => 1 }.freeze + -> { enum.tally(hash) }.should raise_error(FrozenError) + end + + it "does not call given block" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally({ 'foo' => 1 }) { |v| ScratchPad << v } + ScratchPad.recorded.should == [] + end + + it "ignores the default value" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally(Hash.new(100)).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1} + end + + it "ignores the default proc" do + enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz') + enum.tally(Hash.new {100}).should == { 'foo' => 2, 'bar' => 1, 'baz' => 1} + end + + it "needs the values counting each elements to be an integer" do + enum = EnumerableSpecs::Numerous.new('foo') + -> { enum.tally({ 'foo' => 'bar' }) }.should raise_error(TypeError) + end +end diff --git a/spec/ruby/core/enumerable/to_a_spec.rb b/spec/ruby/core/enumerable/to_a_spec.rb index b14a3c7a1a..723f922574 100644 --- a/spec/ruby/core/enumerable/to_a_spec.rb +++ b/spec/ruby/core/enumerable/to_a_spec.rb @@ -1,7 +1,7 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) -require File.expand_path('../shared/entries', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' +require_relative 'shared/entries' describe "Enumerable#to_a" do - it_behaves_like(:enumerable_entries , :to_a) + it_behaves_like :enumerable_entries, :to_a end diff --git a/spec/ruby/core/enumerable/to_h_spec.rb b/spec/ruby/core/enumerable/to_h_spec.rb index b5b301b882..11a4933c10 100644 --- a/spec/ruby/core/enumerable/to_h_spec.rb +++ b/spec/ruby/core/enumerable/to_h_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#to_h" do it "converts empty enumerable to empty hash" do @@ -36,11 +36,61 @@ describe "Enumerable#to_h" do it "raises TypeError if an element is not an array" do enum = EnumerableSpecs::EachDefiner.new(:x) - lambda { enum.to_h }.should raise_error(TypeError) + -> { enum.to_h }.should raise_error(TypeError) end it "raises ArgumentError if an element is not a [key, value] pair" do enum = EnumerableSpecs::EachDefiner.new([:x]) - lambda { enum.to_h }.should raise_error(ArgumentError) + -> { enum.to_h }.should raise_error(ArgumentError) + end + + context "with block" do + before do + @enum = EnumerableSpecs::EachDefiner.new(:a, :b) + end + + it "converts [key, value] pairs returned by the block to a hash" do + @enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' } + end + + it "passes to a block each element as a single argument" do + enum_of_arrays = EnumerableSpecs::EachDefiner.new([:a, 1], [:b, 2]) + + ScratchPad.record [] + enum_of_arrays.to_h { |*args| ScratchPad << args; [args[0], args[1]] } + ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]] + end + + it "raises ArgumentError if block returns longer or shorter array" do + -> do + @enum.to_h { |k| [k, k.to_s, 1] } + end.should raise_error(ArgumentError, /element has wrong array length/) + + -> do + @enum.to_h { |k| [k] } + end.should raise_error(ArgumentError, /element has wrong array length/) + end + + it "raises TypeError if block returns something other than Array" do + -> do + @enum.to_h { |k| "not-array" } + end.should raise_error(TypeError, /wrong element type String/) + end + + it "coerces returned pair to Array with #to_ary" do + x = mock('x') + x.stub!(:to_ary).and_return([:b, 'b']) + + @enum.to_h { |k| x }.should == { :b => 'b' } + end + + it "does not coerce returned pair to Array with #to_a" do + x = mock('x') + x.stub!(:to_a).and_return([:b, 'b']) + + -> do + @enum.to_h { |k| x } + end.should raise_error(TypeError, /wrong element type MockObject/) + end end end diff --git a/spec/ruby/core/enumerable/to_set_spec.rb b/spec/ruby/core/enumerable/to_set_spec.rb new file mode 100644 index 0000000000..c02ead11fa --- /dev/null +++ b/spec/ruby/core/enumerable/to_set_spec.rb @@ -0,0 +1,30 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +describe "Enumerable#to_set" do + it "returns a new Set created from self" do + [1, 2, 3].to_set.should == Set[1, 2, 3] + {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]] + end + + it "passes down passed blocks" do + [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9] + end + + ruby_version_is "4.0"..."4.1" do + it "instantiates an object of provided as the first argument set class" do + set = nil + proc{set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)}.should complain(/Enumerable#to_set/) + set.should be_kind_of(EnumerableSpecs::SetSubclass) + set.to_a.sort.should == [1, 2, 3] + end + end + + ruby_version_is ""..."4.0" do + it "instantiates an object of provided as the first argument set class" do + set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass) + set.should be_kind_of(EnumerableSpecs::SetSubclass) + set.to_a.sort.should == [1, 2, 3] + end + end +end diff --git a/spec/ruby/core/enumerable/uniq_spec.rb b/spec/ruby/core/enumerable/uniq_spec.rb index 5ca7556aed..a1ed44796f 100644 --- a/spec/ruby/core/enumerable/uniq_spec.rb +++ b/spec/ruby/core/enumerable/uniq_spec.rb @@ -1,94 +1,78 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' -ruby_version_is '2.4' do - describe 'Enumerable#uniq' do - it 'returns an array that contains only unique elements' do - [0, 1, 2, 3].to_enum.uniq { |n| n.even? }.should == [0, 1] - end +describe 'Enumerable#uniq' do + it 'returns an array that contains only unique elements' do + [0, 1, 2, 3].to_enum.uniq { |n| n.even? }.should == [0, 1] + end - it "uses eql? semantics" do - [1.0, 1].to_enum.uniq.should == [1.0, 1] - end + it "uses eql? semantics" do + [1.0, 1].to_enum.uniq.should == [1.0, 1] + end - it "compares elements first with hash" do - x = mock('0') - x.should_receive(:hash).at_least(1).and_return(0) - y = mock('0') - y.should_receive(:hash).at_least(1).and_return(0) + it "compares elements first with hash" do + x = mock('0') + x.should_receive(:hash).at_least(1).and_return(0) + y = mock('0') + y.should_receive(:hash).at_least(1).and_return(0) - [x, y].to_enum.uniq.should == [x, y] - end + [x, y].to_enum.uniq.should == [x, y] + end - it "does not compare elements with different hash codes via eql?" do - x = mock('0') - x.should_not_receive(:eql?) - y = mock('1') - y.should_not_receive(:eql?) + it "does not compare elements with different hash codes via eql?" do + x = mock('0') + x.should_not_receive(:eql?) + y = mock('1') + y.should_not_receive(:eql?) - x.should_receive(:hash).at_least(1).and_return(0) - y.should_receive(:hash).at_least(1).and_return(1) + x.should_receive(:hash).at_least(1).and_return(0) + y.should_receive(:hash).at_least(1).and_return(1) - [x, y].to_enum.uniq.should == [x, y] - end + [x, y].to_enum.uniq.should == [x, y] + end - it "compares elements with matching hash codes with #eql?" do - a = Array.new(2) do - obj = mock('0') - obj.should_receive(:hash).at_least(1).and_return(0) - - def obj.eql?(o) - # It's undefined whether the impl does a[0].eql?(a[1]) or - # a[1].eql?(a[0]) so we taint both. - taint - o.taint - false - end + it "compares elements with matching hash codes with #eql?" do + a = Array.new(2) do + obj = mock('0') + obj.should_receive(:hash).at_least(1).and_return(0) - obj + def obj.eql?(o) + false end - a.uniq.should == a - a[0].tainted?.should == true - a[1].tainted?.should == true + obj + end - a = Array.new(2) do - obj = mock('0') - obj.should_receive(:hash).at_least(1).and_return(0) + a.uniq.should == a - def obj.eql?(o) - # It's undefined whether the impl does a[0].eql?(a[1]) or - # a[1].eql?(a[0]) so we taint both. - taint - o.taint - true - end + a = Array.new(2) do + obj = mock('0') + obj.should_receive(:hash).at_least(1).and_return(0) - obj + def obj.eql?(o) + true end - a.to_enum.uniq.size.should == 1 - a[0].tainted?.should == true - a[1].tainted?.should == true + obj end - context 'when yielded with multiple arguments' do - before :each do - @enum = Object.new.to_enum - class << @enum - def each - yield 0, 'foo' - yield 1, 'FOO' - yield 2, 'bar' - end - end - end + a.to_enum.uniq.size.should == 1 + end - ruby_bug '#13669', ''...'2.5' do - it 'returns all yield arguments as an array' do - @enum.uniq { |_, label| label.downcase }.should == [[0, 'foo'], [2, 'bar']] + context 'when yielded with multiple arguments' do + before :each do + @enum = Object.new.to_enum + class << @enum + def each + yield 0, 'foo' + yield 1, 'FOO' + yield 2, 'bar' end end end + + it 'returns all yield arguments as an array' do + @enum.uniq { |_, label| label.downcase }.should == [[0, 'foo'], [2, 'bar']] + end end end diff --git a/spec/ruby/core/enumerable/zip_spec.rb b/spec/ruby/core/enumerable/zip_spec.rb index 2d090f335c..ab148f2a6e 100644 --- a/spec/ruby/core/enumerable/zip_spec.rb +++ b/spec/ruby/core/enumerable/zip_spec.rb @@ -1,5 +1,5 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) +require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "Enumerable#zip" do @@ -21,16 +21,16 @@ describe "Enumerable#zip" do end it "converts arguments to arrays using #to_ary" do - convertable = EnumerableSpecs::ArrayConvertable.new(4,5,6) - EnumerableSpecs::Numerous.new(1,2,3).zip(convertable).should == [[1,4],[2,5],[3,6]] - convertable.called.should == :to_ary + convertible = EnumerableSpecs::ArrayConvertible.new(4,5,6) + EnumerableSpecs::Numerous.new(1,2,3).zip(convertible).should == [[1,4],[2,5],[3,6]] + convertible.called.should == :to_ary end it "converts arguments to enums using #to_enum" do - convertable = EnumerableSpecs::EnumConvertable.new(4..6) - EnumerableSpecs::Numerous.new(1,2,3).zip(convertable).should == [[1,4],[2,5],[3,6]] - convertable.called.should == :to_enum - convertable.sym.should == :each + convertible = EnumerableSpecs::EnumConvertible.new(4..6) + EnumerableSpecs::Numerous.new(1,2,3).zip(convertible).should == [[1,4],[2,5],[3,6]] + convertible.called.should == :to_enum + convertible.sym.should == :each end it "gathers whole arrays as elements when each yields multiple" do @@ -38,5 +38,9 @@ describe "Enumerable#zip" do multi.zip(multi).should == [[[1, 2], [1, 2]], [[3, 4, 5], [3, 4, 5]], [[6, 7, 8, 9], [6, 7, 8, 9]]] end + it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do + -> { EnumerableSpecs::Numerous.new(1,2,3).zip(Object.new) }.should raise_error(TypeError, "wrong argument type Object (must respond to :each)") + -> { EnumerableSpecs::Numerous.new(1,2,3).zip(1) }.should raise_error(TypeError, "wrong argument type Integer (must respond to :each)") + -> { EnumerableSpecs::Numerous.new(1,2,3).zip(true) }.should raise_error(TypeError, "wrong argument type TrueClass (must respond to :each)") + end end - |
