@obj = Object.new
class << @obj
include Enumerable
def foo *a
a.each { |x| yield x }
end
end
assert 'Enumerator' do
assert_equal Class, Enumerator.class
end
assert 'Enumerator' do
assert_equal Object, Enumerator.superclass
end
assert 'Enumerator.new' do
assert_equal [0,1,2], 3.times.map{|i| i}.sort
assert_equal [:x,:y,:z], [:x,:y,:z].each.map{|i| i}.sort
assert_equal [[:x,1],[:y,2]], {x:1, y:2}.each.map{|i| i}.sort
assert_equal [1,2,3], @obj.to_enum(:foo, 1,2,3).to_a
assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a
assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
assert_raise(ArgumentError) { Enumerator.new }
enum = @obj.to_enum
assert_raise(NoMethodError) { enum.each {} }
# examples
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
assert_equal [1,1,2,3,5,8,13,21,34,55], fib.take(10)
end
assert 'Enumerator#initialize_copy' do
assert_equal [1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).dup.to_a
e = @obj.to_enum :foo, 1, 2, 3
assert_nothing_raised { assert_equal(1, e.next) }
assert_raise(TypeError) { e.dup }
e = Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.dup
assert_nothing_raised { assert_equal(1, e.next) }
assert_raise(TypeError) { e.dup }
end
assert 'Enumerator#with_index' do
assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a)
assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
a = []
@obj.to_enum(:foo, 1, 2, 3).with_index(10).with_index(20) { |*i| a << i }
assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a
end
assert 'Enumerator#with_index nonnum offset' do
s = Object.new
def s.to_int; 1 end
assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a)
end
assert 'Enumerator#with_index string offset' do
assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a }
end
assert 'Enumerator#each_with_index' do
assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).each_with_index.to_a)
a = []
@obj.to_enum(:foo, 1, 2, 3).each_with_index {|*i| a << i}
assert_equal([[1, 0], [2, 1], [3, 2]], a)
end
assert 'Enumerator#with_object' do
obj = [0, 1]
ret = (1..10).each.with_object(obj) {|i, memo|
memo[0] += i
memo[1] *= i
}
assert_true(obj.equal?(ret))
assert_equal([55, 3628800], ret)
end
assert 'Enumerator#with_object arguments' do
to_three = Enumerator.new do |y|
3.times do |x|
y << x
end
end
a = []
to_three_with_string = to_three.with_object("foo")
to_three_with_string.each do |x,string|
a << "#{string}:#{x}"
end
assert_equal ["foo:0","foo:1","foo:2"], a
end
assert 'Enumerator#inspect' do
e = (0..10).each
assert_equal("#<Enumerator: 0..10:each>", e.inspect)
e = Enumerator.new("FooObject", :foo, 1)
assert_equal("#<Enumerator: FooObject:foo(1)>", e.inspect)
e = Enumerator.new("FooObject", :foo, 1, 2, 3)
assert_equal("#<Enumerator: FooObject:foo(1, 2, 3)>", e.inspect)
end
assert 'Enumerator#each' do
o = Object.new
def o.each(ary)
ary << 1
yield
end
ary = []
e = o.to_enum.each(ary)
e.next
assert_equal([1], ary)
end
assert 'Enumerator#each arguments' do
obj = Object.new
def obj.each_arg(a, b=:b, *rest)
yield a
yield b
yield rest
:method_returned
end
enum = obj.to_enum :each_arg, :a, :x
assert_equal [:a, :x, []], enum.each.to_a
assert_true enum.each.equal?(enum)
assert_equal :method_returned, enum.each { |elm| elm }
assert_equal [:a, :x, [:y, :z]], enum.each(:y, :z).to_a
assert_false enum.each(:y, :z).equal?(enum)
assert_equal :method_returned, enum.each(:y, :z) { |elm| elm }
end
assert 'Enumerator#next' do
e = 3.times
3.times { |i|
assert_equal i, e.next
}
assert_raise(StopIteration) { e.next }
end
assert 'Enumerator#next_values' do
o = Object.new
def o.each
yield
yield 1
yield 1, 2
end
e = o.to_enum
assert_equal nil, e.next
assert_equal 1, e.next
assert_equal [1,2], e.next
e = o.to_enum
assert_equal [], e.next_values
assert_equal [1], e.next_values
assert_equal [1,2], e.next_values
end
assert 'Enumerator#peek' do
a = [1]
e = a.each
assert_equal 1, e.peek
assert_equal 1, e.peek
assert_equal 1, e.next
assert_raise(StopIteration) { e.peek }
assert_raise(StopIteration) { e.peek }
end
assert 'Enumerator#peek modify' do
o = Object.new
def o.each
yield 1,2
end
e = o.to_enum
a = e.peek
a << 3
assert_equal([1,2], e.peek)
end
assert 'Enumerator#peek_values' do
o = Object.new
def o.each
yield
yield 1
yield 1, 2
end
e = o.to_enum
assert_equal nil, e.peek
assert_equal nil, e.next
assert_equal 1, e.peek
assert_equal 1, e.next
assert_equal [1,2], e.peek
assert_equal [1,2], e.next
e = o.to_enum
assert_equal [], e.peek_values
assert_equal [], e.next_values
assert_equal [1], e.peek_values
assert_equal [1], e.next_values
assert_equal [1,2], e.peek_values
assert_equal [1,2], e.next_values
e = o.to_enum
assert_equal [], e.peek_values
assert_equal nil, e.next
assert_equal [1], e.peek_values
assert_equal 1, e.next
assert_equal [1,2], e.peek_values
assert_equal [1,2], e.next
e = o.to_enum
assert_equal nil, e.peek
assert_equal [], e.next_values
assert_equal 1, e.peek
assert_equal [1], e.next_values
assert_equal [1,2], e.peek
assert_equal [1,2], e.next_values
end
assert 'Enumerator#peek_values modify' do
o = Object.new
def o.each
yield 1,2
end
e = o.to_enum
a = e.peek_values
a << 3
assert_equal [1,2], e.peek
end
assert 'Enumerator#feed' do
o = Object.new
def o.each(ary)
ary << yield
ary << yield
ary << yield
end
ary = []
e = o.to_enum :each, ary
e.next
e.feed 1
e.next
e.feed 2
e.next
e.feed 3
assert_raise(StopIteration) { e.next }
assert_equal [1,2,3], ary
end
assert 'Enumerator#feed mixed' do
o = Object.new
def o.each(ary)
ary << yield
ary << yield
ary << yield
end
ary = []
e = o.to_enum :each, ary
e.next
e.feed 1
e.next
e.next
e.feed 3
assert_raise(StopIteration) { e.next }
assert_equal [1,nil,3], ary
end
assert 'Enumerator#feed twice' do
o = Object.new
def o.each(ary)
ary << yield
ary << yield
ary << yield
end
ary = []
e = o.to_enum :each, ary
e.feed 1
assert_raise(TypeError) { e.feed 2 }
end
assert 'Enumerator#feed before first next' do
o = Object.new
def o.each(ary)
ary << yield
ary << yield
ary << yield
end
ary = []
e = o.to_enum :each, ary
e.feed 1
e.next
e.next
assert_equal [1], ary
end
assert 'Enumerator#feed yielder' do
x = nil
e = Enumerator.new {|y| x = y.yield; 10 }
e.next
e.feed 100
assert_raise(StopIteration) { e.next }
assert_equal 100, x
end
assert 'Enumerator#rewind' do
e = @obj.to_enum(:foo, 1, 2, 3)
assert_equal 1, e.next
assert_equal 2, e.next
e.rewind
assert_equal 1, e.next
assert_equal 2, e.next
assert_equal 3, e.next
assert_raise(StopIteration) { e.next }
end
assert 'Enumerator#rewind clear feed' do
o = Object.new
def o.each(ary)
ary << yield
ary << yield
ary << yield
end
ary = []
e = o.to_enum(:each, ary)
e.next
e.feed 1
e.next
e.feed 2
e.rewind
e.next
e.next
assert_equal([1,nil], ary)
end
assert 'Enumerator#rewind clear' do
o = Object.new
def o.each(ary)
ary << yield
ary << yield
ary << yield
end
ary = []
e = o.to_enum :each, ary
e.next
e.feed 1
e.next
e.feed 2
e.rewind
e.next
e.next
assert_equal [1,nil], ary
end
assert 'Enumerator::Generator' do
# note: Enumerator::Generator is a class just for internal
g = Enumerator::Generator.new {|y| y << 1 << 2 << 3; :foo }
g2 = g.dup
a = []
assert_equal(:foo, g.each {|x| a << x })
assert_equal([1, 2, 3], a)
a = []
assert_equal(:foo, g2.each {|x| a << x })
assert_equal([1, 2, 3], a)
end
assert 'Enumerator::Generator args' do
g = Enumerator::Generator.new {|y, x| y << 1 << 2 << 3; x }
a = []
assert_equal(:bar, g.each(:bar) {|x| a << x })
assert_equal([1, 2, 3], a)
end
assert 'Enumerator::Yielder' do
# note: Enumerator::Yielder is a class just for internal
a = []
y = Enumerator::Yielder.new {|x| a << x }
assert_equal(y, y << 1 << 2 << 3)
assert_equal([1, 2, 3], a)
a = []
y = Enumerator::Yielder.new {|x| a << x }
assert_equal([1], y.yield(1))
assert_equal([1, 2], y.yield(2))
assert_equal([1, 2, 3], y.yield(3))
assert_raise(LocalJumpError) { Enumerator::Yielder.new }
end
assert 'next after StopIteration' do
a = [1]
e = a.each
assert_equal(1, e.next)
assert_raise(StopIteration) { e.next }
assert_raise(StopIteration) { e.next }
e.rewind
assert_equal(1, e.next)
assert_raise(StopIteration) { e.next }
assert_raise(StopIteration) { e.next }
end
assert 'gc' do
assert_nothing_raised do
1.times do
foo = [1,2,3].to_enum
GC.start
end
GC.start
end
end
assert 'nested iteration' do
def (o = Object.new).each
yield :ok1
yield [:ok2, :x].each.next
end
e = o.to_enum
assert_equal :ok1, e.next
assert_equal :ok2, e.next
assert_raise(StopIteration) { e.next }
end
assert 'Kernel#to_enum' do
assert_equal Enumerator, [].to_enum.class
assert_raise(ArgumentError){ nil.to_enum }
end
assert 'modifying existing methods' do
assert_equal Enumerator, loop.class
e = 3.times
i = 0
loop_ret = loop {
assert_equal i, e.next
i += 1
}
end
assert 'Integral#times' do
a = 3
b = a.times
c = []
b.with_object(c) do |i, obj|
obj << i
end
assert_equal 3, a
assert_equal Enumerator, b.class
assert_equal [0,1,2], c
end
assert 'Enumerable#each_with_index' do
assert_equal [['a',0],['b',1],['c',2]], ['a','b','c'].each_with_index.to_a
end
assert 'Enumerable#map' do
a = [1,2,3]
b = a.map
c = b.with_index do |i, index|
[i*i, index*index]
end
assert_equal [1,2,3], a
assert_equal [[1,0],[4,1],[9,4]], c
end
assert 'Enumerable#find_all' do
assert_equal [[3,4]], [[1,2],[3,4],[5,6]].find_all.each{ |i| i[1] == 4 }
end
assert 'Array#each_index' do
a = [1,2,3]
b = a.each_index
c = []
b.with_index do |index1,index2|
c << [index1+2,index2+5]
end
assert_equal [1,2,3], a
assert_equal [[2,5],[3,6],[4,7]], c
end
assert 'Array#map!' do
a = [1,2,3]
b = a.map!
b.with_index do |i, index|
[i*i, index*index]
end
assert_equal [[1,0],[4,1],[9,4]], a
end
assert 'Hash#each' do
a = {a:1,b:2}
b = a.each
c = []
b.each do |k,v|
c << [k,v]
end
assert_equal [[:a,1], [:b,2]], c.sort
end
assert 'Hash#each_key' do
assert_equal [:a,:b], {a:1,b:2}.each_key.to_a.sort
end
assert 'Hash#each_value' do
assert_equal [1,2], {a:1,b:2}.each_value.to_a.sort
end
assert 'Hash#select' do
h = {1=>2,3=>4,5=>6}
hret = h.select.with_index {|a,_b| a[1] == 4}
assert_equal({3=>4}, hret)
assert_equal({1=>2,3=>4,5=>6}, h)
end
assert 'Hash#select!' do
h = {1=>2,3=>4,5=>6}
hret = h.select!.with_index {|a,_b| a[1] == 4}
assert_equal h, hret
assert_equal({3=>4}, h)
end
assert 'Hash#reject' do
h = {1=>2,3=>4,5=>6}
hret = h.reject.with_index {|a,_b| a[1] == 4}
assert_equal({1=>2,5=>6}, hret)
assert_equal({1=>2,3=>4,5=>6}, h)
end
assert 'Hash#reject!' do
h = {1=>2,3=>4,5=>6}
hret = h.reject!.with_index {|a,_b| a[1] == 4}
assert_equal h, hret
assert_equal({1=>2,5=>6}, h)
end
assert 'Range#each' do
a = (1..5)
b = a.each
c = []
b.each do |i|
c << i
end
assert_equal [1,2,3,4,5], c
end