1# frozen_string_literal: false 2require 'test/unit' 3EnvUtil.suppress_warning {require 'continuation'} 4require 'fiber' 5 6class TestContinuation < Test::Unit::TestCase 7 def test_create 8 assert_equal(:ok, callcc{:ok}) 9 assert_equal(:ok, callcc{|c| c.call :ok}) 10 end 11 12 def test_call 13 assert_equal(:ok, callcc{|c| c.call :ok}) 14 15 ary = [] 16 ary << callcc{|c| 17 @cont = c 18 :a 19 } 20 @cont.call :b if ary.length < 3 21 assert_equal([:a, :b, :b], ary) 22 end 23 24 def test_check_localvars 25 vv = 0 26 @v = 0 27 @ary = [] 28 [1, 2, 3].each{|i| 29 callcc {|k| @k = k} 30 @v += 1 31 vv += 1 32 } 33 @ary << [vv, @v] 34 @k.call if @v < 10 35 assert_equal((3..10).map{|e| [e, e]}, @ary) 36 end 37 38 def test_error 39 cont = callcc{|c| c} 40 Thread.new{ 41 assert_raise(RuntimeError){ 42 cont.call 43 } 44 }.join 45 assert_raise(LocalJumpError){ 46 callcc 47 } 48 assert_raise(RuntimeError){ 49 c = nil 50 Fiber.new do 51 callcc {|c2| c = c2 } 52 end.resume 53 c.call 54 } 55 end 56 57 def test_ary_flatten 58 assert_normal_exit %q{ 59 require 'continuation' 60 n = 0 61 o = Object.new 62 def o.to_ary() callcc {|k| $k = k; [1,2,3]} end 63 [10,20,o,30,o,40].flatten.inspect 64 n += 1 65 $k.call if n < 100 66 }, '[ruby-dev:34798]' 67 end 68 69 def test_marshal_dump 70 assert_normal_exit %q{ 71 require 'continuation' 72 n = 0 73 o = Object.new 74 def o.marshal_dump() callcc {|k| $k = k }; "fofof" end 75 a = [1,2,3,o,4,5,6] 76 Marshal.dump(a).inspect 77 n += 1 78 $k.call if n < 100 79 }, '[ruby-dev:34802]' 80 end 81 82 def tracing_with_set_trace_func 83 orig_thread = Thread.current 84 cont = nil 85 func = lambda do |*args| 86 if orig_thread == Thread.current 87 if cont 88 @memo += 1 89 c = cont 90 cont = nil 91 begin 92 c.call(nil) 93 rescue RuntimeError 94 set_trace_func(nil) 95 end 96 end 97 end 98 end 99 cont = callcc { |cc| cc } 100 101 if cont 102 set_trace_func(func) 103 else 104 set_trace_func(nil) 105 end 106 end 107 108 def _test_tracing_with_set_trace_func 109 @memo = 0 110 tracing_with_set_trace_func 111 tracing_with_set_trace_func 112 tracing_with_set_trace_func 113 assert_equal 0, @memo 114 end 115 116 def tracing_with_thread_set_trace_func 117 cont = nil 118 func = lambda do |*args| 119 if cont 120 @memo += 1 121 c = cont 122 cont = nil 123 begin 124 c.call(nil) 125 rescue RuntimeError 126 Thread.current.set_trace_func(nil) 127 end 128 end 129 end 130 cont = callcc { |cc| cc } 131 if cont 132 Thread.current.set_trace_func(func) 133 else 134 Thread.current.set_trace_func(nil) 135 end 136 end 137 138 def test_tracing_with_thread_set_trace_func 139 @memo = 0 140 tracing_with_thread_set_trace_func 141 tracing_with_thread_set_trace_func 142 tracing_with_thread_set_trace_func 143 assert_equal 3, @memo 144 end 145end 146