PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/test/ruby/test_exception.rb

http://github.com/ruby/ruby
Ruby | 1209 lines | 1076 code | 128 blank | 5 comment | 4 complexity | 9c513393a7c25c80aa24263a2af3ab48 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-3.0
  1. # frozen_string_literal: false
  2. require 'test/unit'
  3. require 'tempfile'
  4. class TestException < Test::Unit::TestCase
  5. def test_exception_rescued
  6. begin
  7. raise "this must be handled"
  8. assert(false)
  9. rescue
  10. assert(true)
  11. end
  12. end
  13. def test_exception_retry
  14. bad = true
  15. begin
  16. raise "this must be handled no.2"
  17. rescue
  18. if bad
  19. bad = false
  20. retry
  21. end
  22. assert(!bad)
  23. end
  24. assert(true)
  25. end
  26. def test_exception_in_rescue
  27. string = "this must be handled no.3"
  28. assert_raise_with_message(RuntimeError, string) do
  29. begin
  30. raise "exception in rescue clause"
  31. rescue
  32. raise string
  33. end
  34. assert(false)
  35. end
  36. end
  37. def test_exception_in_ensure
  38. string = "exception in ensure clause"
  39. assert_raise_with_message(RuntimeError, string) do
  40. begin
  41. raise "this must be handled no.4"
  42. ensure
  43. assert_instance_of(RuntimeError, $!)
  44. assert_equal("this must be handled no.4", $!.message)
  45. raise "exception in ensure clause"
  46. end
  47. assert(false)
  48. end
  49. end
  50. def test_exception_ensure
  51. bad = true
  52. begin
  53. begin
  54. raise "this must be handled no.5"
  55. ensure
  56. bad = false
  57. end
  58. rescue
  59. end
  60. assert(!bad)
  61. end
  62. def test_exception_ensure_2 # just duplication?
  63. bad = true
  64. begin
  65. begin
  66. raise "this must be handled no.6"
  67. ensure
  68. bad = false
  69. end
  70. rescue
  71. end
  72. assert(!bad)
  73. end
  74. def test_errinfo_in_debug
  75. bug9568 = EnvUtil.labeled_class("[ruby-core:61091] [Bug #9568]", RuntimeError) do
  76. def to_s
  77. require '\0'
  78. rescue LoadError
  79. self.class.to_s
  80. end
  81. end
  82. err = EnvUtil.verbose_warning do
  83. assert_raise(bug9568) do
  84. $DEBUG, debug = true, $DEBUG
  85. begin
  86. raise bug9568
  87. ensure
  88. $DEBUG = debug
  89. end
  90. end
  91. end
  92. assert_include(err, bug9568.to_s)
  93. end
  94. def test_errinfo_encoding_in_debug
  95. exc = Module.new {break class_eval("class C\u{30a8 30e9 30fc} < RuntimeError; self; end".encode(Encoding::EUC_JP))}
  96. exc.inspect
  97. err = EnvUtil.verbose_warning do
  98. assert_raise(exc) do
  99. $DEBUG, debug = true, $DEBUG
  100. begin
  101. raise exc
  102. ensure
  103. $DEBUG = debug
  104. end
  105. end
  106. end
  107. assert_include(err, exc.to_s)
  108. end
  109. def test_break_ensure
  110. bad = true
  111. while true
  112. begin
  113. break
  114. ensure
  115. bad = false
  116. end
  117. end
  118. assert(!bad)
  119. end
  120. def test_catch_no_throw
  121. assert_equal(:foo, catch {:foo})
  122. end
  123. def test_catch_throw
  124. result = catch(:foo) {
  125. loop do
  126. loop do
  127. throw :foo, true
  128. break
  129. end
  130. assert(false, "should not reach here")
  131. end
  132. false
  133. }
  134. assert(result)
  135. end
  136. def test_catch_throw_noarg
  137. assert_nothing_raised(UncaughtThrowError) {
  138. result = catch {|obj|
  139. throw obj, :ok
  140. assert(false, "should not reach here")
  141. }
  142. assert_equal(:ok, result)
  143. }
  144. end
  145. def test_uncaught_throw
  146. tag = nil
  147. e = assert_raise_with_message(UncaughtThrowError, /uncaught throw/) {
  148. catch("foo") {|obj|
  149. tag = obj.dup
  150. throw tag, :ok
  151. assert(false, "should not reach here")
  152. }
  153. assert(false, "should not reach here")
  154. }
  155. assert_not_nil(tag)
  156. assert_same(tag, e.tag)
  157. assert_equal(:ok, e.value)
  158. end
  159. def test_catch_throw_in_require
  160. bug7185 = '[ruby-dev:46234]'
  161. Tempfile.create(["dep", ".rb"]) {|t|
  162. t.puts("throw :extdep, 42")
  163. t.close
  164. assert_equal(42, assert_throw(:extdep, bug7185) {require t.path}, bug7185)
  165. }
  166. end
  167. def test_throw_false
  168. bug12743 = '[ruby-core:77229] [Bug #12743]'
  169. Thread.start {
  170. e = assert_raise_with_message(UncaughtThrowError, /false/, bug12743) {
  171. throw false
  172. }
  173. assert_same(false, e.tag, bug12743)
  174. }.join
  175. end
  176. def test_else_no_exception
  177. begin
  178. assert(true)
  179. rescue
  180. assert(false)
  181. else
  182. assert(true)
  183. end
  184. end
  185. def test_else_raised
  186. begin
  187. assert(true)
  188. raise
  189. assert(false)
  190. rescue
  191. assert(true)
  192. else
  193. assert(false)
  194. end
  195. end
  196. def test_else_nested_no_exception
  197. begin
  198. assert(true)
  199. begin
  200. assert(true)
  201. rescue
  202. assert(false)
  203. else
  204. assert(true)
  205. end
  206. assert(true)
  207. rescue
  208. assert(false)
  209. else
  210. assert(true)
  211. end
  212. end
  213. def test_else_nested_rescued
  214. begin
  215. assert(true)
  216. begin
  217. assert(true)
  218. raise
  219. assert(false)
  220. rescue
  221. assert(true)
  222. else
  223. assert(false)
  224. end
  225. assert(true)
  226. rescue
  227. assert(false)
  228. else
  229. assert(true)
  230. end
  231. end
  232. def test_else_nested_unrescued
  233. begin
  234. assert(true)
  235. begin
  236. assert(true)
  237. rescue
  238. assert(false)
  239. else
  240. assert(true)
  241. end
  242. assert(true)
  243. raise
  244. assert(false)
  245. rescue
  246. assert(true)
  247. else
  248. assert(false)
  249. end
  250. end
  251. def test_else_nested_rescued_reraise
  252. begin
  253. assert(true)
  254. begin
  255. assert(true)
  256. raise
  257. assert(false)
  258. rescue
  259. assert(true)
  260. else
  261. assert(false)
  262. end
  263. assert(true)
  264. raise
  265. assert(false)
  266. rescue
  267. assert(true)
  268. else
  269. assert(false)
  270. end
  271. end
  272. def test_raise_with_wrong_number_of_arguments
  273. assert_raise(TypeError) { raise nil }
  274. assert_raise(TypeError) { raise 1, 1 }
  275. assert_raise(ArgumentError) { raise 1, 1, 1, 1 }
  276. end
  277. def test_type_error_message_encoding
  278. c = eval("Module.new do break class C\u{4032}; self; end; end")
  279. o = c.new
  280. assert_raise_with_message(TypeError, /C\u{4032}/) do
  281. ""[o]
  282. end
  283. c.class_eval {def to_int; self; end}
  284. assert_raise_with_message(TypeError, /C\u{4032}/) do
  285. ""[o]
  286. end
  287. c.class_eval {def to_a; self; end}
  288. assert_raise_with_message(TypeError, /C\u{4032}/) do
  289. [*o]
  290. end
  291. obj = eval("class C\u{1f5ff}; self; end").new
  292. assert_raise_with_message(TypeError, /C\u{1f5ff}/) do
  293. Class.new {include obj}
  294. end
  295. end
  296. def test_errat
  297. assert_in_out_err([], "p $@", %w(nil), [])
  298. assert_in_out_err([], "$@ = 1", [], /\$! not set \(ArgumentError\)$/)
  299. assert_in_out_err([], <<-INPUT, [], /backtrace must be Array of String \(TypeError\)$/)
  300. begin
  301. raise
  302. rescue
  303. $@ = 1
  304. end
  305. INPUT
  306. assert_in_out_err([], <<-INPUT, [], /^foo: unhandled exception$/)
  307. begin
  308. raise
  309. rescue
  310. $@ = 'foo'
  311. raise
  312. end
  313. INPUT
  314. assert_in_out_err([], <<-INPUT, [], /^foo: unhandled exception\s+from bar\s+from baz$/)
  315. begin
  316. raise
  317. rescue
  318. $@ = %w(foo bar baz)
  319. raise
  320. end
  321. INPUT
  322. end
  323. def test_thread_signal_location
  324. skip
  325. _, stderr, _ = EnvUtil.invoke_ruby(%w"--disable-gems -d", <<-RUBY, false, true)
  326. Thread.start do
  327. Thread.current.report_on_exception = false
  328. begin
  329. Process.kill(:INT, $$)
  330. ensure
  331. raise "in ensure"
  332. end
  333. end.join
  334. RUBY
  335. assert_not_match(/:0/, stderr, "[ruby-dev:39116]")
  336. end
  337. def test_errinfo
  338. begin
  339. raise "foo"
  340. assert(false)
  341. rescue => e
  342. assert_equal(e, $!)
  343. 1.times { assert_equal(e, $!) }
  344. end
  345. assert_equal(nil, $!)
  346. end
  347. def test_inspect
  348. assert_equal("#<Exception: Exception>", Exception.new.inspect)
  349. e = Class.new(Exception)
  350. e.class_eval do
  351. def to_s; ""; end
  352. end
  353. assert_equal(e.inspect, e.new.inspect)
  354. end
  355. def test_to_s
  356. e = StandardError.new("foo")
  357. assert_equal("foo", e.to_s)
  358. def (s = Object.new).to_s
  359. "bar"
  360. end
  361. e = StandardError.new(s)
  362. assert_equal("bar", e.to_s)
  363. end
  364. def test_set_backtrace
  365. e = Exception.new
  366. e.set_backtrace("foo")
  367. assert_equal(["foo"], e.backtrace)
  368. e.set_backtrace(%w(foo bar baz))
  369. assert_equal(%w(foo bar baz), e.backtrace)
  370. assert_raise(TypeError) { e.set_backtrace(1) }
  371. assert_raise(TypeError) { e.set_backtrace([1]) }
  372. end
  373. def test_exit_success_p
  374. begin
  375. exit
  376. rescue SystemExit => e
  377. end
  378. assert_send([e, :success?], "success by default")
  379. begin
  380. exit(true)
  381. rescue SystemExit => e
  382. end
  383. assert_send([e, :success?], "true means success")
  384. begin
  385. exit(false)
  386. rescue SystemExit => e
  387. end
  388. assert_not_send([e, :success?], "false means failure")
  389. begin
  390. abort
  391. rescue SystemExit => e
  392. end
  393. assert_not_send([e, :success?], "abort means failure")
  394. end
  395. def test_errno
  396. assert_equal(Encoding.find("locale"), Errno::EINVAL.new.message.encoding)
  397. end
  398. def test_too_many_args_in_eval
  399. bug5720 = '[ruby-core:41520]'
  400. arg_string = (0...140000).to_a.join(", ")
  401. assert_raise(SystemStackError, bug5720) {eval "raise(#{arg_string})"}
  402. end
  403. def test_systemexit_new
  404. e0 = SystemExit.new
  405. assert_equal(0, e0.status)
  406. assert_equal("SystemExit", e0.message)
  407. ei = SystemExit.new(3)
  408. assert_equal(3, ei.status)
  409. assert_equal("SystemExit", ei.message)
  410. es = SystemExit.new("msg")
  411. assert_equal(0, es.status)
  412. assert_equal("msg", es.message)
  413. eis = SystemExit.new(7, "msg")
  414. assert_equal(7, eis.status)
  415. assert_equal("msg", eis.message)
  416. bug5728 = '[ruby-dev:44951]'
  417. et = SystemExit.new(true)
  418. assert_equal(true, et.success?, bug5728)
  419. assert_equal("SystemExit", et.message, bug5728)
  420. ef = SystemExit.new(false)
  421. assert_equal(false, ef.success?, bug5728)
  422. assert_equal("SystemExit", ef.message, bug5728)
  423. ets = SystemExit.new(true, "msg")
  424. assert_equal(true, ets.success?, bug5728)
  425. assert_equal("msg", ets.message, bug5728)
  426. efs = SystemExit.new(false, "msg")
  427. assert_equal(false, efs.success?, bug5728)
  428. assert_equal("msg", efs.message, bug5728)
  429. end
  430. def test_exception_in_name_error_to_str
  431. assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
  432. bug5575 = '[ruby-core:41612]'
  433. begin;
  434. begin
  435. BasicObject.new.inspect
  436. rescue
  437. assert_nothing_raised(NameError, bug5575) {$!.inspect}
  438. end
  439. end;
  440. end
  441. def test_equal
  442. bug5865 = '[ruby-core:41979]'
  443. assert_equal(RuntimeError.new("a"), RuntimeError.new("a"), bug5865)
  444. assert_not_equal(RuntimeError.new("a"), StandardError.new("a"), bug5865)
  445. end
  446. def test_exception_in_exception_equal
  447. assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
  448. bug5865 = '[ruby-core:41979]'
  449. begin;
  450. o = Object.new
  451. def o.exception(arg)
  452. end
  453. assert_nothing_raised(ArgumentError, bug5865) do
  454. RuntimeError.new("a") == o
  455. end
  456. end;
  457. end
  458. def test_backtrace_by_exception
  459. begin
  460. line = __LINE__; raise "foo"
  461. rescue => e
  462. end
  463. e2 = e.exception("bar")
  464. assert_not_equal(e.message, e2.message)
  465. assert_equal(e.backtrace, e2.backtrace)
  466. loc = e2.backtrace_locations[0]
  467. assert_equal([__FILE__, line], [loc.path, loc.lineno])
  468. end
  469. Bug4438 = '[ruby-core:35364]'
  470. def test_rescue_single_argument
  471. assert_raise(TypeError, Bug4438) do
  472. begin
  473. raise
  474. rescue 1
  475. end
  476. end
  477. end
  478. def test_rescue_splat_argument
  479. assert_raise(TypeError, Bug4438) do
  480. begin
  481. raise
  482. rescue *Array(1)
  483. end
  484. end
  485. end
  486. def m
  487. m(&->{return 0})
  488. 42
  489. end
  490. def test_stackoverflow
  491. feature6216 = '[ruby-core:43794] [Feature #6216]'
  492. e = assert_raise(SystemStackError, feature6216) {m}
  493. level = e.backtrace.size
  494. assert_operator(level, :>, 10, feature6216)
  495. feature6216 = '[ruby-core:63377] [Feature #6216]'
  496. e = assert_raise(SystemStackError, feature6216) {raise e}
  497. assert_equal(level, e.backtrace.size, feature6216)
  498. end
  499. def test_machine_stackoverflow
  500. bug9109 = '[ruby-dev:47804] [Bug #9109]'
  501. assert_separately(%w[--disable-gem], <<-SRC)
  502. assert_raise(SystemStackError, #{bug9109.dump}) {
  503. h = {a: ->{h[:a].call}}
  504. h[:a].call
  505. }
  506. SRC
  507. rescue SystemStackError
  508. end
  509. def test_machine_stackoverflow_by_define_method
  510. bug9454 = '[ruby-core:60113] [Bug #9454]'
  511. assert_separately(%w[--disable-gem], <<-SRC)
  512. assert_raise(SystemStackError, #{bug9454.dump}) {
  513. define_method(:foo) {self.foo}
  514. self.foo
  515. }
  516. SRC
  517. rescue SystemStackError
  518. end
  519. def test_machine_stackoverflow_by_trace
  520. assert_normal_exit("#{<<-"begin;"}\n#{<<~"end;"}", timeout: 60)
  521. begin;
  522. require 'timeout'
  523. require 'tracer'
  524. class HogeError < StandardError
  525. def to_s
  526. message.upcase # disable tailcall optimization
  527. end
  528. end
  529. Tracer.stdout = open(IO::NULL, "w")
  530. begin
  531. Timeout.timeout(5) do
  532. Tracer.on
  533. HogeError.new.to_s
  534. end
  535. rescue Timeout::Error
  536. # ok. there are no SEGV or critical error
  537. rescue SystemStackError => e
  538. # ok.
  539. end
  540. end;
  541. end
  542. def test_cause
  543. msg = "[Feature #8257]"
  544. cause = nil
  545. e = assert_raise(StandardError) {
  546. begin
  547. raise msg
  548. rescue => e
  549. cause = e.cause
  550. raise StandardError
  551. end
  552. }
  553. assert_nil(cause, msg)
  554. cause = e.cause
  555. assert_instance_of(RuntimeError, cause, msg)
  556. assert_equal(msg, cause.message, msg)
  557. end
  558. def test_cause_reraised
  559. msg = "[Feature #8257]"
  560. e = assert_raise(RuntimeError) {
  561. begin
  562. raise msg
  563. rescue => e
  564. raise e
  565. end
  566. }
  567. assert_not_same(e, e.cause, "#{msg}: should not be recursive")
  568. end
  569. def test_cause_raised_in_rescue
  570. a = nil
  571. e = assert_raise_with_message(RuntimeError, 'b') {
  572. begin
  573. raise 'a'
  574. rescue => a
  575. begin
  576. raise 'b'
  577. rescue => b
  578. assert_same(a, b.cause)
  579. begin
  580. raise 'c'
  581. rescue
  582. raise b
  583. end
  584. end
  585. end
  586. }
  587. assert_same(a, e.cause, 'cause should not be overwritten by reraise')
  588. end
  589. def test_cause_at_raised
  590. a = nil
  591. e = assert_raise_with_message(RuntimeError, 'b') {
  592. begin
  593. raise 'a'
  594. rescue => a
  595. b = RuntimeError.new('b')
  596. assert_nil(b.cause)
  597. begin
  598. raise 'c'
  599. rescue
  600. raise b
  601. end
  602. end
  603. }
  604. assert_equal('c', e.cause.message, 'cause should be the exception at raised')
  605. assert_same(a, e.cause.cause)
  606. end
  607. def test_cause_at_end
  608. errs = [
  609. /-: unexpected return\n/,
  610. /.*undefined local variable or method `n'.*\n/,
  611. ]
  612. assert_in_out_err([], <<-'end;', [], errs)
  613. END{n}; END{return}
  614. end;
  615. end
  616. def test_raise_with_cause
  617. msg = "[Feature #8257]"
  618. cause = ArgumentError.new("foobar")
  619. e = assert_raise(RuntimeError) {raise msg, cause: cause}
  620. assert_same(cause, e.cause)
  621. end
  622. def test_cause_with_no_arguments
  623. cause = ArgumentError.new("foobar")
  624. assert_raise_with_message(ArgumentError, /with no arguments/) do
  625. raise cause: cause
  626. end
  627. end
  628. def test_raise_with_cause_in_rescue
  629. e = assert_raise_with_message(RuntimeError, 'b') {
  630. begin
  631. raise 'a'
  632. rescue => a
  633. begin
  634. raise 'b'
  635. rescue => b
  636. assert_same(a, b.cause)
  637. begin
  638. raise 'c'
  639. rescue
  640. raise b, cause: ArgumentError.new('d')
  641. end
  642. end
  643. end
  644. }
  645. assert_equal('d', e.cause.message, 'cause option should be honored always')
  646. assert_nil(e.cause.cause)
  647. end
  648. def test_cause_thread_no_cause
  649. bug12741 = '[ruby-core:77222] [Bug #12741]'
  650. x = Thread.current
  651. a = false
  652. y = Thread.start do
  653. Thread.pass until a
  654. x.raise "stop"
  655. end
  656. begin
  657. raise bug12741
  658. rescue
  659. e = assert_raise_with_message(RuntimeError, "stop") do
  660. a = true
  661. sleep 1
  662. end
  663. end
  664. assert_nil(e.cause)
  665. ensure
  666. y.join
  667. end
  668. def test_cause_thread_with_cause
  669. bug12741 = '[ruby-core:77222] [Bug #12741]'
  670. x = Thread.current
  671. q = Queue.new
  672. y = Thread.start do
  673. q.pop
  674. begin
  675. raise "caller's cause"
  676. rescue
  677. x.raise "stop"
  678. end
  679. end
  680. begin
  681. raise bug12741
  682. rescue
  683. e = assert_raise_with_message(RuntimeError, "stop") do
  684. q.push(true)
  685. sleep 1
  686. end
  687. ensure
  688. y.join
  689. end
  690. assert_equal("caller's cause", e.cause.message)
  691. end
  692. def test_unknown_option
  693. bug = '[ruby-core:63203] [Feature #8257] should pass unknown options'
  694. exc = Class.new(RuntimeError) do
  695. attr_reader :arg
  696. def initialize(msg = nil)
  697. @arg = msg
  698. super(msg)
  699. end
  700. end
  701. e = assert_raise(exc, bug) {raise exc, "foo" => "bar", foo: "bar"}
  702. assert_equal({"foo" => "bar", foo: "bar"}, e.arg, bug)
  703. e = assert_raise(exc, bug) {raise exc, "foo" => "bar", foo: "bar", cause: RuntimeError.new("zzz")}
  704. assert_equal({"foo" => "bar", foo: "bar"}, e.arg, bug)
  705. e = assert_raise(exc, bug) {raise exc, {}}
  706. assert_equal({}, e.arg, bug)
  707. end
  708. def test_circular_cause
  709. bug13043 = '[ruby-core:78688] [Bug #13043]'
  710. begin
  711. begin
  712. raise "error 1"
  713. ensure
  714. orig_error = $!
  715. begin
  716. raise "error 2"
  717. rescue => err
  718. raise orig_error
  719. end
  720. end
  721. rescue => x
  722. end
  723. assert_equal(orig_error, x)
  724. assert_equal(orig_error, err.cause)
  725. assert_nil(orig_error.cause, bug13043)
  726. end
  727. def test_cause_with_frozen_exception
  728. exc = ArgumentError.new("foo").freeze
  729. assert_raise_with_message(ArgumentError, exc.message) {
  730. raise exc, cause: RuntimeError.new("bar")
  731. }
  732. end
  733. def test_anonymous_message
  734. assert_in_out_err([], "raise Class.new(RuntimeError), 'foo'", [], /foo\n/)
  735. end
  736. def test_output_string_encoding
  737. # "\x82\xa0" in cp932 is "\u3042" (Japanese hiragana 'a')
  738. # change $stderr to force calling rb_io_write() instead of fwrite()
  739. assert_in_out_err(["-Eutf-8:cp932"], '# coding: cp932
  740. $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
  741. assert_equal 1, outs.size
  742. assert_equal 0, errs.size
  743. err = outs.first.force_encoding('utf-8')
  744. assert err.valid_encoding?, 'must be valid encoding'
  745. assert_match %r/\u3042/, err
  746. end
  747. end
  748. def test_multibyte_and_newline
  749. bug10727 = '[ruby-core:67473] [Bug #10727]'
  750. assert_in_out_err([], <<-'end;', [], /\u{306b 307b 3093 3054} \(E\)\n\u{6539 884c}/, bug10727, encoding: "UTF-8")
  751. class E < StandardError
  752. def initialize
  753. super("\u{306b 307b 3093 3054}\n\u{6539 884c}")
  754. end
  755. end
  756. raise E
  757. end;
  758. end
  759. def assert_null_char(src, *args, **opts)
  760. begin
  761. eval(src)
  762. rescue => e
  763. end
  764. assert_not_nil(e)
  765. assert_include(e.message, "\0")
  766. assert_in_out_err([], src, [], [], *args, **opts) do |_, err,|
  767. err.each do |e|
  768. assert_not_include(e, "\0")
  769. end
  770. end
  771. e
  772. end
  773. def test_control_in_message
  774. bug7574 = '[ruby-dev:46749]'
  775. assert_null_char("#{<<~"begin;"}\n#{<<~'end;'}", bug7574)
  776. begin;
  777. Object.const_defined?("String\0")
  778. end;
  779. assert_null_char("#{<<~"begin;"}\n#{<<~'end;'}", bug7574)
  780. begin;
  781. Object.const_get("String\0")
  782. end;
  783. end
  784. def test_encoding_in_message
  785. name = "\u{e9}t\u{e9}"
  786. e = EnvUtil.with_default_external("US-ASCII") do
  787. assert_raise(NameError) do
  788. Object.const_get(name)
  789. end
  790. end
  791. assert_include(e.message, name)
  792. end
  793. def test_method_missing_reason_clear
  794. bug10969 = '[ruby-core:68515] [Bug #10969]'
  795. a = Class.new {def method_missing(*) super end}.new
  796. assert_raise(NameError) {a.instance_eval("foo")}
  797. assert_raise(NoMethodError, bug10969) {a.public_send("bar", true)}
  798. end
  799. def test_message_of_name_error
  800. assert_raise_with_message(NameError, /\Aundefined method `foo' for module `#<Module:.*>'$/) do
  801. Module.new do
  802. module_function :foo
  803. end
  804. end
  805. end
  806. def capture_warning_warn
  807. verbose = $VERBOSE
  808. deprecated = Warning[:deprecated]
  809. warning = []
  810. ::Warning.class_eval do
  811. alias_method :warn2, :warn
  812. remove_method :warn
  813. define_method(:warn) do |str|
  814. warning << str
  815. end
  816. end
  817. $VERBOSE = true
  818. Warning[:deprecated] = true
  819. yield
  820. return warning
  821. ensure
  822. $VERBOSE = verbose
  823. Warning[:deprecated] = deprecated
  824. ::Warning.class_eval do
  825. remove_method :warn
  826. alias_method :warn, :warn2
  827. remove_method :warn2
  828. end
  829. end
  830. def test_warning_warn
  831. warning = capture_warning_warn {@a}
  832. assert_match(/instance variable @a not initialized/, warning[0])
  833. assert_equal(["a\nz\n"], capture_warning_warn {warn "a\n", "z"})
  834. assert_equal([], capture_warning_warn {warn})
  835. assert_equal(["\n"], capture_warning_warn {warn ""})
  836. end
  837. def test_kernel_warn_uplevel
  838. warning = capture_warning_warn {warn("test warning", uplevel: 0)}
  839. assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0])
  840. def (obj = Object.new).w(n) warn("test warning", uplevel: n) end
  841. warning = capture_warning_warn {obj.w(0)}
  842. assert_equal("#{__FILE__}:#{__LINE__-2}: warning: test warning\n", warning[0])
  843. warning = capture_warning_warn {obj.w(1)}
  844. assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0])
  845. assert_raise(ArgumentError) {warn("test warning", uplevel: -1)}
  846. assert_in_out_err(["-e", "warn 'ok', uplevel: 1"], '', [], /warning:/)
  847. warning = capture_warning_warn {warn("test warning", {uplevel: 0})}
  848. assert_match(/test warning.*{:uplevel=>0}/m, warning[0])
  849. warning = capture_warning_warn {warn("test warning", **{uplevel: 0})}
  850. assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0])
  851. warning = capture_warning_warn {warn("test warning", {uplevel: 0}, **{})}
  852. assert_equal("test warning\n{:uplevel=>0}\n", warning[0])
  853. assert_raise(ArgumentError) {warn("test warning", foo: 1)}
  854. end
  855. def test_warning_warn_invalid_argument
  856. assert_raise(TypeError) do
  857. ::Warning.warn nil
  858. end
  859. assert_raise(TypeError) do
  860. ::Warning.warn 1
  861. end
  862. assert_raise(Encoding::CompatibilityError) do
  863. ::Warning.warn "\x00a\x00b\x00c".force_encoding("utf-16be")
  864. end
  865. end
  866. def test_warning_warn_circular_require_backtrace
  867. warning = nil
  868. path = nil
  869. Tempfile.create(%w[circular .rb]) do |t|
  870. path = File.realpath(t.path)
  871. basename = File.basename(path)
  872. t.puts "require '#{basename}'"
  873. t.close
  874. $LOAD_PATH.push(File.dirname(t))
  875. warning = capture_warning_warn {
  876. assert require(basename)
  877. }
  878. ensure
  879. $LOAD_PATH.pop
  880. $LOADED_FEATURES.delete(t.path)
  881. end
  882. assert_equal(1, warning.size)
  883. assert_match(/circular require/, warning.first)
  884. assert_match(/^\tfrom #{Regexp.escape(path)}:1:/, warning.first)
  885. end
  886. def test_warning_warn_super
  887. assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /instance variable @a not initialized/)
  888. {#
  889. module Warning
  890. def warn(message)
  891. super
  892. end
  893. end
  894. $VERBOSE = true
  895. @a
  896. };
  897. end
  898. def test_warning_category
  899. assert_raise(TypeError) {Warning[nil]}
  900. assert_raise(ArgumentError) {Warning[:XXXX]}
  901. assert_include([true, false], Warning[:deprecated])
  902. assert_include([true, false], Warning[:experimental])
  903. end
  904. def test_undefined_backtrace
  905. assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
  906. begin;
  907. class Exception
  908. undef backtrace
  909. end
  910. assert_raise(RuntimeError) {
  911. raise RuntimeError, "hello"
  912. }
  913. end;
  914. end
  915. def test_redefined_backtrace
  916. assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
  917. begin;
  918. $exc = nil
  919. class Exception
  920. undef backtrace
  921. def backtrace
  922. $exc = self
  923. end
  924. end
  925. e = assert_raise(RuntimeError) {
  926. raise RuntimeError, "hello"
  927. }
  928. assert_same(e, $exc)
  929. end;
  930. end
  931. def test_blocking_backtrace
  932. assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
  933. begin;
  934. class Bug < RuntimeError
  935. def backtrace
  936. IO.readlines(IO::NULL)
  937. end
  938. end
  939. bug = Bug.new '[ruby-core:85939] [Bug #14577]'
  940. n = 10000
  941. i = 0
  942. n.times do
  943. begin
  944. raise bug
  945. rescue Bug
  946. i += 1
  947. end
  948. end
  949. assert_equal(n, i)
  950. end;
  951. end
  952. def test_wrong_backtrace
  953. assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
  954. begin;
  955. class Exception
  956. undef backtrace
  957. def backtrace(a)
  958. end
  959. end
  960. assert_raise(RuntimeError) {
  961. raise RuntimeError, "hello"
  962. }
  963. end;
  964. error_class = Class.new(StandardError) do
  965. def backtrace; :backtrace; end
  966. end
  967. begin
  968. raise error_class
  969. rescue error_class => e
  970. assert_raise(TypeError) {$@}
  971. assert_raise(TypeError) {e.full_message}
  972. end
  973. end
  974. def test_backtrace_in_eval
  975. bug = '[ruby-core:84434] [Bug #14229]'
  976. assert_in_out_err(['-e', 'eval("raise")'], "", [], /^\(eval\):1:/, bug)
  977. end
  978. def test_full_message
  979. message = RuntimeError.new("testerror").full_message
  980. assert_operator(message, :end_with?, "\n")
  981. test_method = "def foo; raise 'testerror'; end"
  982. out1, err1, status1 = EnvUtil.invoke_ruby(['-e', "#{test_method}; begin; foo; rescue => e; puts e.full_message; end"], '', true, true)
  983. assert_predicate(status1, :success?)
  984. assert_empty(err1, "expected nothing wrote to $stdout by #full_message")
  985. _, err2, status1 = EnvUtil.invoke_ruby(['-e', "#{test_method}; begin; foo; end"], '', true, true)
  986. assert_equal(err2, out1)
  987. e = RuntimeError.new("a\n")
  988. message = assert_nothing_raised(ArgumentError, proc {e.pretty_inspect}) do
  989. e.full_message
  990. end
  991. assert_operator(message, :end_with?, "\n")
  992. message = message.gsub(/\e\[[\d;]*m/, '')
  993. assert_not_operator(message, :end_with?, "\n\n")
  994. e = RuntimeError.new("a\n\nb\n\nc")
  995. message = assert_nothing_raised(ArgumentError, proc {e.pretty_inspect}) do
  996. e.full_message
  997. end
  998. assert_all?(message.lines) do |m|
  999. /\e\[\d[;\d]*m[^\e]*\n/ !~ m
  1000. end
  1001. e = RuntimeError.new("testerror")
  1002. message = e.full_message(highlight: false)
  1003. assert_not_match(/\e/, message)
  1004. bt = ["test:100", "test:99", "test:98", "test:1"]
  1005. e = assert_raise(RuntimeError) {raise RuntimeError, "testerror", bt}
  1006. bottom = "test:100: testerror (RuntimeError)\n"
  1007. top = "test:1\n"
  1008. remark = "Traceback (most recent call last):"
  1009. message = e.full_message(highlight: false, order: :top)
  1010. assert_not_match(/\e/, message)
  1011. assert_operator(message.count("\n"), :>, 2)
  1012. assert_operator(message, :start_with?, bottom)
  1013. assert_operator(message, :end_with?, top)
  1014. message = e.full_message(highlight: false, order: :bottom)
  1015. assert_not_match(/\e/, message)
  1016. assert_operator(message.count("\n"), :>, 2)
  1017. assert_operator(message, :start_with?, remark)
  1018. assert_operator(message, :end_with?, bottom)
  1019. assert_raise_with_message(ArgumentError, /:top or :bottom/) {
  1020. e.full_message(highlight: false, order: :middle)
  1021. }
  1022. message = e.full_message(highlight: true)
  1023. assert_match(/\e/, message)
  1024. assert_not_match(/(\e\[1)m\1/, message)
  1025. e2 = assert_raise(RuntimeError) {raise RuntimeError, "", bt}
  1026. assert_not_match(/(\e\[1)m\1/, e2.full_message(highlight: true))
  1027. message = e.full_message
  1028. if Exception.to_tty?
  1029. assert_match(/\e/, message)
  1030. message = message.gsub(/\e\[[\d;]*m/, '')
  1031. else
  1032. assert_not_match(/\e/, message)
  1033. end
  1034. assert_operator(message, :start_with?, bottom)
  1035. assert_operator(message, :end_with?, top)
  1036. end
  1037. def test_exception_in_message
  1038. code = "#{<<~"begin;"}\n#{<<~'end;'}"
  1039. begin;
  1040. class Bug14566 < StandardError
  1041. def message; raise self.class; end
  1042. end
  1043. raise Bug14566
  1044. end;
  1045. assert_in_out_err([], code, [], /Bug14566/, success: false, timeout: 2)
  1046. end
  1047. def test_non_exception_cause
  1048. assert_raise_with_message(TypeError, /exception/) do
  1049. raise "foo", cause: 1
  1050. end;
  1051. end
  1052. def test_circular_cause_handle
  1053. assert_raise_with_message(ArgumentError, /circular cause/) do
  1054. begin
  1055. raise "error 1"
  1056. rescue => e1
  1057. raise "error 2" rescue raise e1, cause: $!
  1058. end
  1059. end;
  1060. end
  1061. def test_super_in_method_missing
  1062. assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
  1063. begin;
  1064. $VERBOSE = nil
  1065. class Object
  1066. def method_missing(name, *args, &block)
  1067. super
  1068. end
  1069. end
  1070. bug14670 = '[ruby-dev:50522] [Bug #14670]'
  1071. assert_raise_with_message(NoMethodError, /`foo'/, bug14670) do
  1072. Object.new.foo
  1073. end
  1074. end;
  1075. end
  1076. end