PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Languages/Ruby/IronRuby.Tests/Runtime/ExceptionTests.cs

#
C# | 811 lines | 735 code | 50 blank | 26 comment | 0 complexity | 8ef6741b82fd56de412690ebcbd39b55 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using IronRuby.Builtins;
  17. namespace IronRuby.Tests {
  18. public partial class Tests {
  19. public void Scenario_RubyExceptions1() {
  20. AssertExceptionThrown<RuntimeError>(delegate() {
  21. CompilerTest(@"raise");
  22. });
  23. }
  24. public void Scenario_RubyExceptions1A() {
  25. AssertExceptionThrown<RuntimeError>(delegate() {
  26. CompilerTest(@"raise 'foo'");
  27. });
  28. }
  29. public void Scenario_RubyExceptions2A() {
  30. AssertExceptionThrown<NotImplementedError>(delegate() {
  31. CompilerTest(@"
  32. $! = NotImplementedError.new
  33. raise");
  34. });
  35. }
  36. public void Scenario_RubyExceptions2B() {
  37. AssertExceptionThrown<InvalidOperationException>(delegate() {
  38. CompilerTest("$! = NotImplementedError");
  39. });
  40. }
  41. public void Scenario_RubyExceptions2C() {
  42. AssertOutput(delegate() {
  43. CompilerTest(@"
  44. x = NotImplementedError.new 'hello'
  45. puts x.message
  46. x.message[0] = ?H
  47. puts x.message
  48. x.send :initialize
  49. puts x.message
  50. x.send :initialize, 'Bye'
  51. puts x.message
  52. ");
  53. }, @"
  54. hello
  55. Hello
  56. NotImplementedError
  57. Bye
  58. ");
  59. }
  60. public void Scenario_RubyExceptions2D() {
  61. AssertOutput(delegate() {
  62. CompilerTest(@"
  63. x = IOError.new 'hello'
  64. puts x.message
  65. x.message[0] = ?H
  66. puts x.message
  67. x.send :initialize
  68. puts x.message
  69. x.send :initialize,'Bye'
  70. puts x.message
  71. ");
  72. }, @"
  73. hello
  74. Hello
  75. IOError
  76. Bye
  77. ");
  78. }
  79. public void Scenario_RubyExceptions3() {
  80. AssertOutput(delegate() {
  81. CompilerTest(@"
  82. begin
  83. raise
  84. print 'U'
  85. rescue
  86. print 'X'
  87. end
  88. ");
  89. }, "X");
  90. }
  91. public void Scenario_RubyExceptions4() {
  92. AssertOutput(delegate() {
  93. CompilerTest(@"
  94. begin
  95. raise
  96. print 'U'
  97. rescue IOError
  98. print 'U'
  99. rescue StandardError
  100. print 'X'
  101. end
  102. ");
  103. }, "X");
  104. }
  105. public void Scenario_RubyExceptions5() {
  106. AssertOutput(delegate() {
  107. CompilerTest(@"
  108. begin
  109. raise
  110. rescue StandardError => $x
  111. puts 'Caught'
  112. puts ""$! = '#{$!.class.name}'""
  113. puts ""$x = '#{$x.class.name}'""
  114. end
  115. ");
  116. }, @"
  117. Caught
  118. $! = 'RuntimeError'
  119. $x = 'RuntimeError'
  120. ");
  121. }
  122. public void Scenario_RubyExceptions6() {
  123. AssertOutput(delegate() {
  124. CompilerTest(@"
  125. x = StandardError
  126. begin
  127. raise
  128. rescue x => x
  129. puts 'Caught'
  130. puts ""$! = '#{$!.class.name}'""
  131. puts ""x = '#{x.class.name}'""
  132. end
  133. ");
  134. }, @"
  135. Caught
  136. $! = 'RuntimeError'
  137. x = 'RuntimeError'
  138. ");
  139. }
  140. public void Scenario_RubyExceptions7() {
  141. AssertOutput(delegate() {
  142. CompilerTest(@"
  143. def foo
  144. raise
  145. end
  146. begin
  147. foo
  148. rescue Exception => e
  149. $found = false
  150. e.backtrace.each { |frame| if frame.index('foo') != nil then $found = true end }
  151. puts $found
  152. end");
  153. }, @"true");
  154. }
  155. public void Scenario_RubyExceptions8() {
  156. AssertOutput(delegate() {
  157. CompilerTest(@"
  158. puts 'Begin'
  159. x = begin
  160. puts 'Raise'
  161. 1
  162. raise
  163. puts 'Unreachable'
  164. 2
  165. rescue IOError
  166. puts 'Rescue1'
  167. 3
  168. rescue
  169. puts 'Rescue2'
  170. 4
  171. else
  172. puts 'Else'
  173. 5
  174. ensure
  175. puts 'Ensure'
  176. 6
  177. end
  178. puts x
  179. puts 'End'
  180. ");
  181. }, @"
  182. Begin
  183. Raise
  184. Rescue2
  185. Ensure
  186. 4
  187. End
  188. ");
  189. }
  190. public void Scenario_RubyExceptions9() {
  191. AssertOutput(delegate() {
  192. CompilerTest(@"
  193. puts 'Begin'
  194. x = class C
  195. puts 'Raise'
  196. 1
  197. rescue IOError
  198. puts 'Rescue1'
  199. 3
  200. else
  201. puts 'Else'
  202. 5
  203. ensure
  204. puts 'Ensure'
  205. 6
  206. end
  207. puts x
  208. puts 'End'
  209. ");
  210. }, @"
  211. Begin
  212. Raise
  213. Else
  214. Ensure
  215. 5
  216. End
  217. ");
  218. }
  219. public void Scenario_RubyExceptions10() {
  220. AssertOutput(delegate() {
  221. CompilerTest(@"
  222. puts 'Begin'
  223. begin
  224. puts 'Class'
  225. class C
  226. puts 'NoRaise'
  227. rescue
  228. puts 'Rescue'
  229. else
  230. puts 'Else'
  231. ensure
  232. puts 'Ensure'
  233. end
  234. puts 'ClassEnd'
  235. rescue
  236. puts 'OuterRescue'
  237. end
  238. puts 'End'
  239. ");
  240. }, @"
  241. Begin
  242. Class
  243. NoRaise
  244. Else
  245. Ensure
  246. ClassEnd
  247. End
  248. ");
  249. }
  250. public void Scenario_RubyExceptions11() {
  251. AssertOutput(delegate() {
  252. CompilerTest(@"
  253. puts 'Begin'
  254. begin
  255. puts 'Class'
  256. class C
  257. puts 'NoRaise'
  258. rescue
  259. puts 'Rescue'
  260. else
  261. puts 'Else'
  262. ensure
  263. puts 'Ensure'
  264. end
  265. puts 'ClassEnd'
  266. rescue
  267. puts 'OutterRescue'
  268. end
  269. puts 'End'
  270. ");
  271. }, @"
  272. Begin
  273. Class
  274. NoRaise
  275. Else
  276. Ensure
  277. ClassEnd
  278. End
  279. ");
  280. }
  281. public void Scenario_RubyExceptions12() {
  282. AssertOutput(delegate() {
  283. CompilerTest(@"
  284. class A < Exception; end
  285. class B < Exception; end
  286. class C < Exception; end
  287. begin
  288. raise B
  289. rescue A,B,C => e
  290. puts e.class
  291. end
  292. ");
  293. }, @"B");
  294. }
  295. /// <summary>
  296. /// Order of evaluation inside rescue clauses.
  297. /// </summary>
  298. public void Scenario_RubyExceptions12A() {
  299. AssertOutput(delegate() {
  300. CompilerTest(@"
  301. class Module
  302. alias old ===
  303. def ===(other)
  304. puts ""cmp(#{self}, #{other})""
  305. old other
  306. end
  307. end
  308. class A < Exception; end
  309. class B < Exception; end
  310. class C < Exception; end
  311. class D < Exception; end
  312. class E < Exception; end
  313. class F < Exception; end
  314. class G < Exception; end
  315. def id(t)
  316. puts ""r(#{t})""
  317. t
  318. end
  319. def foo
  320. raise F
  321. rescue id(A),id(B),id(C)
  322. puts 'rescued 1' # unreachable
  323. rescue id(E),id(F),id(G)
  324. puts 'rescued 2'
  325. end
  326. foo
  327. ");
  328. }, @"
  329. r(A)
  330. r(B)
  331. r(C)
  332. cmp(A, F)
  333. cmp(B, F)
  334. cmp(C, F)
  335. r(E)
  336. r(F)
  337. r(G)
  338. cmp(E, F)
  339. cmp(F, F)
  340. rescued 2
  341. ");
  342. }
  343. /// <summary>
  344. /// Retry try-catch block.
  345. /// </summary>
  346. public void Scenario_RubyExceptions13() {
  347. AssertOutput(delegate() {
  348. CompilerTest(@"
  349. i = 0
  350. begin
  351. puts i
  352. i = i + 1
  353. if i < 3 then raise end
  354. rescue
  355. puts 'retrying'
  356. retry
  357. else
  358. puts 'no exception'
  359. ensure
  360. puts 'giving up'
  361. end
  362. ");
  363. }, @"
  364. 0
  365. retrying
  366. 1
  367. retrying
  368. 2
  369. no exception
  370. giving up
  371. ");
  372. }
  373. public void Scenario_RubyExceptions14() {
  374. AssertOutput(delegate() {
  375. CompilerTest(@"
  376. begin
  377. raise IOError
  378. rescue IOError
  379. puts 'rescued'
  380. end
  381. ");
  382. }, "rescued");
  383. }
  384. public void Scenario_RubyExceptions15() {
  385. AssertOutput(delegate() {
  386. CompilerTest(@"
  387. class C
  388. def exception
  389. IOError.new
  390. end
  391. end
  392. begin
  393. raise C.new
  394. rescue IOError
  395. puts 'rescued'
  396. end
  397. ");
  398. }, @"rescued");
  399. }
  400. public void Scenario_RubyExceptions16() {
  401. AssertOutput(delegate() {
  402. CompilerTest(@"
  403. begin
  404. raise Exception.new('foo')
  405. rescue Exception => e
  406. puts e.message
  407. end
  408. ");
  409. }, @"foo");
  410. }
  411. public void JumpFromEnsure1() {
  412. AssertOutput(delegate() {
  413. CompilerTest(@"
  414. def foo
  415. ensure
  416. return 1
  417. end
  418. p foo
  419. ");
  420. }, @"1");
  421. }
  422. public void Scenario_RubyExceptions_Globals() {
  423. AssertOutput(delegate() {
  424. CompilerTest(@"
  425. p $!
  426. p $@
  427. $! = Exception.new
  428. p $@ = nil
  429. p $@ = ['foo']
  430. p $@ = class A < Array; new; end
  431. p $@ = [class S < String; new; end]
  432. ");
  433. }, @"
  434. nil
  435. nil
  436. nil
  437. [""foo""]
  438. []
  439. [""""]
  440. ");
  441. // $! must be non-null when assigning to $@
  442. AssertExceptionThrown<ArgumentException>(delegate() {
  443. CompilerTest(@"$! = nil; $@ = ['foo']");
  444. });
  445. // $! non-nullity checked before type of backtracce:
  446. AssertExceptionThrown<ArgumentException>(delegate() {
  447. CompilerTest(@"$! = nil; $@ = 1");
  448. });
  449. // backtrace needs to be an array
  450. AssertExceptionThrown<InvalidOperationException>(delegate() {
  451. CompilerTest(@"$! = Exception.new; $@ = 1");
  452. });
  453. // backtrace needs to be an array of strings
  454. AssertExceptionThrown<InvalidOperationException>(delegate() {
  455. CompilerTest(@"$! = Exception.new; $@ = ['foo', 1]");
  456. });
  457. // backtrace needs to be an array, no conversion take place:
  458. AssertExceptionThrown<InvalidOperationException>(delegate() {
  459. CompilerTest(@"
  460. $! = Exception.new
  461. class B; def to_ary; []; end; end
  462. $@ = B.new
  463. ");
  464. });
  465. // backtrace needs to be an array of strings, no item conversion take place:
  466. AssertExceptionThrown<InvalidOperationException>(delegate() {
  467. CompilerTest(@"
  468. $! = Exception.new
  469. class T; def to_str; ''; end; end
  470. $@ = [T.new]
  471. ");
  472. });
  473. }
  474. public void Scenario_RubyRescueStatement1() {
  475. AssertOutput(delegate() {
  476. CompilerTest(@"
  477. def foo
  478. raise IOError.new('1')
  479. end
  480. foo rescue puts $!
  481. puts '1' rescue puts '2'
  482. ");
  483. }, @"
  484. 1
  485. 1");
  486. }
  487. public void Scenario_RubyRescueExpression1() {
  488. AssertOutput(delegate() {
  489. CompilerTest(@"
  490. def foo
  491. raise
  492. end
  493. x = foo rescue 2
  494. puts x
  495. ");
  496. }, @"2");
  497. }
  498. public void Scenario_RubyRescueExpression2() {
  499. TestOutput(@"
  500. def foo
  501. raise
  502. end
  503. def bar
  504. x = foo rescue return
  505. puts 'unreachable'
  506. end
  507. def baz
  508. foo rescue return
  509. puts 'unreachable'
  510. end
  511. def bazz
  512. foo rescue return 2
  513. puts 'unreachable'
  514. end
  515. bar
  516. baz
  517. bazz
  518. ", @"");
  519. }
  520. public void ExceptionArg1() {
  521. AssertOutput(delegate() {
  522. CompilerTest(@"
  523. begin
  524. raise SystemExit, 42
  525. rescue SystemExit
  526. puts $!.status
  527. end
  528. ");
  529. }, @"42");
  530. }
  531. public void ExceptionArg2() {
  532. AssertOutput(delegate() {
  533. CompilerTest(@"
  534. begin
  535. raise SystemExit, 'foo'
  536. rescue SystemExit
  537. puts $!.message
  538. end
  539. ");
  540. }, @"foo");
  541. }
  542. public void RescueSplat1() {
  543. AssertOutput(delegate() {
  544. CompilerTest(@"
  545. begin
  546. raise IOError
  547. rescue *[IOError]
  548. puts 'ok'
  549. end
  550. ");
  551. }, @"ok");
  552. }
  553. public void RescueSplat2() {
  554. AssertOutput(delegate() {
  555. CompilerTest(@"
  556. begin
  557. raise IOError
  558. rescue SyntaxError, *[SyntaxError, SyntaxError, IOError, nil]
  559. puts 'ok'
  560. end
  561. ");
  562. }, @"ok");
  563. }
  564. public void RescueSplat3() {
  565. TestOutput(@"
  566. class C
  567. def respond_to? name
  568. puts '?' + name.to_s
  569. false
  570. end
  571. def to_ary
  572. puts 'to_ary'
  573. [Exception]
  574. end
  575. def to_a
  576. puts 'to_a'
  577. [SyntaxError, IOError]
  578. end
  579. end
  580. begin
  581. begin
  582. raise IOError
  583. rescue *C.new
  584. puts :a
  585. end
  586. rescue
  587. puts :b
  588. end
  589. ", @"
  590. ?to_a
  591. b
  592. ");
  593. }
  594. public void RescueSplat4() {
  595. TestOutput(@"
  596. class C
  597. def respond_to? name
  598. puts '?' + name.to_s
  599. true
  600. end
  601. def to_a
  602. puts 'to_a'
  603. 1
  604. end
  605. end
  606. begin
  607. begin
  608. raise IOError
  609. rescue *C.new
  610. puts 'ok'
  611. end
  612. rescue
  613. p $!
  614. end
  615. ", @"
  616. ?to_a
  617. to_a
  618. #<TypeError: C#to_a should return Array>
  619. ");
  620. }
  621. public void RescueSplat5() {
  622. TestOutput(@"
  623. class E < Exception
  624. end
  625. class C
  626. def ===(other)
  627. puts ""===#{other}""
  628. 0
  629. end
  630. end
  631. def foo(i)
  632. puts ""foo(#{i})""
  633. end
  634. a = []
  635. b = [1,2,3]
  636. c = 1
  637. begin
  638. raise E.new
  639. rescue *a,*b,*[foo(0), C.new],foo(1),C.new,2 => x
  640. p x
  641. end
  642. ", @"
  643. foo(0)
  644. foo(1)
  645. ===E
  646. #<E: E>
  647. ");
  648. }
  649. public void ExceptionMapping1() {
  650. TestOutput(@"
  651. class LoadError
  652. def self.new message
  653. ZeroDivisionError.new message
  654. end
  655. end
  656. class SecurityError # partial trust: current directory detection
  657. def self.new message
  658. ZeroDivisionError.new message
  659. end
  660. end
  661. begin
  662. require 'non-existent'
  663. rescue ZeroDivisionError
  664. puts 'Caught ZeroDivisionError'
  665. end
  666. ", @"
  667. Caught ZeroDivisionError
  668. ");
  669. }
  670. public void ExceptionMapping2() {
  671. TestOutput(@"
  672. class ZeroDivisionError
  673. def self.new(message)
  674. puts 'new ZeroDivError'
  675. 'not an exception'
  676. end
  677. end
  678. module Any
  679. def self.===(other)
  680. puts ""?#{other.inspect}""
  681. true
  682. end
  683. end
  684. begin
  685. 1/0
  686. rescue Any
  687. puts 'rescue'
  688. p $!
  689. end
  690. puts 'Done'
  691. ", @"
  692. new ZeroDivError
  693. ?#<TypeError: exception object expected>
  694. rescue
  695. #<TypeError: exception object expected>
  696. Done
  697. ");
  698. }
  699. public void ExceptionMapping3() {
  700. TestOutput(@"
  701. class LoadError
  702. def initialize *args
  703. puts 'initLE'
  704. end
  705. end
  706. class SecurityError
  707. def initialize *args
  708. puts 'initSE'
  709. end
  710. end
  711. begin
  712. require 'non-existent'
  713. rescue SecurityError
  714. puts 'Caught SecurityError' # partial trust: current directory detection
  715. rescue LoadError
  716. puts 'Caught LoadError'
  717. end
  718. ", _driver.PartialTrust ? @"
  719. initSE
  720. Caught SecurityError
  721. " : @"
  722. initLE
  723. Caught LoadError
  724. ");
  725. }
  726. }
  727. }