PageRenderTime 55ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/test/test_backtraces.rb

https://github.com/moses/jruby
Ruby | 300 lines | 259 code | 21 blank | 20 comment | 4 complexity | 90b94b2518fe9564e8d57b9cba171c59 MD5 | raw file
  1. require 'test/unit'
  2. # Unit and regression tests for backtraces.
  3. # Note: The tests follow MRI 1.8.6 behavior.
  4. # Behavior of MRI 1.9 is different:
  5. # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/15589
  6. class TestBacktraces < Test::Unit::TestCase
  7. def setup
  8. @offset = nil
  9. end
  10. # Convenience method to obtain the exception,
  11. # and to print the stack trace, if needed.
  12. def get_exception(verbose=false)
  13. begin
  14. @get_exception_yield_line = __LINE__ + 1
  15. yield
  16. rescue Exception => ex
  17. puts ex.backtrace.join("\n") if verbose
  18. ex
  19. end
  20. end
  21. # Main verification method that performs actual checks
  22. # on the stacktraces.
  23. def check(expectations, exception)
  24. backtrace = []
  25. expectations.strip.split("\n").each { |line|
  26. line.strip!
  27. # if line starts with +nnn, we prepend
  28. # the current file and offset
  29. md = line.match(/^\+(\d+)(:.*)/)
  30. if (md)
  31. flunk("@offset is not defined in the test case") unless @offset
  32. line = "#{__FILE__}:#{$1.to_i + @offset}#{$2}"
  33. end
  34. backtrace << line.strip
  35. }
  36. backtrace.each_with_index { |expected, idx|
  37. assert_equal(expected, exception.backtrace[idx])
  38. }
  39. end
  40. def test_simple_exception
  41. @offset = __LINE__
  42. raise RuntimeError.new("Test")
  43. rescue Exception => ex
  44. expectation = "+1:in `test_simple_exception'"
  45. check(expectation, ex)
  46. end
  47. import org.jruby.test.TestHelper
  48. def test_java_backtrace
  49. TestHelper.throwTestHelperException
  50. rescue NativeException => ex
  51. backtrace = ex.backtrace.join("\r\n")
  52. if (!backtrace.include?("throwTestHelperException"))
  53. flunk("test_java_backtrace not in backtrace")
  54. end
  55. end
  56. def test_simple_exception_recursive
  57. @offset = __LINE__
  58. def meth(n)
  59. raise RuntimeError.new("Test") if n == 10
  60. n += 1
  61. meth(n)
  62. end
  63. meth(0)
  64. rescue Exception => ex
  65. expectation = %q{
  66. +2:in `meth'
  67. +4:in `meth'
  68. +6:in `test_simple_exception_recursive'
  69. }
  70. check(expectation, ex)
  71. end
  72. def test_native_exception_recursive
  73. @offset = __LINE__
  74. def meth(n)
  75. raise "hello".sub(/l/, 5) if n == 10
  76. n += 1
  77. meth(n)
  78. end
  79. meth(0)
  80. rescue Exception => ex
  81. expectation = %q{
  82. +2:in `sub'
  83. +2:in `meth'
  84. +4:in `meth'
  85. +6:in `test_native_exception_recursive'
  86. }
  87. check(expectation, ex)
  88. 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. def test_exception_from_for
  109. array = [1,2,3,4,5]
  110. @offset = __LINE__
  111. for element in array
  112. raise RuntimeError
  113. end
  114. rescue Exception => ex
  115. expectation = %q{
  116. +2:in `test_exception_from_for'
  117. +1:in `each'
  118. +1:in `test_exception_from_for'
  119. }
  120. check(expectation, ex)
  121. end
  122. def test_exception_from_proc
  123. p = Proc.new {
  124. @offset = __LINE__
  125. raise StandardError.new
  126. }
  127. p.call
  128. rescue Exception => ex
  129. expectation = %q{
  130. +1:in `test_exception_from_proc'
  131. +3:in `call'
  132. +3:in `test_exception_from_proc'
  133. }
  134. check(expectation, ex)
  135. end
  136. def test_exception_from_lambda
  137. l = lambda {
  138. @offset = __LINE__
  139. raise StandardError.new
  140. }
  141. l.call
  142. rescue Exception => ex
  143. expectation = %q{
  144. +1:in `test_exception_from_lambda'
  145. +3:in `call'
  146. +3:in `test_exception_from_lambda'
  147. }
  148. check(expectation, ex)
  149. end
  150. # TODO: currently fails
  151. def XXXtest_exception_from_array_plus
  152. @offset = __LINE__
  153. [1,2,3] + 5
  154. rescue Exception => ex
  155. expectation = %q{
  156. +1:in `+'
  157. +1:in `test_exception_from_array_plus'
  158. }
  159. check(expectation, ex)
  160. end
  161. # JRUBY-2138
  162. # # TODO: currently fails
  163. def XXXtest_exception_from_string_plus
  164. @offset = __LINE__
  165. "hello" + nil
  166. rescue Exception => ex
  167. expectation = %q{
  168. +1:in `+'
  169. +1:in `test_exception_from_string_plus'
  170. }
  171. check(expectation, ex)
  172. end
  173. def test_exception_from_string_sub
  174. @offset = __LINE__
  175. "hello".sub(/l/, 5)
  176. rescue Exception => ex
  177. expectation = %q{
  178. +1:in `sub'
  179. +1:in `test_exception_from_string_sub'
  180. }
  181. check(expectation, ex)
  182. end
  183. # TODO: currently fails
  184. def XXXtest_zero_devision_exception
  185. @offset = __LINE__
  186. 1/0
  187. rescue Exception => ex
  188. expectation = %q{
  189. +1:in `/'
  190. +1:in `test_zero_devision_exception'
  191. }
  192. check(expectation, ex)
  193. end
  194. # TODO: currently fails
  195. def XXXtest_exeption_from_object_send
  196. @offset = __LINE__
  197. "hello".__send__(:sub, /l/, 5)
  198. rescue Exception => ex
  199. expectation = %q{
  200. +1:in `sub'
  201. +1:in `__send__'
  202. +1:in `test_exeption_from_object_send'
  203. }
  204. check(expectation, ex)
  205. end
  206. # TODO: currently fails
  207. def XXXtest_arity_exception
  208. @offset = __LINE__
  209. "hello".sub
  210. rescue Exception => ex
  211. expectation = "+1:in `sub'"
  212. check(expectation, ex)
  213. end
  214. # TODO: currently fails
  215. def XXXtest_exception_from_eval
  216. ex = get_exception {
  217. @offset = __LINE__
  218. eval("raise RuntimeError.new")
  219. }
  220. expectation = %Q{
  221. +1:in `test_exception_from_eval'
  222. #{__FILE__}:#{@get_exception_yield_line}:in `eval'
  223. +1:in `test_exception_from_eval'
  224. #{__FILE__}:#{@get_exception_yield_line}:in `get_exception'
  225. }
  226. check(expectation, ex)
  227. end
  228. # TODO: currently fails
  229. def XXXtest_exception_from_block_inside_eval
  230. ex = get_exception {
  231. @offset = __LINE__
  232. eval("def foo; yield; end; foo { raise RuntimeError.new }")
  233. }
  234. expectation = %Q{
  235. +1:in `test_exception_from_block_inside_eval'
  236. (eval):1:in `foo'
  237. (eval):1:in `test_exception_from_block_inside_eval'
  238. #{__FILE__}:#{@get_exception_yield_line}:in `eval'
  239. +1:in `test_exception_from_block_inside_eval'
  240. #{__FILE__}:#{@get_exception_yield_line}:in `get_exception'
  241. }
  242. check(expectation, ex)
  243. end
  244. # JRUBY-2695
  245. def test_exception_from_thread_with_abort_on_exception_true
  246. require 'stringio'
  247. $stderr = StringIO.new
  248. Thread.abort_on_exception = true
  249. ex = get_exception {
  250. @offset = __LINE__
  251. t = Thread.new do
  252. raise RuntimeError.new "DUMMY_MSG"
  253. end
  254. sleep 3
  255. t.join
  256. }
  257. assert_match(
  258. /test_backtraces.rb:#{@offset + 2}.*DUMMY_MSG.*RuntimeError/,
  259. $stderr.string
  260. )
  261. assert_equal(SystemExit, ex.class)
  262. # This check is not fully MRI-compatible (MRI reports more frames),
  263. # but at list this is something.
  264. expectation = %Q{
  265. +2:in `test_exception_from_thread_with_abort_on_exception_true'
  266. }
  267. check(expectation, ex)
  268. ensure
  269. Thread.abort_on_exception = false
  270. $stderr = STDERR
  271. end
  272. end