diff options
author | Benoit Daloze <eregontp@gmail.com> | 2019-11-30 21:26:52 +0100 |
---|---|---|
committer | Benoit Daloze <eregontp@gmail.com> | 2019-11-30 21:26:52 +0100 |
commit | 1243255c3a36433041012b6107a5ac48658a0895 (patch) | |
tree | 04440f84b48999ff08d4a2a16d066d0ad731400e /spec/ruby/core/exception | |
parent | ab8345271eb87ff155d8bd5f22f53a4cf2902c26 (diff) |
Update to ruby/spec@4eec3dc
Diffstat (limited to 'spec/ruby/core/exception')
19 files changed, 343 insertions, 154 deletions
diff --git a/spec/ruby/core/exception/args_spec.rb b/spec/ruby/core/exception/args_spec.rb deleted file mode 100644 index 005c2dd198..0000000000 --- a/spec/ruby/core/exception/args_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require_relative '../../spec_helper' - -describe "NoMethodError#args" do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/core/exception/arguments_spec.rb b/spec/ruby/core/exception/arguments_spec.rb deleted file mode 100644 index 0b283e9a54..0000000000 --- a/spec/ruby/core/exception/arguments_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require_relative '../../spec_helper' - -describe "ArgumentError" do - it "is a subclass of StandardError" do - StandardError.should be_ancestor_of(ArgumentError) - end - - it "gives its own class name as message if it has no message" do - ArgumentError.new.message.should == "ArgumentError" - end -end diff --git a/spec/ruby/core/exception/backtrace_spec.rb b/spec/ruby/core/exception/backtrace_spec.rb index 5e140f8d9b..2d6825180a 100644 --- a/spec/ruby/core/exception/backtrace_spec.rb +++ b/spec/ruby/core/exception/backtrace_spec.rb @@ -47,7 +47,7 @@ describe "Exception#backtrace" do end end - it "produces a backtrace for an exception captured using $!" do + it "captures the backtrace for an exception into $!" do exception = begin raise rescue RuntimeError @@ -57,6 +57,16 @@ describe "Exception#backtrace" do exception.backtrace.first.should =~ /backtrace_spec/ end + it "captures the backtrace for an exception into $@" do + backtrace = begin + raise + rescue RuntimeError + $@ + end + + backtrace.first.should =~ /backtrace_spec/ + end + it "returns an Array that can be updated" do begin raise diff --git a/spec/ruby/core/exception/case_compare_spec.rb b/spec/ruby/core/exception/case_compare_spec.rb index a4c9eaa6bf..87b9dee3ca 100644 --- a/spec/ruby/core/exception/case_compare_spec.rb +++ b/spec/ruby/core/exception/case_compare_spec.rb @@ -1,5 +1,39 @@ require_relative '../../spec_helper' describe "SystemCallError.===" do - it "needs to be reviewed for spec completeness" + before :all do + @example_errno_class = Errno::EINVAL + @example_errno = @example_errno_class::Errno + end + + it "returns true for an instance of the same class" do + Errno::EINVAL.should === Errno::EINVAL.new + end + + it "returns true if errnos same" do + e = SystemCallError.new('foo', @example_errno) + @example_errno_class.===(e).should == true + end + + it "returns false if errnos different" do + e = SystemCallError.new('foo', @example_errno + 1) + @example_errno_class.===(e).should == false + end + + it "returns false if arg is not kind of SystemCallError" do + e = Object.new + @example_errno_class.===(e).should == false + end + + it "returns true if receiver is generic and arg is kind of SystemCallError" do + unknown_error_number = Errno.constants.size + e = SystemCallError.new('foo', @example_errno) + SystemCallError.===(e).should == true + end + + it "returns false if receiver is generic and arg is not kind of SystemCallError" do + unknown_error_number = Errno.constants.size + e = Object.new + SystemCallError.===(e).should == false + end end diff --git a/spec/ruby/core/exception/destination_encoding_name_spec.rb b/spec/ruby/core/exception/destination_encoding_name_spec.rb index b6ffff8c9c..a9e6474974 100644 --- a/spec/ruby/core/exception/destination_encoding_name_spec.rb +++ b/spec/ruby/core/exception/destination_encoding_name_spec.rb @@ -1,9 +1,23 @@ require_relative '../../spec_helper' describe "Encoding::UndefinedConversionError#destination_encoding_name" do - it "needs to be reviewed for spec completeness" + it "returns the destination encoding name" do + ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") + begin + ec.convert("\xa0") + rescue Encoding::UndefinedConversionError => e + e.destination_encoding_name.should == "EUC-JP" + end + end end describe "Encoding::InvalidByteSequenceError#destination_encoding_name" do - it "needs to be reviewed for spec completeness" + it "returns the destination encoding name" do + ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") + begin + ec.convert("\xa0") + rescue Encoding::InvalidByteSequenceError => e + e.destination_encoding_name.should == "UTF-8" + end + end end diff --git a/spec/ruby/core/exception/destination_encoding_spec.rb b/spec/ruby/core/exception/destination_encoding_spec.rb index c3ad0342a1..5709c31e55 100644 --- a/spec/ruby/core/exception/destination_encoding_spec.rb +++ b/spec/ruby/core/exception/destination_encoding_spec.rb @@ -1,9 +1,23 @@ require_relative '../../spec_helper' describe "Encoding::UndefinedConversionError#destination_encoding" do - it "needs to be reviewed for spec completeness" + it "returns the destination encoding" do + ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") + begin + ec.convert("\xa0") + rescue Encoding::UndefinedConversionError => e + e.destination_encoding.should == Encoding::EUC_JP + end + end end describe "Encoding::InvalidByteSequenceError#destination_encoding" do - it "needs to be reviewed for spec completeness" + it "returns the destination encoding" do + ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") + begin + ec.convert("\xa0") + rescue Encoding::InvalidByteSequenceError => e + e.destination_encoding.should == Encoding::UTF_8 + end + end end diff --git a/spec/ruby/core/exception/error_bytes_spec.rb b/spec/ruby/core/exception/error_bytes_spec.rb index 2a95bcfdf4..66dd4b62c1 100644 --- a/spec/ruby/core/exception/error_bytes_spec.rb +++ b/spec/ruby/core/exception/error_bytes_spec.rb @@ -1,5 +1,12 @@ require_relative '../../spec_helper' describe "Encoding::InvalidByteSequenceError#error_bytes" do - it "needs to be reviewed for spec completeness" + it "returns the error bytes" do + ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") + begin + ec.convert("\xa0") + rescue Encoding::InvalidByteSequenceError => e + e.error_bytes.should == "\xA0".force_encoding("ASCII-8BIT") + end + end end diff --git a/spec/ruby/core/exception/error_char_spec.rb b/spec/ruby/core/exception/error_char_spec.rb index c0256af03a..f95ae2a6ce 100644 --- a/spec/ruby/core/exception/error_char_spec.rb +++ b/spec/ruby/core/exception/error_char_spec.rb @@ -1,5 +1,12 @@ require_relative '../../spec_helper' describe "Encoding::UndefinedConversionError#error_char" do - it "needs to be reviewed for spec completeness" + it "returns the error char" do + ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") + begin + ec.convert("\xa0") + rescue Encoding::UndefinedConversionError => e + e.error_char.should == "\u00A0" + end + end end diff --git a/spec/ruby/core/exception/exception_spec.rb b/spec/ruby/core/exception/exception_spec.rb index 3a01366920..d6f5283bd9 100644 --- a/spec/ruby/core/exception/exception_spec.rb +++ b/spec/ruby/core/exception/exception_spec.rb @@ -6,48 +6,6 @@ describe "Exception.exception" do it_behaves_like :exception_new, :exception end -describe "Exception" do - it "is a Class" do - Exception.should be_kind_of(Class) - end - - it "is a superclass of NoMemoryError" do - Exception.should be_ancestor_of(NoMemoryError) - end - - it "is a superclass of ScriptError" do - Exception.should be_ancestor_of(ScriptError) - end - - it "is a superclass of SignalException" do - Exception.should be_ancestor_of(SignalException) - end - - it "is a superclass of Interrupt" do - SignalException.should be_ancestor_of(Interrupt) - end - - it "is a superclass of StandardError" do - Exception.should be_ancestor_of(StandardError) - end - - it "is a superclass of SystemExit" do - Exception.should be_ancestor_of(SystemExit) - end - - it "is a superclass of SystemStackError" do - Exception.should be_ancestor_of(SystemStackError) - end - - it "is a superclass of SecurityError" do - Exception.should be_ancestor_of(SecurityError) - end - - it "is a superclass of EncodingError" do - Exception.should be_ancestor_of(EncodingError) - end -end - describe "Exception#exception" do it "returns self when passed no argument" do e = RuntimeError.new @@ -82,6 +40,18 @@ describe "Exception#exception" do raised_second.should == caught_second end + it "captures an exception into $!" do + exception = begin + raise + rescue RuntimeError + $! + end + + exception.class.should == RuntimeError + exception.message.should == "" + exception.backtrace.first.should =~ /exception_spec/ + end + class CustomArgumentError < StandardError attr_reader :val def initialize(val) diff --git a/spec/ruby/core/exception/hierarchy_spec.rb b/spec/ruby/core/exception/hierarchy_spec.rb new file mode 100644 index 0000000000..e52811c761 --- /dev/null +++ b/spec/ruby/core/exception/hierarchy_spec.rb @@ -0,0 +1,62 @@ +require_relative '../../spec_helper' + +describe "Exception" do + it "has the right class hierarchy" do + hierarchy = { + Exception => { + NoMemoryError => nil, + ScriptError => { + LoadError => nil, + NotImplementedError => nil, + SyntaxError => nil, + }, + SecurityError => nil, + SignalException => { + Interrupt => nil, + }, + StandardError => { + ArgumentError => { + UncaughtThrowError => nil, + }, + EncodingError => nil, + FiberError => nil, + IOError => { + EOFError => nil, + }, + IndexError => { + KeyError => nil, + StopIteration => { + ClosedQueueError => nil, + }, + }, + LocalJumpError => nil, + NameError => { + NoMethodError => nil, + }, + RangeError => { + FloatDomainError => nil, + }, + RegexpError => nil, + RuntimeError => nil, + SystemCallError => nil, + ThreadError => nil, + TypeError => nil, + ZeroDivisionError => nil, + }, + SystemExit => nil, + SystemStackError => nil, + }, + } + ruby_version_is "2.5" do + hierarchy[Exception][StandardError][RuntimeError] = {FrozenError => nil} + end + traverse = -> parent_class, parent_subclass_hash { + parent_subclass_hash.each do |child_class, child_subclass_hash| + child_class.class.should == Class + child_class.superclass.should == parent_class + traverse.call(child_class, child_subclass_hash) if child_subclass_hash + end + } + traverse.call(Object, hierarchy) + end +end diff --git a/spec/ruby/core/exception/interrupt_spec.rb b/spec/ruby/core/exception/interrupt_spec.rb index bc01b7b703..14f294bec6 100644 --- a/spec/ruby/core/exception/interrupt_spec.rb +++ b/spec/ruby/core/exception/interrupt_spec.rb @@ -1,11 +1,5 @@ require_relative '../../spec_helper' -describe "Interrupt" do - it "is a subclass of SignalException" do - Interrupt.superclass.should == SignalException - end -end - describe "Interrupt.new" do it "returns an instance of interrupt with no message given" do e = Interrupt.new diff --git a/spec/ruby/core/exception/readagain_bytes_spec.rb b/spec/ruby/core/exception/readagain_bytes_spec.rb index f7e8d9d1d3..0f1e24f1cf 100644 --- a/spec/ruby/core/exception/readagain_bytes_spec.rb +++ b/spec/ruby/core/exception/readagain_bytes_spec.rb @@ -1,5 +1,12 @@ require_relative '../../spec_helper' describe "Encoding::InvalidByteSequenceError#readagain_bytes" do - it "needs to be reviewed for spec completeness" + it "returns the next byte" do + begin + "abc\xa4def".encode("ISO-8859-1", "EUC-JP") + rescue Encoding::InvalidByteSequenceError => e + e.error_bytes.should == "\xA4".force_encoding("ASCII-8BIT") + e.readagain_bytes.should == 'd' + end + end end diff --git a/spec/ruby/core/exception/script_error_spec.rb b/spec/ruby/core/exception/script_error_spec.rb deleted file mode 100644 index e33a5d3a58..0000000000 --- a/spec/ruby/core/exception/script_error_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require_relative '../../spec_helper' - -describe "ScriptError" do - it "is a superclass of LoadError" do - ScriptError.should be_ancestor_of(LoadError) - end - - it "is a superclass of NotImplementedError" do - ScriptError.should be_ancestor_of(NotImplementedError) - end - - it "is a superclass of SyntaxError" do - ScriptError.should be_ancestor_of(SyntaxError) - end -end diff --git a/spec/ruby/core/exception/signal_exception_spec.rb b/spec/ruby/core/exception/signal_exception_spec.rb index e0b30236f7..e494e18cde 100644 --- a/spec/ruby/core/exception/signal_exception_spec.rb +++ b/spec/ruby/core/exception/signal_exception_spec.rb @@ -30,6 +30,12 @@ describe "SignalException.new" do -> { SignalException.new("NONEXISTENT") }.should raise_error(ArgumentError) end + ruby_version_is "2.6" do + it "raises an exception with an invalid first argument type" do + -> { SignalException.new(Object.new) }.should raise_error(ArgumentError) + end + end + it "takes a signal symbol without SIG prefix as the first argument" do exc = SignalException.new(:INT) exc.signo.should == Signal.list["INT"] @@ -72,3 +78,48 @@ describe "rescuing SignalException" do end end end + +describe "SignalException" do + it "can be rescued" do + ruby_exe(<<-RUBY) + begin + raise SignalException, 'SIGKILL' + rescue SignalException + exit(0) + end + exit(1) + RUBY + + $?.exitstatus.should == 0 + end + + platform_is_not :windows do + it "runs after at_exit" do + output = ruby_exe(<<-RUBY) + at_exit do + puts "hello" + $stdout.flush + end + + raise SignalException, 'SIGKILL' + RUBY + + $?.termsig.should == Signal.list.fetch("KILL") + output.should == "hello\n" + end + + it "cannot be trapped with Signal.trap" do + ruby_exe(<<-RUBY) + Signal.trap("PROF") {} + raise(SignalException, "PROF") + RUBY + + $?.termsig.should == Signal.list.fetch("PROF") + end + + it "self-signals for USR1" do + ruby_exe("raise(SignalException, 'USR1')") + $?.termsig.should == Signal.list.fetch('USR1') + end + end +end diff --git a/spec/ruby/core/exception/source_encoding_name_spec.rb b/spec/ruby/core/exception/source_encoding_name_spec.rb index bd8bc359b6..6f5dbd01aa 100644 --- a/spec/ruby/core/exception/source_encoding_name_spec.rb +++ b/spec/ruby/core/exception/source_encoding_name_spec.rb @@ -1,9 +1,23 @@ require_relative '../../spec_helper' describe "Encoding::UndefinedConversionError#source_encoding_name" do - it "needs to be reviewed for spec completeness" + it "returns the source encoding name" do + ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") + begin + ec.convert("\xa0") + rescue Encoding::UndefinedConversionError => e + e.source_encoding_name.should == "UTF-8" + end + end end describe "Encoding::InvalidByteSequenceError#source_encoding_name" do - it "needs to be reviewed for spec completeness" + it "returns the source encoding name" do + ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") + begin + ec.convert("\xa0") + rescue Encoding::InvalidByteSequenceError => e + e.source_encoding_name.should == "EUC-JP" + end + end end diff --git a/spec/ruby/core/exception/source_encoding_spec.rb b/spec/ruby/core/exception/source_encoding_spec.rb index 65ac98d791..fac38e75f4 100644 --- a/spec/ruby/core/exception/source_encoding_spec.rb +++ b/spec/ruby/core/exception/source_encoding_spec.rb @@ -1,9 +1,23 @@ require_relative '../../spec_helper' describe "Encoding::UndefinedConversionError#source_encoding" do - it "needs to be reviewed for spec completeness" + it "returns the source encoding" do + ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") + begin + ec.convert("\xa0") + rescue Encoding::UndefinedConversionError => e + e.source_encoding.should == Encoding::UTF_8 + end + end end describe "Encoding::InvalidByteSequenceError#source_encoding" do - it "needs to be reviewed for spec completeness" + it "returns the source encoding" do + ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") + begin + ec.convert("\xa0") + rescue Encoding::InvalidByteSequenceError => e + e.source_encoding.should == Encoding::EUC_JP + end + end end diff --git a/spec/ruby/core/exception/standard_error_spec.rb b/spec/ruby/core/exception/standard_error_spec.rb index 1b469b5090..17e98ce7f0 100644 --- a/spec/ruby/core/exception/standard_error_spec.rb +++ b/spec/ruby/core/exception/standard_error_spec.rb @@ -1,56 +1,23 @@ require_relative '../../spec_helper' describe "StandardError" do - it "is a superclass of ArgumentError" do - StandardError.should be_ancestor_of(ArgumentError) - end - - it "is a superclass of IOError" do - StandardError.should be_ancestor_of(IOError) - end - - it "is a superclass of IndexError" do - StandardError.should be_ancestor_of(IndexError) - end - - it "is a superclass of LocalJumpError" do - StandardError.should be_ancestor_of(LocalJumpError) - end - - it "is a superclass of NameError" do - StandardError.should be_ancestor_of(NameError) - end - - it "is a superclass of RangeError" do - StandardError.should be_ancestor_of(RangeError) - end - - it "is a superclass of RegexpError" do - StandardError.should be_ancestor_of(RegexpError) - end - - it "is a superclass of RuntimeError" do - StandardError.should be_ancestor_of(RuntimeError) - end - - it "is a superclass of SystemCallError" do - StandardError.should be_ancestor_of(SystemCallError.new("").class) - end - it "is a superclass of ThreadError" do - StandardError.should be_ancestor_of(ThreadError) - end - - it "is a superclass of TypeError" do - StandardError.should be_ancestor_of(TypeError) + it "rescues StandardError" do + begin + raise StandardError + rescue => exception + exception.class.should == StandardError + end end - it "is a superclass of ZeroDivisionError" do - StandardError.should be_ancestor_of(ZeroDivisionError) + it "rescues subclass of StandardError" do + begin + raise RuntimeError + rescue => exception + exception.class.should == RuntimeError + end end - ruby_version_is '2.5' do - it "is a superclass of FrozenError" do - StandardError.should be_ancestor_of(FrozenError) - end + it "does not rescue superclass of StandardError" do + -> { begin; raise Exception; rescue; end }.should raise_error(Exception) end end diff --git a/spec/ruby/core/exception/system_call_error_spec.rb b/spec/ruby/core/exception/system_call_error_spec.rb index c07c8af72c..c510ae440f 100644 --- a/spec/ruby/core/exception/system_call_error_spec.rb +++ b/spec/ruby/core/exception/system_call_error_spec.rb @@ -20,41 +20,82 @@ describe "SystemCallError" do end describe "SystemCallError.new" do + before :all do + @example_errno = Errno::EINVAL::Errno + @example_errno_class = Errno::EINVAL + @last_known_errno = Errno.constants.size - 1 + @unknown_errno = Errno.constants.size + end + it "requires at least one argument" do -> { SystemCallError.new }.should raise_error(ArgumentError) end it "accepts single Fixnum argument as errno" do SystemCallError.new(-2**24).errno.should == -2**24 - SystemCallError.new(42).errno.should == 42 + SystemCallError.new(-1).errno.should == -1 + SystemCallError.new(0).errno.should == 0 + SystemCallError.new(@last_known_errno).errno.should == @last_known_errno + SystemCallError.new(@unknown_errno).errno.should == @unknown_errno SystemCallError.new(2**24).errno.should == 2**24 end + it "constructs a SystemCallError for an unknown error number" do + SystemCallError.new(-2**24).should be_an_instance_of(SystemCallError) + SystemCallError.new(-1).should be_an_instance_of(SystemCallError) + SystemCallError.new(@unknown_errno).should be_an_instance_of(SystemCallError) + SystemCallError.new(2**24).should be_an_instance_of(SystemCallError) + end + it "constructs the appropriate Errno class" do - # EINVAL should be more or less mortable across the platforms, - # so let's use it then. - SystemCallError.new(22).should be_kind_of(SystemCallError) - SystemCallError.new(22).should be_an_instance_of(Errno::EINVAL) - SystemCallError.new(2**28).should be_an_instance_of(SystemCallError) + e = SystemCallError.new(@example_errno) + e.should be_kind_of(SystemCallError) + e.should be_an_instance_of(@example_errno_class) end it "accepts an optional custom message preceding the errno" do - exc = SystemCallError.new("custom message", 22) - exc.should be_an_instance_of(Errno::EINVAL) - exc.errno.should == 22 - exc.message.should == "Invalid argument - custom message" + exc = SystemCallError.new("custom message", @example_errno) + exc.should be_an_instance_of(@example_errno_class) + exc.errno.should == @example_errno + exc.message.should == 'Invalid argument - custom message' end it "accepts an optional third argument specifying the location" do - exc = SystemCallError.new("custom message", 22, "location") - exc.should be_an_instance_of(Errno::EINVAL) - exc.errno.should == 22 - exc.message.should == "Invalid argument @ location - custom message" + exc = SystemCallError.new("custom message", @example_errno, "location") + exc.should be_an_instance_of(@example_errno_class) + exc.errno.should == @example_errno + exc.message.should == 'Invalid argument @ location - custom message' + end + + it "coerces location if it is not a String" do + e = SystemCallError.new('foo', 1, :not_a_string) + e.message.should =~ /@ not_a_string - foo/ end it "returns an arity of -1 for the initialize method" do SystemCallError.instance_method(:initialize).arity.should == -1 end + + it "converts to Integer if errno is a Float" do + SystemCallError.new('foo', 2.0).should == SystemCallError.new('foo', 2) + SystemCallError.new('foo', 2.9).should == SystemCallError.new('foo', 2) + end + + it "converts to Integer if errno is a Complex convertible to Integer" do + SystemCallError.new('foo', Complex(2.9, 0)).should == SystemCallError.new('foo', 2) + end + + it "raises TypeError if message is not a String" do + -> { SystemCallError.new(:foo, 1) }.should raise_error(TypeError, /no implicit conversion of Symbol into String/) + end + + it "raises TypeError if errno is not an Integer" do + -> { SystemCallError.new('foo', 'bar') }.should raise_error(TypeError, /no implicit conversion of String into Integer/) + end + + it "raises RangeError if errno is a Complex not convertible to Integer" do + -> { SystemCallError.new('foo', Complex(2.9, 1)) }.should raise_error(RangeError, /can't convert/) + end end describe "SystemCallError#errno" do diff --git a/spec/ruby/core/exception/to_s_spec.rb b/spec/ruby/core/exception/to_s_spec.rb index 8570b18cfd..4c4c7ab432 100644 --- a/spec/ruby/core/exception/to_s_spec.rb +++ b/spec/ruby/core/exception/to_s_spec.rb @@ -19,5 +19,19 @@ describe "Exception#to_s" do end describe "NameError#to_s" do - it "needs to be reviewed for spec completeness" + it "raises its own message for an undefined variable" do + begin + puts not_defined + rescue => exception + exception.message.should =~ /undefined local variable or method `not_defined'/ + end + end + + it "raises its own message for an undefined constant" do + begin + puts NotDefined + rescue => exception + exception.message.should =~ /uninitialized constant NotDefined/ + end + end end |