diff options
Diffstat (limited to 'spec/ruby/core/exception')
45 files changed, 1207 insertions, 0 deletions
diff --git a/spec/ruby/core/exception/args_spec.rb b/spec/ruby/core/exception/args_spec.rb new file mode 100644 index 0000000000..410e21edfb --- /dev/null +++ b/spec/ruby/core/exception/args_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +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 new file mode 100644 index 0000000000..47c4339e2d --- /dev/null +++ b/spec/ruby/core/exception/arguments_spec.rb @@ -0,0 +1,11 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +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 new file mode 100644 index 0000000000..2d115e9b2f --- /dev/null +++ b/spec/ruby/core/exception/backtrace_spec.rb @@ -0,0 +1,68 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "Exception#backtrace" do + before :each do + @backtrace = ExceptionSpecs::Backtrace.backtrace + end + + it "returns nil if no backtrace was set" do + Exception.new.backtrace.should be_nil + end + + it "returns an Array" do + @backtrace.should be_an_instance_of(Array) + end + + it "sets each element to a String" do + @backtrace.each {|l| l.should be_an_instance_of(String)} + end + + it "includes the filename of the location where self raised in the first element" do + @backtrace.first.should =~ /common\.rb/ + end + + it "includes the line number of the location where self raised in the first element" do + @backtrace.first.should =~ /:7:in / + end + + it "includes the name of the method from where self raised in the first element" do + @backtrace.first.should =~ /in `backtrace'/ + end + + it "includes the filename of the location immediately prior to where self raised in the second element" do + @backtrace[1].should =~ /backtrace_spec\.rb/ + end + + it "includes the line number of the location immediately prior to where self raised in the second element" do + @backtrace[1].should =~ /:6(:in )?/ + end + + it "contains lines of the same format for each prior position in the stack" do + @backtrace[2..-1].each do |line| + # This regexp is deliberately imprecise to account for the need to abstract out + # the paths of the included mspec files and the desire to avoid specifying in any + # detail what the in `...' portion looks like. + line.should =~ /^[^ ]+\:\d+(:in `[^`]+')?$/ + end + end + + it "produces a backtrace for an exception captured using $!" do + exception = begin + raise + rescue RuntimeError + $! + end + + exception.backtrace.first.should =~ /backtrace_spec/ + end + + it "returns an Array that can be updated" do + begin + raise + rescue RuntimeError => e + e.backtrace.unshift "backtrace first" + e.backtrace[0].should == "backtrace first" + end + end +end diff --git a/spec/ruby/core/exception/case_compare_spec.rb b/spec/ruby/core/exception/case_compare_spec.rb new file mode 100644 index 0000000000..7592564855 --- /dev/null +++ b/spec/ruby/core/exception/case_compare_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "SystemCallError.===" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/cause_spec.rb b/spec/ruby/core/exception/cause_spec.rb new file mode 100644 index 0000000000..a1aa39ae34 --- /dev/null +++ b/spec/ruby/core/exception/cause_spec.rb @@ -0,0 +1,19 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Exception#cause" do + it "returns the active exception when an exception is raised" do + begin + raise Exception, "the cause" + rescue Exception + begin + raise RuntimeError, "the consequence" + rescue RuntimeError => e + e.should be_an_instance_of(RuntimeError) + e.message.should == "the consequence" + + e.cause.should be_an_instance_of(Exception) + e.cause.message.should == "the cause" + end + end + end +end diff --git a/spec/ruby/core/exception/destination_encoding_name_spec.rb b/spec/ruby/core/exception/destination_encoding_name_spec.rb new file mode 100644 index 0000000000..d6a01c3220 --- /dev/null +++ b/spec/ruby/core/exception/destination_encoding_name_spec.rb @@ -0,0 +1,9 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::UndefinedConversionError#destination_encoding_name" do + it "needs to be reviewed for spec completeness" +end + +describe "Encoding::InvalidByteSequenceError#destination_encoding_name" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/destination_encoding_spec.rb b/spec/ruby/core/exception/destination_encoding_spec.rb new file mode 100644 index 0000000000..09064a01f3 --- /dev/null +++ b/spec/ruby/core/exception/destination_encoding_spec.rb @@ -0,0 +1,9 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::UndefinedConversionError#destination_encoding" do + it "needs to be reviewed for spec completeness" +end + +describe "Encoding::InvalidByteSequenceError#destination_encoding" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/equal_value_spec.rb b/spec/ruby/core/exception/equal_value_spec.rb new file mode 100644 index 0000000000..3aad809377 --- /dev/null +++ b/spec/ruby/core/exception/equal_value_spec.rb @@ -0,0 +1,68 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "Exception#==" do + it "returns true if both exceptions are the same object" do + e = ArgumentError.new + e.should == e + end + + it "returns true if one exception is the dup'd copy of the other" do + e = ArgumentError.new + e.should == e.dup + end + + it "returns true if both exceptions have the same class, no message, and no backtrace" do + RuntimeError.new.should == RuntimeError.new + end + + it "returns true if both exceptions have the same class, the same message, and no backtrace" do + TypeError.new("message").should == TypeError.new("message") + end + + it "returns true if both exceptions have the same class, the same message, and the same backtrace" do + one = TypeError.new("message") + one.set_backtrace [File.dirname(__FILE__)] + two = TypeError.new("message") + two.set_backtrace [File.dirname(__FILE__)] + one.should == two + end + + it "returns false if the two exceptions inherit from Exception but have different classes" do + one = RuntimeError.new("message") + one.set_backtrace [File.dirname(__FILE__)] + one.should be_kind_of(Exception) + two = TypeError.new("message") + two.set_backtrace [File.dirname(__FILE__)] + two.should be_kind_of(Exception) + one.should_not == two + end + + it "returns true if the two objects subclass Exception and have the same message and backtrace" do + one = ExceptionSpecs::UnExceptional.new + two = ExceptionSpecs::UnExceptional.new + one.message.should == two.message + two.backtrace.should == two.backtrace + one.should == two + end + + it "returns false if the argument is not an Exception" do + ArgumentError.new.should_not == String.new + end + + it "returns false if the two exceptions differ only in their backtrace" do + one = RuntimeError.new("message") + one.set_backtrace [File.dirname(__FILE__)] + two = RuntimeError.new("message") + two.set_backtrace nil + one.should_not == two + end + + it "returns false if the two exceptions differ only in their message" do + one = RuntimeError.new("message") + one.set_backtrace [File.dirname(__FILE__)] + two = RuntimeError.new("message2") + two.set_backtrace [File.dirname(__FILE__)] + one.should_not == two + end +end diff --git a/spec/ruby/core/exception/errno_spec.rb b/spec/ruby/core/exception/errno_spec.rb new file mode 100644 index 0000000000..f7f5b45d8a --- /dev/null +++ b/spec/ruby/core/exception/errno_spec.rb @@ -0,0 +1,48 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "SystemCallError#errno" do + it "needs to be reviewed for spec completeness" +end + +describe "Errno::EINVAL.new" do + it "can be called with no arguments" do + exc = Errno::EINVAL.new + exc.should be_an_instance_of(Errno::EINVAL) + exc.errno.should == Errno::EINVAL::Errno + exc.message.should == "Invalid argument" + end + + it "accepts an optional custom message" do + exc = Errno::EINVAL.new('custom message') + exc.should be_an_instance_of(Errno::EINVAL) + exc.errno.should == Errno::EINVAL::Errno + exc.message.should == "Invalid argument - custom message" + end + + it "accepts an optional custom message and location" do + exc = Errno::EINVAL.new('custom message', 'location') + exc.should be_an_instance_of(Errno::EINVAL) + exc.errno.should == Errno::EINVAL::Errno + exc.message.should == "Invalid argument @ location - custom message" + end +end + +describe "Errno::EMFILE" do + it "can be subclassed" do + ExceptionSpecs::EMFILESub = Class.new(Errno::EMFILE) + exc = ExceptionSpecs::EMFILESub.new + exc.should be_an_instance_of(ExceptionSpecs::EMFILESub) + end +end + +describe "Errno::EAGAIN" do + # From http://jira.codehaus.org/browse/JRUBY-4747 + it "is the same class as Errno::EWOULDBLOCK if they represent the same errno value" do + if Errno::EAGAIN::Errno == Errno::EWOULDBLOCK::Errno + Errno::EAGAIN.should == Errno::EWOULDBLOCK + else + Errno::EAGAIN.should_not == Errno::EWOULDBLOCK + end + end +end diff --git a/spec/ruby/core/exception/error_bytes_spec.rb b/spec/ruby/core/exception/error_bytes_spec.rb new file mode 100644 index 0000000000..e5027d0cf3 --- /dev/null +++ b/spec/ruby/core/exception/error_bytes_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::InvalidByteSequenceError#error_bytes" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/error_char_spec.rb b/spec/ruby/core/exception/error_char_spec.rb new file mode 100644 index 0000000000..8842424e90 --- /dev/null +++ b/spec/ruby/core/exception/error_char_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::UndefinedConversionError#error_char" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/exception_spec.rb b/spec/ruby/core/exception/exception_spec.rb new file mode 100644 index 0000000000..afa482b9d7 --- /dev/null +++ b/spec/ruby/core/exception/exception_spec.rb @@ -0,0 +1,83 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) +require File.expand_path('../shared/new', __FILE__) + +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 + e.should == e.exception + end + + it "returns self when passed self as an argument" do + e = RuntimeError.new + e.should == e.exception(e) + end + + it "returns an exception of the same class as self with the message given as argument" do + e = RuntimeError.new + e2 = e.exception("message") + e2.should be_an_instance_of(RuntimeError) + e2.message.should == "message" + end + + class CustomArgumentError < StandardError + attr_reader :val + def initialize(val) + @val = val + end + end + + it "returns an exception of the same class as self with the message given as argument, but without reinitializing" do + e = CustomArgumentError.new(:boom) + e2 = e.exception("message") + e2.should be_an_instance_of(CustomArgumentError) + e2.val.should == :boom + e2.message.should == "message" + end +end diff --git a/spec/ruby/core/exception/exit_value_spec.rb b/spec/ruby/core/exception/exit_value_spec.rb new file mode 100644 index 0000000000..daa5eb0b94 --- /dev/null +++ b/spec/ruby/core/exception/exit_value_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "LocalJumpError#exit_value" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/fixtures/common.rb b/spec/ruby/core/exception/fixtures/common.rb new file mode 100644 index 0000000000..51dd0bf9ed --- /dev/null +++ b/spec/ruby/core/exception/fixtures/common.rb @@ -0,0 +1,64 @@ +module ExceptionSpecs + class Exceptional < Exception; end + + class Backtrace + def self.backtrace + begin + raise # Do not move this line or update backtrace_spec.rb + rescue RuntimeError => e + e.backtrace + end + end + end + + class UnExceptional < Exception + def backtrace + nil + end + def message + nil + end + end + + class ConstructorException < Exception + + def initialize + end + + end + + class OverrideToS < RuntimeError + def to_s + "this is from #to_s" + end + end + + class EmptyToS < RuntimeError + def to_s + "" + end + end +end + +module NoMethodErrorSpecs + class NoMethodErrorA; end + + class NoMethodErrorB; end + + class NoMethodErrorC; + protected + def a_protected_method;end + private + def a_private_method; end + end + + class NoMethodErrorD; end +end + +class NameErrorSpecs + class ReceiverClass + def call_undefined_class_variable + @@doesnt_exist + end + end +end diff --git a/spec/ruby/core/exception/incomplete_input_spec.rb b/spec/ruby/core/exception/incomplete_input_spec.rb new file mode 100644 index 0000000000..a64d4be3f3 --- /dev/null +++ b/spec/ruby/core/exception/incomplete_input_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::InvalidByteSequenceError#incomplete_input?" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/initialize_spec.rb b/spec/ruby/core/exception/initialize_spec.rb new file mode 100644 index 0000000000..14fb93ef07 --- /dev/null +++ b/spec/ruby/core/exception/initialize_spec.rb @@ -0,0 +1 @@ +require File.expand_path('../../../spec_helper', __FILE__) diff --git a/spec/ruby/core/exception/inspect_spec.rb b/spec/ruby/core/exception/inspect_spec.rb new file mode 100644 index 0000000000..5b06ffee71 --- /dev/null +++ b/spec/ruby/core/exception/inspect_spec.rb @@ -0,0 +1,20 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "Exception#inspect" do + it "returns '#<Exception: Exception>' when no message given" do + Exception.new.inspect.should == "#<Exception: Exception>" + end + + it "includes #to_s when the result is non-empty" do + ExceptionSpecs::OverrideToS.new.inspect.should == "#<ExceptionSpecs::OverrideToS: this is from #to_s>" + end + + it "returns the class name when #to_s returns an empty string" do + ExceptionSpecs::EmptyToS.new.inspect.should == "ExceptionSpecs::EmptyToS" + end + + it "returns the derived class name with a subclassed Exception" do + ExceptionSpecs::UnExceptional.new.inspect.should == "#<ExceptionSpecs::UnExceptional: ExceptionSpecs::UnExceptional>" + end +end diff --git a/spec/ruby/core/exception/interrupt_spec.rb b/spec/ruby/core/exception/interrupt_spec.rb new file mode 100644 index 0000000000..ef24743936 --- /dev/null +++ b/spec/ruby/core/exception/interrupt_spec.rb @@ -0,0 +1,41 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +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 + e.signo.should == Signal.list["INT"] + e.signm.should == "Interrupt" + end + + it "takes an optional message argument" do + e = Interrupt.new("message") + e.signo.should == Signal.list["INT"] + e.signm.should == "message" + end +end + +describe "rescueing Interrupt" do + before do + @original_sigint_proc = Signal.trap(:INT, :SIG_DFL) + end + + after do + Signal.trap(:INT, @original_sigint_proc) + end + + it "raises an Interrupt when sent a signal SIGINT" do + begin + Process.kill :INT, Process.pid + sleep + rescue Interrupt => e + e.signo.should == Signal.list["INT"] + e.signm.should == "" + end + end +end diff --git a/spec/ruby/core/exception/io_error_spec.rb b/spec/ruby/core/exception/io_error_spec.rb new file mode 100644 index 0000000000..0971be332f --- /dev/null +++ b/spec/ruby/core/exception/io_error_spec.rb @@ -0,0 +1,51 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "IOError" do + it "is a superclass of EOFError" do + IOError.should be_ancestor_of(EOFError) + end +end + +describe "IO::EAGAINWaitReadable" do + it "combines Errno::EAGAIN and IO::WaitReadable" do + IO::EAGAINWaitReadable.superclass.should == Errno::EAGAIN + IO::EAGAINWaitReadable.ancestors.should include IO::WaitReadable + end + + it "is the same as IO::EWOULDBLOCKWaitReadable if Errno::EAGAIN is the same as Errno::EWOULDBLOCK" do + if Errno::EAGAIN.equal? Errno::EWOULDBLOCK + IO::EAGAINWaitReadable.should equal IO::EWOULDBLOCKWaitReadable + else + IO::EAGAINWaitReadable.should_not equal IO::EWOULDBLOCKWaitReadable + end + end +end + +describe "IO::EWOULDBLOCKWaitReadable" do + it "combines Errno::EWOULDBLOCK and IO::WaitReadable" do + IO::EWOULDBLOCKWaitReadable.superclass.should == Errno::EWOULDBLOCK + IO::EAGAINWaitReadable.ancestors.should include IO::WaitReadable + end +end + +describe "IO::EAGAINWaitWritable" do + it "combines Errno::EAGAIN and IO::WaitWritable" do + IO::EAGAINWaitWritable.superclass.should == Errno::EAGAIN + IO::EAGAINWaitWritable.ancestors.should include IO::WaitWritable + end + + it "is the same as IO::EWOULDBLOCKWaitWritable if Errno::EAGAIN is the same as Errno::EWOULDBLOCK" do + if Errno::EAGAIN.equal? Errno::EWOULDBLOCK + IO::EAGAINWaitWritable.should equal IO::EWOULDBLOCKWaitWritable + else + IO::EAGAINWaitWritable.should_not equal IO::EWOULDBLOCKWaitWritable + end + end +end + +describe "IO::EWOULDBLOCKWaitWritable" do + it "combines Errno::EWOULDBLOCK and IO::WaitWritable" do + IO::EWOULDBLOCKWaitWritable.superclass.should == Errno::EWOULDBLOCK + IO::EAGAINWaitWritable.ancestors.should include IO::WaitWritable + end +end diff --git a/spec/ruby/core/exception/load_error_spec.rb b/spec/ruby/core/exception/load_error_spec.rb new file mode 100644 index 0000000000..2999c66117 --- /dev/null +++ b/spec/ruby/core/exception/load_error_spec.rb @@ -0,0 +1,21 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "LoadError#path" do + before :each do + @le = LoadError.new + end + + it "is nil when constructed directly" do + @le.path.should == nil + end +end + +describe "LoadError raised by load or require" do + it "provides the failing path in its #path attribute" do + begin + require 'file_that_does_not_exist' + rescue LoadError => le + le.path.should == 'file_that_does_not_exist' + end + end +end diff --git a/spec/ruby/core/exception/message_spec.rb b/spec/ruby/core/exception/message_spec.rb new file mode 100644 index 0000000000..7eee6d99de --- /dev/null +++ b/spec/ruby/core/exception/message_spec.rb @@ -0,0 +1,27 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "Exception#message" do + it "returns the class name if there is no message" do + Exception.new.message.should == "Exception" + end + + it "returns the message passed to #initialize" do + Exception.new("Ouch!").message.should == "Ouch!" + end + + it "calls #to_s on self" do + exc = ExceptionSpecs::OverrideToS.new("you won't see this") + exc.message.should == "this is from #to_s" + end + + context "when #backtrace is redefined" do + it "returns the Exception message" do + e = Exception.new + e.message.should == 'Exception' + + def e.backtrace; []; end + e.message.should == 'Exception' + end + end +end diff --git a/spec/ruby/core/exception/name_error_spec.rb b/spec/ruby/core/exception/name_error_spec.rb new file mode 100644 index 0000000000..e5b19d6219 --- /dev/null +++ b/spec/ruby/core/exception/name_error_spec.rb @@ -0,0 +1,13 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "NameError" do + it "is a superclass of NoMethodError" do + NameError.should be_ancestor_of(NoMethodError) + end +end + +describe "NameError.new" do + it "should take optional name argument" do + NameError.new("msg","name").name.should == "name" + end +end diff --git a/spec/ruby/core/exception/name_spec.rb b/spec/ruby/core/exception/name_spec.rb new file mode 100644 index 0000000000..e8a3c011d2 --- /dev/null +++ b/spec/ruby/core/exception/name_spec.rb @@ -0,0 +1,61 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "NameError#name" do + it "returns a method name as a symbol" do + -> { + doesnt_exist + }.should raise_error(NameError) {|e| e.name.should == :doesnt_exist } + end + + it "returns a constant name as a symbol" do + -> { + DoesntExist + }.should raise_error(NameError) {|e| e.name.should == :DoesntExist } + end + + it "returns a constant name without namespace as a symbol" do + -> { + Object::DoesntExist + }.should raise_error(NameError) {|e| e.name.should == :DoesntExist } + end + + it "returns a class variable name as a symbol" do + -> { + -> { + @@doesnt_exist + }.should complain(/class variable access from toplevel/) + }.should raise_error(NameError) { |e| e.name.should == :@@doesnt_exist } + end + + ruby_version_is ""..."2.3" do + it "always returns a symbol when a NameError is raised from #instance_variable_get" do + -> { + Object.new.instance_variable_get("invalid_ivar_name") + }.should raise_error(NameError) { |e| e.name.should == :invalid_ivar_name } + end + + it "always returns a symbol when a NameError is raised from #class_variable_get" do + -> { + Object.class_variable_get("invalid_cvar_name") + }.should raise_error(NameError) { |e| e.name.should == :invalid_cvar_name } + end + end + + ruby_version_is "2.3" do + it "returns the first argument passed to the method when a NameError is raised from #instance_variable_get" do + invalid_ivar_name = "invalid_ivar_name" + + -> { + Object.new.instance_variable_get(invalid_ivar_name) + }.should raise_error(NameError) {|e| e.name.should equal(invalid_ivar_name) } + end + + it "returns the first argument passed to the method when a NameError is raised from #class_variable_get" do + invalid_cvar_name = "invalid_cvar_name" + + -> { + Object.class_variable_get(invalid_cvar_name) + }.should raise_error(NameError) {|e| e.name.should equal(invalid_cvar_name) } + end + end +end diff --git a/spec/ruby/core/exception/new_spec.rb b/spec/ruby/core/exception/new_spec.rb new file mode 100644 index 0000000000..61d35a1dfa --- /dev/null +++ b/spec/ruby/core/exception/new_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) +require File.expand_path('../shared/new', __FILE__) + +describe "Exception.new" do + it_behaves_like(:exception_new, :new) +end diff --git a/spec/ruby/core/exception/no_method_error_spec.rb b/spec/ruby/core/exception/no_method_error_spec.rb new file mode 100644 index 0000000000..cf3fe58b1d --- /dev/null +++ b/spec/ruby/core/exception/no_method_error_spec.rb @@ -0,0 +1,59 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "NoMethodError.new" do + it "allows passing method args" do + NoMethodError.new("msg","name","args").args.should == "args" + end + + it "does not require a name" do + NoMethodError.new("msg").message.should == "msg" + end +end + +describe "NoMethodError#args" do + it "returns an empty array if the caller method had no arguments" do + begin + NoMethodErrorSpecs::NoMethodErrorB.new.foo + rescue Exception => e + e.args.should == [] + end + end + + it "returns an array with the same elements as passed to the method" do + begin + a = NoMethodErrorSpecs::NoMethodErrorA.new + NoMethodErrorSpecs::NoMethodErrorB.new.foo(1,a) + rescue Exception => e + e.args.should == [1,a] + e.args[1].object_id.should == a.object_id + end + end +end + +describe "NoMethodError#message" do + it "for an undefined method match /undefined method/" do + begin + NoMethodErrorSpecs::NoMethodErrorD.new.foo + rescue Exception => e + e.should be_kind_of(NoMethodError) + end + end + + it "for an protected method match /protected method/" do + begin + NoMethodErrorSpecs::NoMethodErrorC.new.a_protected_method + rescue Exception => e + e.should be_kind_of(NoMethodError) + end + end + + it "for private method match /private method/" do + begin + NoMethodErrorSpecs::NoMethodErrorC.new.a_private_method + rescue Exception => e + e.should be_kind_of(NoMethodError) + e.message.match(/private method/).should_not == nil + end + end +end diff --git a/spec/ruby/core/exception/range_error_spec.rb b/spec/ruby/core/exception/range_error_spec.rb new file mode 100644 index 0000000000..9c0462bbf7 --- /dev/null +++ b/spec/ruby/core/exception/range_error_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "RangeError" do + it "is a superclass of FloatDomainError" do + RangeError.should be_ancestor_of(FloatDomainError) + end +end diff --git a/spec/ruby/core/exception/readagain_bytes_spec.rb b/spec/ruby/core/exception/readagain_bytes_spec.rb new file mode 100644 index 0000000000..30efb67686 --- /dev/null +++ b/spec/ruby/core/exception/readagain_bytes_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::InvalidByteSequenceError#readagain_bytes" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/reason_spec.rb b/spec/ruby/core/exception/reason_spec.rb new file mode 100644 index 0000000000..fad4d47c64 --- /dev/null +++ b/spec/ruby/core/exception/reason_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "LocalJumpError#reason" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/receiver_spec.rb b/spec/ruby/core/exception/receiver_spec.rb new file mode 100644 index 0000000000..83f8d5927c --- /dev/null +++ b/spec/ruby/core/exception/receiver_spec.rb @@ -0,0 +1,62 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +ruby_version_is "2.3" do + describe "NameError#receiver" do + class ::ReceiverClass + def call_undefined_class_variable; @@doesnt_exist end + end + + it "returns the object that raised the exception" do + receiver = Object.new + + -> { + receiver.doesnt_exist + }.should raise_error(NameError) {|e| e.receiver.should equal(receiver) } + end + + it "returns the Object class when an undefined constant is called without namespace" do + -> { + DoesntExist + }.should raise_error(NameError) {|e| e.receiver.should equal(Object) } + end + + it "returns a class when an undefined constant is called" do + -> { + NameErrorSpecs::ReceiverClass::DoesntExist + }.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) } + end + + it "returns the Object class when an undefined class variable is called" do + -> { + -> { + @@doesnt_exist + }.should complain(/class variable access from toplevel/) + }.should raise_error(NameError) {|e| e.receiver.should equal(Object) } + end + + it "returns a class when an undefined class variable is called in a subclass' namespace" do + -> { + NameErrorSpecs::ReceiverClass.new.call_undefined_class_variable + }.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) } + end + + it "returns the receiver when raised from #instance_variable_get" do + receiver = Object.new + + -> { + receiver.instance_variable_get("invalid_ivar_name") + }.should raise_error(NameError) {|e| e.receiver.should equal(receiver) } + end + + it "returns the receiver when raised from #class_variable_get" do + -> { + Object.class_variable_get("invalid_cvar_name") + }.should raise_error(NameError) {|e| e.receiver.should equal(Object) } + end + + it "raises an ArgumentError when the receiver is none" do + -> { NameError.new.receiver }.should raise_error(ArgumentError) + end + end +end diff --git a/spec/ruby/core/exception/result_spec.rb b/spec/ruby/core/exception/result_spec.rb new file mode 100644 index 0000000000..350c071f60 --- /dev/null +++ b/spec/ruby/core/exception/result_spec.rb @@ -0,0 +1,29 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "StopIteration" do + it "is a subclass of IndexError" do + StopIteration.superclass.should equal(IndexError) + end +end + +describe "StopIteration#result" do + before :each do + obj = Object.new + def obj.each + yield :yield_returned_1 + yield :yield_returned_2 + :method_returned + end + @enum = obj.to_enum + end + + it "returns the method-returned-object from an Enumerator" do + @enum.next + @enum.next + lambda { @enum.next }.should( + raise_error(StopIteration) do |error| + error.result.should equal(:method_returned) + end + ) + end +end diff --git a/spec/ruby/core/exception/script_error_spec.rb b/spec/ruby/core/exception/script_error_spec.rb new file mode 100644 index 0000000000..5ca0333261 --- /dev/null +++ b/spec/ruby/core/exception/script_error_spec.rb @@ -0,0 +1,15 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +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/set_backtrace_spec.rb b/spec/ruby/core/exception/set_backtrace_spec.rb new file mode 100644 index 0000000000..db58a193ef --- /dev/null +++ b/spec/ruby/core/exception/set_backtrace_spec.rb @@ -0,0 +1,56 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "Exception#set_backtrace" do + it "accepts an Array of Strings" do + err = RuntimeError.new + err.set_backtrace ["unhappy"] + err.backtrace.should == ["unhappy"] + end + + it "allows the user to set the backtrace from a rescued exception" do + bt = ExceptionSpecs::Backtrace.backtrace + err = RuntimeError.new + + err.set_backtrace bt + err.backtrace.should == bt + end + + it "accepts an empty Array" do + err = RuntimeError.new + err.set_backtrace [] + err.backtrace.should == [] + end + + it "accepts a String" do + err = RuntimeError.new + err.set_backtrace "unhappy" + err.backtrace.should == ["unhappy"] + end + + it "accepts nil" do + err = RuntimeError.new + err.set_backtrace nil + err.backtrace.should be_nil + end + + it "raises a TypeError when passed a Symbol" do + err = RuntimeError.new + lambda { err.set_backtrace :unhappy }.should raise_error(TypeError) + end + + it "raises a TypeError when the Array contains a Symbol" do + err = RuntimeError.new + lambda { err.set_backtrace ["String", :unhappy] }.should raise_error(TypeError) + end + + it "raises a TypeError when the array contains nil" do + err = Exception.new + lambda { err.set_backtrace ["String", nil] }.should raise_error(TypeError) + end + + it "raises a TypeError when the argument is a nested array" do + err = Exception.new + lambda { err.set_backtrace ["String", ["String"]] }.should raise_error(TypeError) + end +end diff --git a/spec/ruby/core/exception/shared/new.rb b/spec/ruby/core/exception/shared/new.rb new file mode 100644 index 0000000000..bcde8ee4b2 --- /dev/null +++ b/spec/ruby/core/exception/shared/new.rb @@ -0,0 +1,18 @@ +describe :exception_new, shared: true do + it "creates a new instance of Exception" do + Exception.should be_ancestor_of(Exception.send(@method).class) + end + + it "sets the message of the Exception when passes a message" do + Exception.send(@method, "I'm broken.").message.should == "I'm broken." + end + + it "returns 'Exception' for message when no message given" do + Exception.send(@method).message.should == "Exception" + end + + it "returns the exception when it has a custom constructor" do + ExceptionSpecs::ConstructorException.send(@method).should be_kind_of(ExceptionSpecs::ConstructorException) + end + +end diff --git a/spec/ruby/core/exception/signal_exception_spec.rb b/spec/ruby/core/exception/signal_exception_spec.rb new file mode 100644 index 0000000000..3b2d1aad61 --- /dev/null +++ b/spec/ruby/core/exception/signal_exception_spec.rb @@ -0,0 +1,74 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "SignalException.new" do + it "takes a signal number as the first argument" do + exc = SignalException.new(Signal.list["INT"]) + exc.signo.should == Signal.list["INT"] + exc.signm.should == "SIGINT" + exc.message.should == "SIGINT" + end + + it "raises an exception with an invalid signal number" do + lambda { SignalException.new(100000) }.should raise_error(ArgumentError) + end + + it "takes a signal name without SIG prefix as the first argument" do + exc = SignalException.new("INT") + exc.signo.should == Signal.list["INT"] + exc.signm.should == "SIGINT" + exc.message.should == "SIGINT" + end + + it "takes a signal name with SIG prefix as the first argument" do + exc = SignalException.new("SIGINT") + exc.signo.should == Signal.list["INT"] + exc.signm.should == "SIGINT" + exc.message.should == "SIGINT" + end + + it "raises an exception with an invalid signal name" do + lambda { SignalException.new("NONEXISTANT") }.should raise_error(ArgumentError) + end + + it "takes a signal symbol without SIG prefix as the first argument" do + exc = SignalException.new(:INT) + exc.signo.should == Signal.list["INT"] + exc.signm.should == "SIGINT" + exc.message.should == "SIGINT" + end + + it "takes a signal symbol with SIG prefix as the first argument" do + exc = SignalException.new(:SIGINT) + exc.signo.should == Signal.list["INT"] + exc.signm.should == "SIGINT" + exc.message.should == "SIGINT" + end + + it "raises an exception with an invalid signal name" do + lambda { SignalException.new(:NONEXISTANT) }.should raise_error(ArgumentError) + end + + it "takes an optional message argument with a signal number" do + exc = SignalException.new(Signal.list["INT"], "name") + exc.signo.should == Signal.list["INT"] + exc.signm.should == "name" + exc.message.should == "name" + end + + it "raises an exception for an optional argument with a signal name" do + lambda { SignalException.new("INT","name") }.should raise_error(ArgumentError) + end +end + +describe "rescueing SignalException" do + it "raises a SignalException when sent a signal" do + begin + Process.kill :TERM, Process.pid + sleep + rescue SignalException => e + e.signo.should == Signal.list["TERM"] + e.signm.should == "SIGTERM" + e.message.should == "SIGTERM" + end + end +end diff --git a/spec/ruby/core/exception/signm_spec.rb b/spec/ruby/core/exception/signm_spec.rb new file mode 100644 index 0000000000..e205b79e19 --- /dev/null +++ b/spec/ruby/core/exception/signm_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "SignalException#signm" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/signo_spec.rb b/spec/ruby/core/exception/signo_spec.rb new file mode 100644 index 0000000000..08c85274ca --- /dev/null +++ b/spec/ruby/core/exception/signo_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "SignalException#signo" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/source_encoding_name_spec.rb b/spec/ruby/core/exception/source_encoding_name_spec.rb new file mode 100644 index 0000000000..5796072121 --- /dev/null +++ b/spec/ruby/core/exception/source_encoding_name_spec.rb @@ -0,0 +1,9 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::UndefinedConversionError#source_encoding_name" do + it "needs to be reviewed for spec completeness" +end + +describe "Encoding::InvalidByteSequenceError#source_encoding_name" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/source_encoding_spec.rb b/spec/ruby/core/exception/source_encoding_spec.rb new file mode 100644 index 0000000000..796bec88f6 --- /dev/null +++ b/spec/ruby/core/exception/source_encoding_spec.rb @@ -0,0 +1,9 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Encoding::UndefinedConversionError#source_encoding" do + it "needs to be reviewed for spec completeness" +end + +describe "Encoding::InvalidByteSequenceError#source_encoding" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/standard_error_spec.rb b/spec/ruby/core/exception/standard_error_spec.rb new file mode 100644 index 0000000000..9b3af4b322 --- /dev/null +++ b/spec/ruby/core/exception/standard_error_spec.rb @@ -0,0 +1,50 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +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) + end + + it "is a superclass of ZeroDivisionError" do + StandardError.should be_ancestor_of(ZeroDivisionError) + end +end diff --git a/spec/ruby/core/exception/status_spec.rb b/spec/ruby/core/exception/status_spec.rb new file mode 100644 index 0000000000..e648dc0adc --- /dev/null +++ b/spec/ruby/core/exception/status_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "SystemExit#status" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/success_spec.rb b/spec/ruby/core/exception/success_spec.rb new file mode 100644 index 0000000000..d9b69b4f45 --- /dev/null +++ b/spec/ruby/core/exception/success_spec.rb @@ -0,0 +1,5 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "SystemExit#success?" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/system_call_error_spec.rb b/spec/ruby/core/exception/system_call_error_spec.rb new file mode 100644 index 0000000000..edcc8d3734 --- /dev/null +++ b/spec/ruby/core/exception/system_call_error_spec.rb @@ -0,0 +1,89 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "SystemCallError" do + before :each do + ScratchPad.clear + end + + it "can be subclassed" do + ExceptionSpecs::SCESub = Class.new(SystemCallError) do + def initialize + ScratchPad.record :initialize + end + end + + exc = ExceptionSpecs::SCESub.new + ScratchPad.recorded.should equal(:initialize) + exc.should be_an_instance_of(ExceptionSpecs::SCESub) + end +end + +describe "SystemCallError.new" do + it "requires at least one argument" do + lambda { 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(2**24).errno.should == 2**24 + 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) + 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" + 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" + end + + it "returns an arity of -1 for the initialize method" do + SystemCallError.instance_method(:initialize).arity.should == -1 + end +end + +describe "SystemCallError#errno" do + it "returns nil when no errno given" do + SystemCallError.new("message").errno.should == nil + end + + it "returns the errno given as optional argument to new" do + SystemCallError.new("message", -2**20).errno.should == -2**20 + SystemCallError.new("message", -1).errno.should == -1 + SystemCallError.new("message", 0).errno.should == 0 + SystemCallError.new("message", 1).errno.should == 1 + SystemCallError.new("message", 42).errno.should == 42 + SystemCallError.new("message", 2**20).errno.should == 2**20 + end +end + +describe "SystemCallError#message" do + it "returns the default message when no message is given" do + platform_is :aix do + SystemCallError.new(2**28).message.should =~ /Error .*occurred/i + end + platform_is_not :aix do + SystemCallError.new(2**28).message.should =~ /Unknown error/i + end + end + + it "returns the message given as an argument to new" do + SystemCallError.new("message", 1).message.should =~ /message/ + SystemCallError.new("XXX").message.should =~ /XXX/ + end +end diff --git a/spec/ruby/core/exception/system_stack_error_spec.rb b/spec/ruby/core/exception/system_stack_error_spec.rb new file mode 100644 index 0000000000..acd56c0a0f --- /dev/null +++ b/spec/ruby/core/exception/system_stack_error_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "SystemStackError" do + it "is a subclass of Exception" do + SystemStackError.superclass.should == Exception + end +end diff --git a/spec/ruby/core/exception/to_s_spec.rb b/spec/ruby/core/exception/to_s_spec.rb new file mode 100644 index 0000000000..83234bfe23 --- /dev/null +++ b/spec/ruby/core/exception/to_s_spec.rb @@ -0,0 +1,23 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/common', __FILE__) + +describe "Exception#to_s" do + it "returns the self's name if no message is set" do + Exception.new.to_s.should == 'Exception' + ExceptionSpecs::Exceptional.new.to_s.should == 'ExceptionSpecs::Exceptional' + end + + it "returns self's message if set" do + ExceptionSpecs::Exceptional.new('!!').to_s.should == '!!' + end + + it "calls #to_s on the message" do + message = mock("message") + message.should_receive(:to_s).and_return("message") + ExceptionSpecs::Exceptional.new(message).to_s.should == "message" + end +end + +describe "NameError#to_s" do + it "needs to be reviewed for spec completeness" +end diff --git a/spec/ruby/core/exception/uncaught_throw_error_spec.rb b/spec/ruby/core/exception/uncaught_throw_error_spec.rb new file mode 100644 index 0000000000..3ed166af5b --- /dev/null +++ b/spec/ruby/core/exception/uncaught_throw_error_spec.rb @@ -0,0 +1,19 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "UncaughtThrowError" do + it "is a subclass of ArgumentError" do + ArgumentError.should be_ancestor_of(UncaughtThrowError) + end +end + +describe "UncaughtThrowError#tag" do + it "returns the object thrown" do + begin + throw :abc + + rescue UncaughtThrowError => e + e.tag.should == :abc + end + end +end + |