* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / ruby / test_iterator.rb
blob820d5591c1d192a21c05890c3a0c51e07d59de1f
1 # frozen_string_literal: false
2 require 'test/unit'
4 class Array
5   def iter_test1
6     collect{|e| [e, yield(e)]}.sort{|a,b|a[1]<=>b[1]}
7   end
8   def iter_test2
9     ary = collect{|e| [e, yield(e)]}
10     ary.sort{|a,b|a[1]<=>b[1]}
11   end
12 end
14 class TestIterator < Test::Unit::TestCase
15   def test_yield_at_toplevel
16     assert_separately([],"#{<<~"begin;"}\n#{<<~'end;'}")
17     begin;
18       assert(!block_given?)
19       assert(!defined?(yield))
20     end;
21   end
23   def test_array
24     x = [1, 2, 3, 4]
25     y = []
27     # iterator over array
28     for i in x
29       y.push i
30     end
31     assert_equal(x, y)
32   end
34   def tt
35     1.upto(10) {|i|
36       yield i
37     }
38   end
40   def tt2(dummy)
41     yield 1
42   end
44   def tt3(&block)
45     tt2(raise(ArgumentError,""),&block)
46   end
48   def test_nested_iterator
49     i = 0
50     tt{|j| break if j == 5}
51     assert_equal(0, i)
53     assert_raise(ArgumentError) do
54       tt3{}
55     end
56   end
58   def tt4 &block
59     tt2(raise(ArgumentError,""),&block)
60   end
62   def test_block_argument_without_paren
63     assert_raise(ArgumentError) do
64       tt4{}
65     end
66   end
68   # iterator break/redo/next
69   def test_break
70     done = true
71     loop{
72       break if true
73       done = false                      # should not reach here
74     }
75     assert(done)
77     done = false
78     bad = false
79     loop {
80       break if done
81       done = true
82       next if true
83       bad = true                        # should not reach here
84     }
85     assert(!bad)
87     done = false
88     bad = false
89     loop {
90       break if done
91       done = true
92       redo if true
93       bad = true                        # should not reach here
94     }
95     assert(!bad)
97     x = []
98     for i in 1 .. 7
99       x.push i
100     end
101     assert_equal(7, x.size)
102     assert_equal([1, 2, 3, 4, 5, 6, 7], x)
103   end
105   def test_array_for_masgn
106     a = [Struct.new(:to_ary).new([1,2])]
107     x = []
108     a.each {|i,j|x << [i,j]}
109     assert_equal([[1,2]], x)
110     x = []
111     for i,j in a; x << [i,j]; end
112     assert_equal([[1,2]], x)
113   end
115   def test_append_method_to_built_in_class
116     x = [[1,2],[3,4],[5,6]]
117     assert_equal(x.iter_test1{|e|e}, x.iter_test2{|e|e})
118   end
120   class IterTest
121     def initialize(e); @body = e; end
123     def each0(&block); @body.each(&block); end
124     def each1(&block); @body.each {|*x| block.call(*x) } end
125     def each2(&block); @body.each {|*x| block.call(x) } end
126     def each3(&block); @body.each {|x| block.call(*x) } end
127     def each4(&block); @body.each {|x| block.call(x) } end
128     def each5; @body.each {|*x| yield(*x) } end
129     def each6; @body.each {|*x| yield(x) } end
130     def each7; @body.each {|x| yield(*x) } end
131     def each8; @body.each {|x| yield(x) } end
133     def f(a)
134       a
135     end
136   end
138   def test_itertest
139     assert_equal([1], IterTest.new(nil).method(:f).to_proc.call([1]))
140     m = /\w+/.match("abc")
141     assert_equal([m], IterTest.new(nil).method(:f).to_proc.call([m]))
143     IterTest.new([0]).each0 {|x| assert_equal(0, x)}
144     IterTest.new([1]).each1 {|x| assert_equal(1, x)}
145     IterTest.new([2]).each2 {|x| assert_equal([2], x)}
146     IterTest.new([4]).each4 {|x| assert_equal(4, x)}
147     IterTest.new([5]).each5 {|x| assert_equal(5, x)}
148     IterTest.new([6]).each6 {|x| assert_equal([6], x)}
149     IterTest.new([8]).each8 {|x| assert_equal(8, x)}
151     IterTest.new([[0]]).each0 {|x| assert_equal([0], x)}
152     IterTest.new([[1]]).each1 {|x| assert_equal([1], x)}
153     IterTest.new([[2]]).each2 {|x| assert_equal([[2]], x)}
154     IterTest.new([[3]]).each3 {|x| assert_equal(3, x)}
155     IterTest.new([[4]]).each4 {|x| assert_equal([4], x)}
156     IterTest.new([[5]]).each5 {|x| assert_equal([5], x)}
157     IterTest.new([[6]]).each6 {|x| assert_equal([[6]], x)}
158     IterTest.new([[7]]).each7 {|x| assert_equal(7, x)}
159     IterTest.new([[8]]).each8 {|x| assert_equal([8], x)}
161     IterTest.new([[0,0]]).each0 {|*x| assert_equal([[0,0]], x)}
162     IterTest.new([[8,8]]).each8 {|*x| assert_equal([[8,8]], x)}
163   end
165   def m(var)
166     var
167   end
169   def m1
170     m(block_given?)
171   end
173   def m2
174     m(block_given?,&proc{})
175   end
177   def test_block_given
178     assert(m1{p 'test'})
179     assert(m2{p 'test'})
180     assert(!m1())
181     assert(!m2())
182   end
184   def m3(var, &block)
185     m(yield(var), &block)
186   end
188   def m4(&block)
189     m(m1(), &block)
190   end
192   def test_block_passing
193     assert(!m4())
194     assert(!m4 {})
195     assert_equal(100, m3(10) {|x|x*x})
196   end
198   class C
199     include Enumerable
200     def initialize
201       @a = [1,2,3]
202     end
203     def each(&block)
204       @a.each(&block)
205     end
206   end
208   def test_collect
209     assert_equal([1,2,3], C.new.collect{|n| n})
210   end
212   def test_proc
213     assert_instance_of(Proc, lambda{})
214     assert_instance_of(Proc, Proc.new{})
215     lambda{|a|assert_equal(a, 1)}.call(1)
216   end
218   def test_block
219     assert_instance_of(NilClass, get_block)
220     assert_instance_of(Proc, get_block{})
221   end
223   def test_argument
224     assert_nothing_raised {lambda{||}.call}
225     assert_raise(ArgumentError) {lambda{||}.call(1)}
226     assert_nothing_raised {lambda{|a,|}.call(1)}
227     assert_raise(ArgumentError) {lambda{|a,|}.call()}
228     assert_raise(ArgumentError) {lambda{|a,|}.call(1,2)}
229   end
231   def get_block(&block)
232     block
233   end
235   def test_get_block
236     assert_instance_of(Proc, get_block{})
237     assert_nothing_raised {get_block{||}.call()}
238     assert_nothing_raised {get_block{||}.call(1)}
239     assert_nothing_raised {get_block{|a,|}.call(1)}
240     assert_nothing_raised {get_block{|a,|}.call()}
241     assert_nothing_raised {get_block{|a,|}.call(1,2)}
243     assert_nothing_raised {get_block(&lambda{||}).call()}
244     assert_raise(ArgumentError) {get_block(&lambda{||}).call(1)}
245     assert_nothing_raised {get_block(&lambda{|a,|}).call(1)}
246     assert_raise(ArgumentError) {get_block(&lambda{|a,|}).call(1,2)}
248     block = get_block{11}
249     assert_instance_of(Proc, block)
250     assert_instance_of(Proc, block.to_proc)
251     assert_equal(block.clone.call, 11)
252     assert_instance_of(Proc, get_block(&block))
254     lmd = lambda{44}
255     assert_instance_of(Proc, lmd)
256     assert_instance_of(Proc, lmd.to_proc)
257     assert_equal(lmd.clone.call, 44)
258     assert_instance_of(Proc, get_block(&lmd))
260     assert_equal(1, Proc.new{|a,| a}.call(1,2,3))
261     assert_nothing_raised {Proc.new{|a,|}.call(1,2)}
262   end
264   def return1_test
265     Proc.new {
266       return 55
267     }.call + 5
268   end
270   def test_return1
271     assert_equal(55, return1_test())
272   end
274   def return2_test
275     lambda {
276       return 55
277     }.call + 5
278   end
280   def test_return2
281     assert_equal(60, return2_test())
282   end
284   def proc_call(&b)
285     b.call
286   end
287   def proc_call2(b)
288     b.call
289   end
290   def proc_yield()
291     yield
292   end
293   def proc_return1
294     proc_call{return 42}+1
295   end
297   def test_proc_return1
298     assert_equal(42, proc_return1())
299   end
301   def proc_return2
302     proc_yield{return 42}+1
303   end
305   def test_proc_return2
306     assert_equal(42, proc_return2())
307   end
309   def test_ljump
310     assert_raise(LocalJumpError) {get_block{break}.call}
311     assert_raise(LocalJumpError) {proc_call2(get_block{break}){}}
313     # cannot use assert_nothing_raised due to passing block.
314     begin
315       val = lambda{break 11}.call
316     rescue LocalJumpError
317       assert(false, "LocalJumpError occurred from break in lambda")
318     else
319       assert_equal(11, val)
320     end
322     block = get_block{11}
323     lmd = lambda{44}
324     assert_equal(0, block.arity)
325     assert_equal(0, lmd.arity)
326     assert_equal(0, lambda{||}.arity)
327     assert_equal(1, lambda{|a|}.arity)
328     assert_equal(1, lambda{|a,|}.arity)
329     assert_equal(2, lambda{|a,b|}.arity)
330   end
332   def marity_test(m)
333     mobj = method(m)
334     assert_equal(mobj.arity, mobj.to_proc.arity)
335   end
337   def test_marity
338     marity_test(:assert)
339     marity_test(:marity_test)
340     marity_test(:p)
342     get_block{|a,n| assert(a,n)}.call(true, "marity")
343   end
345   def foo
346     yield(:key, :value)
347   end
348   def bar(&blk)
349     blk.call(:key, :value)
350   end
352   def test_yield_vs_call
353     foo{|k,v| assert_equal([:key, :value], [k,v])}
354     bar{|k,v| assert_equal([:key, :value], [k,v])}
355   end
357   class H
358     def each
359       yield [:key, :value]
360     end
361     alias each_pair each
362   end
364   def test_assoc_yield
365      [{:key=>:value}, H.new].each {|h|
366        h.each{|a| assert_equal([:key, :value], a)}
367        h.each{|a,| assert_equal(:key, a)}
368        h.each{|*a| assert_equal([[:key, :value]], a)}
369        h.each{|k,v| assert_equal([:key, :value], [k,v])}
370        h.each_pair{|a| assert_equal([:key, :value], a)}
371        h.each_pair{|a,| assert_equal(:key, a)}
372        h.each_pair{|*a| assert_equal([[:key, :value]], a)}
373        h.each_pair{|k,v| assert_equal([:key, :value], [k,v])}
374     }
375   end
377   class ITER_TEST1
378     def a
379       block_given?
380     end
381   end
383   class ITER_TEST2 < ITER_TEST1
384     include Test::Unit::Assertions
385     def a
386       assert(super)
387       super
388     end
389   end
391   def test_iter_test2
392     assert(ITER_TEST2.new.a {})
393   end
395   class ITER_TEST3
396     def foo x
397       return yield if block_given?
398       x
399     end
400   end
402   class ITER_TEST4 < ITER_TEST3
403     include Test::Unit::Assertions
404     def foo x
405       assert_equal(super, yield)
406       assert_equal(x, super(x, &nil))
407     end
408   end
410   def test_iter4
411     ITER_TEST4.new.foo(44){55}
412   end
414   def test_break__nested_loop1
415     _test_break__nested_loop1 do
416       break
417     end
418   end
420   def _test_break__nested_loop1
421     while true
422       yield
423     end
424     assert(false, "must not reach here")
425   end
427   def test_break__nested_loop2
428     _test_break__nested_loop2 do
429       break
430     end
431   end
433   def _test_break__nested_loop2
434     until false
435       yield
436     end
437     assert(false, "must not reach here")
438   end
440   def test_break__nested_loop3
441     _test_break__nested_loop3 do
442       break
443     end
444   end
446   def _test_break__nested_loop3
447     loop do
448       yield
449     end
450     assert(false, "must not reach here")
451   end
453   def test_break_from_enum
454     result = ["a"].inject("ng") {|x,y| break "ok"}
455     assert_equal("ok", result)
456   end
458   def _test_return_trace_func(x)
459     set_trace_func(proc {})
460     [].fetch(2) {return x}
461   ensure
462     set_trace_func(nil)
463   end
465   def test_return_trace_func
466     ok = "returned gracefully"
467     result = "skipped"
468     result = _test_return_trace_func(ok)
469   ensure
470     assert_equal(ok, result)
471     return
472   end
474   class IterString < ::String
475     def ===(other)
476       super if !block_given?
477     end
478   end
480   # Check that the block passed to an iterator
481   # does not get propagated inappropriately
482   def test_block_given_within_iterator
483     assert_equal(["b"], ["a", "b", "c"].grep(IterString.new("b")) {|s| s})
484   end
486   def test_enumerator
487     [1,2,3].each.with_index {|x,i|
488       assert_equal(x, i+1)
489     }
491     e = [1,2,3].each
492     assert_equal(1, e.next)
493     assert_equal(2, e.next)
494     assert_equal(3, e.next)
495     assert_raise(StopIteration){e.next}
496     e.rewind
497     assert_equal(1, e.next)
498     e.rewind
499     a = []
500     loop{a.push e.next}
501     assert_equal([1,2,3], a)
503     assert_equal([[8, 1, 10], [6, 2, 11], [4, 3, 12]],
504                  [8,6,4].zip((1..10),(10..100)).to_a)
505   end