aboutsummaryrefslogtreecommitdiffstats
path: root/spec/rubyspec/shared/enumerator
diff options
context:
space:
mode:
Diffstat (limited to 'spec/rubyspec/shared/enumerator')
-rw-r--r--spec/rubyspec/shared/enumerator/each.rb89
-rw-r--r--spec/rubyspec/shared/enumerator/enum_cons.rb12
-rw-r--r--spec/rubyspec/shared/enumerator/enum_for.rb50
-rw-r--r--spec/rubyspec/shared/enumerator/new.rb42
-rw-r--r--spec/rubyspec/shared/enumerator/next.rb28
-rw-r--r--spec/rubyspec/shared/enumerator/rewind.rb39
-rw-r--r--spec/rubyspec/shared/enumerator/with_index.rb32
-rw-r--r--spec/rubyspec/shared/enumerator/with_object.rb42
8 files changed, 334 insertions, 0 deletions
diff --git a/spec/rubyspec/shared/enumerator/each.rb b/spec/rubyspec/shared/enumerator/each.rb
new file mode 100644
index 0000000000..bbab86fed7
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/each.rb
@@ -0,0 +1,89 @@
+# -*- encoding: us-ascii -*-
+
+describe :enum_each, shared: true do
+ before :each do
+ object_each_with_arguments = Object.new
+ def object_each_with_arguments.each_with_arguments(arg, *args)
+ yield arg, *args
+ :method_returned
+ end
+
+ @enum_with_arguments = object_each_with_arguments.to_enum(:each_with_arguments, :arg0, :arg1, :arg2)
+
+ @enum_with_yielder = Enumerator.new {|y| y.yield :ok}
+ end
+
+ it "yields each element of self to the given block" do
+ acc = []
+ [1,2,3].to_enum.each {|e| acc << e }
+ acc.should == [1,2,3]
+ end
+
+ it "calls #each on the object given in the constructor by default" do
+ each = mock('each')
+ each.should_receive(:each)
+ each.to_enum.each {|e| e }
+ end
+
+ it "calls #each on the underlying object until it's exhausted" do
+ each = mock('each')
+ each.should_receive(:each).and_yield(1).and_yield(2).and_yield(3)
+ acc = []
+ each.to_enum.each {|e| acc << e }
+ acc.should == [1,2,3]
+ end
+
+ it "calls the method given in the constructor instead of #each" do
+ each = mock('peach')
+ each.should_receive(:peach)
+ each.to_enum(:peach).each {|e| e }
+ end
+
+ it "calls the method given in the constructor until it's exhausted" do
+ each = mock('each')
+ each.should_receive(:each).and_yield(1).and_yield(2).and_yield(3)
+ acc = []
+ each.to_enum.each {|e| acc << e }
+ acc.should == [1,2,3]
+ end
+
+ it "raises a NoMethodError if the object doesn't respond to #each" do
+ enum = Object.new.to_enum
+ lambda do
+ enum.each { |e| e }
+ end.should raise_error(NoMethodError)
+ end
+
+ it "returns self if not given arguments and not given a block" do
+ @enum_with_arguments.each.should equal(@enum_with_arguments)
+
+ @enum_with_yielder.each.should equal(@enum_with_yielder)
+ end
+
+ it "returns the same value from receiver.each if block is given" do
+ @enum_with_arguments.each {}.should equal(:method_returned)
+ end
+
+ it "passes given arguments at initialized to receiver.each" do
+ @enum_with_arguments.each.to_a.should == [[:arg0, :arg1, :arg2]]
+ end
+
+ it "requires multiple arguments" do
+ Enumerator.instance_method(:each).arity.should < 0
+ end
+
+ it "appends given arguments to receiver.each" do
+ @enum_with_arguments.each(:each0, :each1).to_a.should == [[:arg0, :arg1, :arg2, :each0, :each1]]
+ @enum_with_arguments.each(:each2, :each3).to_a.should == [[:arg0, :arg1, :arg2, :each2, :each3]]
+ end
+
+ it "returns the same value from receiver.each if block and arguments are given" do
+ @enum_with_arguments.each(:each1, :each2) {}.should equal(:method_returned)
+ end
+
+ it "returns new Enumerator if given arguments but not given a block" do
+ ret = @enum_with_arguments.each 1
+ ret.should be_an_instance_of(Enumerator)
+ ret.should_not equal(@enum_with_arguments)
+ end
+end
diff --git a/spec/rubyspec/shared/enumerator/enum_cons.rb b/spec/rubyspec/shared/enumerator/enum_cons.rb
new file mode 100644
index 0000000000..59eed949d8
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/enum_cons.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/enumerator/classes', __FILE__)
+
+describe :enum_cons, shared: true do
+ it "returns an enumerator of the receiver with iteration of each_cons for each array of n concecutive elements" do
+ a = []
+ enum = EnumSpecs::Numerous.new.enum_cons(3)
+ enum.each {|x| a << x}
+ enum.should be_an_instance_of(Enumerator)
+ a.should == [[2, 5, 3], [5, 3, 6], [3, 6, 1], [6, 1, 4]]
+ end
+end
diff --git a/spec/rubyspec/shared/enumerator/enum_for.rb b/spec/rubyspec/shared/enumerator/enum_for.rb
new file mode 100644
index 0000000000..9030ffbd7d
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/enum_for.rb
@@ -0,0 +1,50 @@
+describe :enum_for, shared: true do
+ it "is defined in Kernel" do
+ Kernel.method_defined?(@method).should be_true
+ end
+
+ it "returns a new enumerator" do
+ "abc".send(@method).should be_an_instance_of(Enumerator)
+ end
+
+ it "defaults the first argument to :each" do
+ enum = [1,2].send(@method)
+ enum.map { |v| v }.should == [1,2].each { |v| v }
+ end
+
+ it "exposes multi-arg yields as an array" do
+ o = Object.new
+ def o.each
+ yield :a
+ yield :b1, :b2
+ yield [:c]
+ yield :d1, :d2
+ yield :e1, :e2, :e3
+ end
+
+ enum = o.send(@method)
+ enum.next.should == :a
+ enum.next.should == [:b1, :b2]
+ enum.next.should == [:c]
+ enum.next.should == [:d1, :d2]
+ enum.next.should == [:e1, :e2, :e3]
+ end
+
+ it "uses the passed block's value to calculate the size of the enumerator" do
+ Object.new.enum_for { 100 }.size.should == 100
+ end
+
+ it "defers the evaluation of the passed block until #size is called" do
+ ScratchPad.record []
+
+ enum = Object.new.enum_for do
+ ScratchPad << :called
+ 100
+ end
+
+ ScratchPad.recorded.should be_empty
+
+ enum.size
+ ScratchPad.recorded.should == [:called]
+ end
+end
diff --git a/spec/rubyspec/shared/enumerator/new.rb b/spec/rubyspec/shared/enumerator/new.rb
new file mode 100644
index 0000000000..23ace99816
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/new.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe :enum_new, shared: true do
+ it "creates a new custom enumerator with the given object, iterator and arguments" do
+ enum = Enumerator.new(1, :upto, 3)
+ enum.should be_an_instance_of(Enumerator)
+ end
+
+ it "creates a new custom enumerator that responds to #each" do
+ enum = Enumerator.new(1, :upto, 3)
+ enum.respond_to?(:each).should == true
+ end
+
+ it "creates a new custom enumerator that runs correctly" do
+ Enumerator.new(1, :upto, 3).map{|x|x}.should == [1,2,3]
+ end
+
+ it "aliases the second argument to :each" do
+ Enumerator.new(1..2).to_a.should == Enumerator.new(1..2, :each).to_a
+ end
+
+ it "doesn't check for the presence of the iterator method" do
+ Enumerator.new(nil).should be_an_instance_of(Enumerator)
+ end
+
+ it "uses the latest define iterator method" do
+ class StrangeEach
+ def each
+ yield :foo
+ end
+ end
+ enum = Enumerator.new(StrangeEach.new)
+ enum.to_a.should == [:foo]
+ class StrangeEach
+ def each
+ yield :bar
+ end
+ end
+ enum.to_a.should == [:bar]
+ end
+
+end
diff --git a/spec/rubyspec/shared/enumerator/next.rb b/spec/rubyspec/shared/enumerator/next.rb
new file mode 100644
index 0000000000..d8ae6d9673
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/next.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe :enum_next, shared: true do
+
+ before :each do
+ @enum = 1.upto(3)
+ end
+
+ it "returns the next element of the enumeration" do
+ @enum.next.should == 1
+ @enum.next.should == 2
+ @enum.next.should == 3
+ end
+
+ it "raises a StopIteration exception at the end of the stream" do
+ 3.times { @enum.next }
+ lambda { @enum.next }.should raise_error(StopIteration)
+ end
+
+ it "cannot be called again until the enumerator is rewound" do
+ 3.times { @enum.next }
+ lambda { @enum.next }.should raise_error(StopIteration)
+ lambda { @enum.next }.should raise_error(StopIteration)
+ lambda { @enum.next }.should raise_error(StopIteration)
+ @enum.rewind
+ @enum.next.should == 1
+ end
+end
diff --git a/spec/rubyspec/shared/enumerator/rewind.rb b/spec/rubyspec/shared/enumerator/rewind.rb
new file mode 100644
index 0000000000..4d4139204c
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/rewind.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe :enum_rewind, shared: true do
+
+ before :each do
+ @enum = 1.upto(3)
+ end
+
+ it "resets the enumerator to its initial state" do
+ @enum.next.should == 1
+ @enum.next.should == 2
+ @enum.rewind
+ @enum.next.should == 1
+ end
+
+ it "returns self" do
+ @enum.rewind.should == @enum
+ end
+
+ it "has no effect on a new enumerator" do
+ @enum.rewind
+ @enum.next.should == 1
+ end
+
+ it "has no effect if called multiple, consecutive times" do
+ @enum.next.should == 1
+ @enum.rewind
+ @enum.rewind
+ @enum.next.should == 1
+ end
+
+ it "works with peek to reset the position" do
+ @enum.next
+ @enum.next
+ @enum.rewind
+ @enum.next
+ @enum.peek.should == 2
+ end
+end
diff --git a/spec/rubyspec/shared/enumerator/with_index.rb b/spec/rubyspec/shared/enumerator/with_index.rb
new file mode 100644
index 0000000000..37048a7b52
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/with_index.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe :enum_with_index, shared: true do
+
+ require File.expand_path('../../../fixtures/enumerator/classes', __FILE__)
+
+ before :each do
+ @enum = [1, 2, 3, 4].to_enum
+ end
+
+ it "passes each element and its index to block" do
+ @a = []
+ @enum.send(@method) { |o, i| @a << [o, i] }
+ @a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
+ end
+
+ it "returns the object being enumerated when given a block" do
+ [1, 2, 3, 4].should == @enum.send(@method) { |o, i| :glark }
+ end
+
+ it "binds splat arguments properly" do
+ acc = []
+ @enum.send(@method) { |*b| c,d = b; acc << c; acc << d }
+ [1, 0, 2, 1, 3, 2, 4, 3].should == acc
+ end
+
+ it "returns an enumerator if no block is supplied" do
+ ewi = @enum.send(@method)
+ ewi.should be_an_instance_of(Enumerator)
+ ewi.to_a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
+ end
+end
diff --git a/spec/rubyspec/shared/enumerator/with_object.rb b/spec/rubyspec/shared/enumerator/with_object.rb
new file mode 100644
index 0000000000..1830736713
--- /dev/null
+++ b/spec/rubyspec/shared/enumerator/with_object.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe :enum_with_object, shared: true do
+ before :each do
+ @enum = [:a, :b].to_enum
+ @memo = ''
+ @block_params = @enum.send(@method, @memo).to_a
+ end
+
+ it "receives an argument" do
+ @enum.method(@method).arity.should == 1
+ end
+
+ context "with block" do
+ it "returns the given object" do
+ ret = @enum.send(@method, @memo) do |elm, memo|
+ # nothing
+ end
+ ret.should equal(@memo)
+ end
+
+ context "the block parameter" do
+ it "passes each element to first parameter" do
+ @block_params[0][0].should equal(:a)
+ @block_params[1][0].should equal(:b)
+ end
+
+ it "passes the given object to last parameter" do
+ @block_params[0][1].should equal(@memo)
+ @block_params[1][1].should equal(@memo)
+ end
+ end
+ end
+
+ context "without block" do
+ it "returns new Enumerator" do
+ ret = @enum.send(@method, @memo)
+ ret.should be_an_instance_of(Enumerator)
+ ret.should_not equal(@enum)
+ end
+ end
+end