1require 'test/unit' 2require 'thread' 3 4class TestBacktrace < Test::Unit::TestCase 5 def test_exception 6 bt = Fiber.new{ 7 begin 8 raise 9 rescue => e 10 e.backtrace 11 end 12 }.resume 13 assert_equal(1, bt.size) 14 assert_match(/.+:\d+:.+/, bt[0]) 15 end 16 17 def test_caller_lev 18 cs = [] 19 Fiber.new{ 20 Proc.new{ 21 cs << caller(0) 22 cs << caller(1) 23 cs << caller(2) 24 cs << caller(3) 25 cs << caller(4) 26 cs << caller(5) 27 }.call 28 }.resume 29 assert_equal(3, cs[0].size) 30 assert_equal(2, cs[1].size) 31 assert_equal(1, cs[2].size) 32 assert_equal(0, cs[3].size) 33 assert_equal(nil, cs[4]) 34 35 # 36 max = 7 37 rec = lambda{|n| 38 if n > 0 39 1.times{ 40 rec[n-1] 41 } 42 else 43 (max*3).times{|i| 44 total_size = caller(0).size 45 c = caller(i) 46 if c 47 assert_equal(total_size - i, caller(i).size, "[ruby-dev:45673]") 48 end 49 } 50 end 51 } 52 bt = Fiber.new{ 53 rec[max] 54 }.resume 55 end 56 57 def test_caller_lev_and_n 58 m = 10 59 rec = lambda{|n| 60 if n < 0 61 (m*6).times{|lev| 62 (m*6).times{|n| 63 t = caller(0).size 64 r = caller(lev, n) 65 r = r.size if r.respond_to? :size 66 67 # STDERR.puts [t, lev, n, r].inspect 68 if n == 0 69 assert_equal(0, r, [t, lev, n, r].inspect) 70 elsif t < lev 71 assert_equal(nil, r, [t, lev, n, r].inspect) 72 else 73 if t - lev > n 74 assert_equal(n, r, [t, lev, n, r].inspect) 75 else 76 assert_equal(t - lev, r, [t, lev, n, r].inspect) 77 end 78 end 79 } 80 } 81 else 82 rec[n-1] 83 end 84 } 85 rec[m] 86 end 87 88 def test_caller_with_nil_length 89 assert_equal caller(0), caller(0, nil) 90 end 91 92 def test_caller_locations 93 cs = caller(0); locs = caller_locations(0).map{|loc| 94 loc.to_s 95 } 96 assert_equal(cs, locs) 97 end 98 99 def test_caller_locations_with_range 100 cs = caller(0,2); locs = caller_locations(0..1).map { |loc| 101 loc.to_s 102 } 103 assert_equal(cs, locs) 104 end 105 106 def test_caller_locations_to_s_inspect 107 cs = caller(0); locs = caller_locations(0) 108 cs.zip(locs){|str, loc| 109 assert_equal(str, loc.to_s) 110 assert_equal(str.inspect, loc.inspect) 111 } 112 end 113 114 def th_rec q, n=10 115 if n > 1 116 th_rec q, n-1 117 else 118 q.pop 119 end 120 end 121 122 def test_thread_backtrace 123 begin 124 q = Queue.new 125 th = Thread.new{ 126 th_rec q 127 } 128 sleep 0.5 129 th_backtrace = th.backtrace 130 th_locations = th.backtrace_locations 131 132 assert_equal(10, th_backtrace.count{|e| e =~ /th_rec/}) 133 assert_equal(th_backtrace, th_locations.map{|e| e.to_s}) 134 assert_equal(th_backtrace, th.backtrace(0)) 135 assert_equal(th_locations.map{|e| e.to_s}, 136 th.backtrace_locations(0).map{|e| e.to_s}) 137 th_backtrace.size.times{|n| 138 assert_equal(n, th.backtrace(0, n).size) 139 assert_equal(n, th.backtrace_locations(0, n).size) 140 } 141 n = th_backtrace.size 142 assert_equal(n, th.backtrace(0, n + 1).size) 143 assert_equal(n, th.backtrace_locations(0, n + 1).size) 144 ensure 145 q << true 146 end 147 end 148 149 def test_thread_backtrace_locations_with_range 150 begin 151 q = Queue.new 152 th = Thread.new{ 153 th_rec q 154 } 155 sleep 0.5 156 bt = th.backtrace(0,2) 157 locs = th.backtrace_locations(0..1).map { |loc| 158 loc.to_s 159 } 160 assert_equal(bt, locs) 161 ensure 162 q << true 163 end 164 end 165end 166