Fix some symbol.to_proc problems
[jruby.git] / test / test_backtraces.rb
blobc08cc9ee5f77fd106177749681dfa45020285a8f
1 require 'test/unit'
3 # Unit and regression tests for backtraces.
4 # Note: The tests follow MRI 1.8.6 behavior.
5 # Behavior of MRI 1.9 is different:
6 # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/15589
7 class TestBacktraces < Test::Unit::TestCase
8   def setup
9     @offset = nil
10   end
12   # Convenience method to obtain the exception,
13   # and to print the stack trace, if needed.
14   def get_exception(verbose=false)
15     begin
16       @get_exception_yield_line = __LINE__ + 1
17       yield
18     rescue Exception => ex
19       puts ex.backtrace.join("\n") if verbose
20       ex
21     end
22   end
24   # Main verification method that performs actual checks
25   # on the stacktraces.
26   def check(expectations, exception)
27     backtrace = []
28     expectations.strip.split("\n").each { |line|
29       line.strip!
31       # if line starts with +nnn, we prepend
32       # the current file and offset
33       md = line.match(/^\+(\d+)(:.*)/)
34       if (md)
35         flunk("@offset is not defined in the test case") unless @offset
36         line = "#{__FILE__}:#{$1.to_i + @offset}#{$2}"
37       end
39       backtrace << line.strip
40     }
41     backtrace.each_with_index { |expected, idx|
42       assert_equal(expected, exception.backtrace[idx])
43     }
44   end
46   def test_simple_exception
47     @offset = __LINE__
48     raise RuntimeError.new("Test")
49   rescue Exception => ex
50     expectation = "+1:in `test_simple_exception'"
51     check(expectation, ex)
52   end
54   def test_simple_exception_recursive
55     @offset = __LINE__
56     def meth(n)
57       raise RuntimeError.new("Test") if n == 10
58       n += 1
59       meth(n)
60     end
61     meth(0)
62   rescue Exception => ex
63     expectation = %q{
64       +2:in `meth'
65       +4:in `meth'
66       +6:in `test_simple_exception_recursive'
67     }
68     check(expectation, ex)
69   end
71   def test_native_exception_recursive
72     @offset = __LINE__
73     def meth(n)
74       raise "hello".sub(/l/, 5) if n == 10
75       n += 1
76       meth(n)
77     end
78     meth(0)
79   rescue Exception => ex
80     expectation = %q{
81       +2:in `sub'
82       +2:in `meth'
83       +4:in `meth'
84       +6:in `test_native_exception_recursive'
85     }
86     check(expectation, ex)
87   end
89   def test_exception_from_block
90     @offset = __LINE__
91     def foo
92       yield
93     end
94     def bar
95       yield
96     end
97     foo { bar { raise TypeError.new("HEH") } }
98   rescue Exception => ex
99     expectation = %q{
100       +7:in `test_exception_from_block'
101       +5:in `bar'
102       +7:in `test_exception_from_block'
103       +2:in `foo'
104       +7:in `test_exception_from_block'
105     }
106     check(expectation, ex)
107   end
108   
109   def test_exception_from_for
110     array = [1,2,3,4,5]
111     @offset = __LINE__
112     for element in array
113       raise RuntimeError
114     end
115   rescue Exception => ex
116     expectation = %q{
117       +2:in `test_exception_from_for'
118       +1:in `each'
119       +1:in `test_exception_from_for'
120     }
121     check(expectation, ex)
122   end
124   def test_exception_from_proc
125     p = Proc.new {
126       @offset = __LINE__
127       raise StandardError.new
128     }
129     p.call
130   rescue Exception => ex
131     expectation = %q{
132       +1:in `test_exception_from_proc'
133       +3:in `call'
134       +3:in `test_exception_from_proc'
135     }
136     check(expectation, ex)
137   end
139   def test_exception_from_lambda
140     l = lambda {
141       @offset = __LINE__
142       raise StandardError.new
143     }
144     l.call
145   rescue Exception => ex
146     expectation = %q{
147       +1:in `test_exception_from_lambda'
148       +3:in `call'
149       +3:in `test_exception_from_lambda'
150     }
151     check(expectation, ex)
152   end
154   def test_exception_from_array_plus
155     @offset = __LINE__
156     [1,2,3] + 5
157   rescue Exception => ex
158     expectation = %q{
159       +1:in `+'
160       +1:in `test_exception_from_array_plus'
161     }
162     check(expectation, ex)
163   end
164   
165   # JRUBY-2138
166   def test_exception_from_string_plus
167     @offset = __LINE__
168     "hello" + nil
169   rescue Exception => ex
170     expectation = %q{
171       +1:in `+'
172       +1:in `test_exception_from_string_plus'
173     }
174     check(expectation, ex)
175   end
177   def test_exception_from_string_sub
178     @offset = __LINE__
179     "hello".sub(/l/, 5)
180   rescue Exception => ex
181     expectation = %q{
182       +1:in `sub'
183       +1:in `test_exception_from_string_sub'
184     }
185     check(expectation, ex)
186   end
188   def test_zero_devision_exception
189     @offset = __LINE__
190     1/0
191   rescue Exception => ex
192     expectation = %q{
193       +1:in `/'
194       +1:in `test_zero_devision_exception'
195     }
196     check(expectation, ex)
197   end
199   def test_exeption_from_object_send
200     @offset = __LINE__
201     "hello".__send__(:sub, /l/, 5)
202   rescue Exception => ex
203     expectation = %q{
204       +1:in `sub'
205       +1:in `__send__'
206       +1:in `test_exeption_from_object_send'
207     }
208     check(expectation, ex)
209   end
211   def test_arity_exception
212     @offset = __LINE__
213     "hello".sub
214   rescue Exception => ex
215     expectation = "+1:in `sub'"
216     check(expectation, ex)
217   end
219   def test_exception_from_eval
220     ex = get_exception {
221       @offset = __LINE__
222       eval("raise RuntimeError.new")
223     }
224     expectation = %Q{
225       +1:in `test_exception_from_eval'
226       #{__FILE__}:#{@get_exception_yield_line}:in `eval'
227       +1:in `test_exception_from_eval'
228       #{__FILE__}:#{@get_exception_yield_line}:in `get_exception'
229     }
230     check(expectation, ex)
231   end
233   def test_exception_from_block_inside_eval
234     ex = get_exception {
235       @offset = __LINE__
236       eval("def foo; yield; end; foo { raise RuntimeError.new }")
237     }
238     expectation = %Q{
239       +1:in `test_exception_from_block_inside_eval'
240       (eval):1:in `foo'
241       (eval):1:in `test_exception_from_block_inside_eval'
242       #{__FILE__}:#{@get_exception_yield_line}:in `eval'
243       +1:in `test_exception_from_block_inside_eval'
244       #{__FILE__}:#{@get_exception_yield_line}:in `get_exception'
245     }
246     check(expectation, ex)
247   end