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