diff options
Diffstat (limited to 'spec/ruby/core/method/shared')
| -rw-r--r-- | spec/ruby/core/method/shared/call.rb | 51 | ||||
| -rw-r--r-- | spec/ruby/core/method/shared/dup.rb | 32 | ||||
| -rw-r--r-- | spec/ruby/core/method/shared/eql.rb | 94 | ||||
| -rw-r--r-- | spec/ruby/core/method/shared/to_s.rb | 81 |
4 files changed, 258 insertions, 0 deletions
diff --git a/spec/ruby/core/method/shared/call.rb b/spec/ruby/core/method/shared/call.rb new file mode 100644 index 0000000000..f26e373695 --- /dev/null +++ b/spec/ruby/core/method/shared/call.rb @@ -0,0 +1,51 @@ +describe :method_call, shared: true do + it "invokes the method with the specified arguments, returning the method's return value" do + m = 12.method("+") + m.send(@method, 3).should == 15 + m.send(@method, 20).should == 32 + + m = MethodSpecs::Methods.new.method(:attr=) + m.send(@method, 42).should == 42 + end + + it "raises an ArgumentError when given incorrect number of arguments" do + -> { + MethodSpecs::Methods.new.method(:two_req).send(@method, 1, 2, 3) + }.should raise_error(ArgumentError) + -> { + MethodSpecs::Methods.new.method(:two_req).send(@method, 1) + }.should raise_error(ArgumentError) + end + + describe "for a Method generated by respond_to_missing?" do + it "invokes method_missing with the specified arguments and returns the result" do + @m = MethodSpecs::Methods.new + meth = @m.method(:handled_via_method_missing) + meth.send(@method, :argument).should == [:argument] + end + + it "invokes method_missing with the method name and the specified arguments" do + @m = MethodSpecs::Methods.new + meth = @m.method(:handled_via_method_missing) + + @m.should_receive(:method_missing).with(:handled_via_method_missing, :argument) + meth.send(@method, :argument) + end + + it "invokes method_missing dynamically" do + @m = MethodSpecs::Methods.new + meth = @m.method(:handled_via_method_missing) + + def @m.method_missing(*); :changed; end + meth.send(@method, :argument).should == :changed + end + + it "does not call the original method name even if it now exists" do + @m = MethodSpecs::Methods.new + meth = @m.method(:handled_via_method_missing) + + def @m.handled_via_method_missing(*); :not_called; end + meth.send(@method, :argument).should == [:argument] + end + end +end diff --git a/spec/ruby/core/method/shared/dup.rb b/spec/ruby/core/method/shared/dup.rb new file mode 100644 index 0000000000..c74847083f --- /dev/null +++ b/spec/ruby/core/method/shared/dup.rb @@ -0,0 +1,32 @@ +describe :method_dup, shared: true do + it "returns a copy of self" do + a = Object.new.method(:method) + b = a.send(@method) + + a.should == b + a.should_not equal(b) + end + + ruby_version_is "3.4" do + it "copies instance variables" do + method = Object.new.method(:method) + method.instance_variable_set(:@ivar, 1) + cl = method.send(@method) + cl.instance_variables.should == [:@ivar] + end + + it "copies the finalizer" do + code = <<-'RUBY' + obj = Object.new.method(:method) + + ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" }) + + obj.clone + + exit 0 + RUBY + + ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"] + end + end +end diff --git a/spec/ruby/core/method/shared/eql.rb b/spec/ruby/core/method/shared/eql.rb new file mode 100644 index 0000000000..5c720cbac1 --- /dev/null +++ b/spec/ruby/core/method/shared/eql.rb @@ -0,0 +1,94 @@ +require_relative '../../../spec_helper' +require_relative '../fixtures/classes' + +describe :method_equal, shared: true do + before :each do + @m = MethodSpecs::Methods.new + @m_foo = @m.method(:foo) + @m2 = MethodSpecs::Methods.new + @a = MethodSpecs::A.new + end + + it "returns true if methods are the same" do + m2 = @m.method(:foo) + + @m_foo.send(@method, @m_foo).should be_true + @m_foo.send(@method, m2).should be_true + end + + it "returns true on aliased methods" do + m_bar = @m.method(:bar) + + m_bar.send(@method, @m_foo).should be_true + end + + it "returns true if the two core methods are aliases" do + s = "hello" + a = s.method(:size) + b = s.method(:length) + a.send(@method, b).should be_true + end + + it "returns false on a method which is neither aliased nor the same method" do + m2 = @m.method(:zero) + + @m_foo.send(@method, m2).should be_false + end + + it "returns false for a method which is not bound to the same object" do + m2_foo = @m2.method(:foo) + a_baz = @a.method(:baz) + + @m_foo.send(@method, m2_foo).should be_false + @m_foo.send(@method, a_baz).should be_false + end + + it "returns false if the two methods are bound to the same object but were defined independently" do + m2 = @m.method(:same_as_foo) + @m_foo.send(@method, m2).should be_false + end + + it "returns true if a method was defined using the other one" do + MethodSpecs::Methods.send :define_method, :defined_foo, MethodSpecs::Methods.instance_method(:foo) + m2 = @m.method(:defined_foo) + @m_foo.send(@method, m2).should be_true + end + + it "returns false if comparing a method defined via define_method and def" do + defn = @m.method(:zero) + defined = @m.method(:zero_defined_method) + + defn.send(@method, defined).should be_false + defined.send(@method, defn).should be_false + end + + describe 'missing methods' do + it "returns true for the same method missing" do + miss1 = @m.method(:handled_via_method_missing) + miss1bis = @m.method(:handled_via_method_missing) + miss2 = @m.method(:also_handled) + + miss1.send(@method, miss1bis).should be_true + miss1.send(@method, miss2).should be_false + end + + it 'calls respond_to_missing? with true to include private methods' do + @m.should_receive(:respond_to_missing?).with(:some_missing_method, true).and_return(true) + @m.method(:some_missing_method) + end + end + + it "returns false if the two methods are bound to different objects, have the same names, and identical bodies" do + a = MethodSpecs::Eql.instance_method(:same_body) + b = MethodSpecs::Eql2.instance_method(:same_body) + a.send(@method, b).should be_false + end + + it "returns false if the argument is not a Method object" do + String.instance_method(:size).send(@method, 7).should be_false + end + + it "returns false if the argument is an unbound version of self" do + method(:load).send(@method, method(:load).unbind).should be_false + end +end diff --git a/spec/ruby/core/method/shared/to_s.rb b/spec/ruby/core/method/shared/to_s.rb new file mode 100644 index 0000000000..b2d27d370f --- /dev/null +++ b/spec/ruby/core/method/shared/to_s.rb @@ -0,0 +1,81 @@ +require_relative '../../../spec_helper' +require_relative '../fixtures/classes' + +describe :method_to_s, shared: true do + before :each do + @m = MethodSpecs::MySub.new.method :bar + @string = @m.send(@method) + end + + it "returns a String" do + @m.send(@method).should be_kind_of(String) + end + + it "returns a String for methods defined with attr_accessor" do + m = MethodSpecs::Methods.new.method :attr + m.send(@method).should be_kind_of(String) + end + + it "returns a String containing 'Method'" do + @string.should =~ /\bMethod\b/ + end + + it "returns a String containing the method name" do + @string.should =~ /\#bar/ + end + + it "returns a String containing method arguments" do + obj = MethodSpecs::Methods.new + obj.method(:zero).send(@method).should.include?("()") + obj.method(:one_req).send(@method).should.include?("(a)") + obj.method(:one_req_named).send(@method).should.include?("(a:)") + obj.method(:zero_with_block).send(@method).should.include?("(&blk)") + obj.method(:one_opt).send(@method).should.include?("(a=...)") + obj.method(:one_opt_named).send(@method).should.include?("(a: ...)") + obj.method(:zero_with_splat).send(@method).should.include?("(*a)") + obj.method(:zero_with_double_splat).send(@method).should.include?("(**a)") + obj.method(:one_req_one_opt_with_splat_and_block).send(@method).should.include?("(a, b=..., *c, &blk)") + end + + it "returns a String containing the Module the method is defined in" do + @string.should =~ /MethodSpecs::MyMod/ + end + + it "returns a String containing the Module the method is referenced from" do + @string.should =~ /MethodSpecs::MySub/ + end + + it "returns a String including all details" do + @string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar" + end + + it "does not show the defining module if it is the same as the receiver class" do + MethodSpecs::A.new.method(:baz).send(@method).should.start_with? "#<Method: MethodSpecs::A#baz" + end + + it "returns a String containing the Module containing the method if object has a singleton class but method is not defined in the singleton class" do + obj = MethodSpecs::MySub.new + obj.singleton_class + @m = obj.method(:bar) + @string = @m.send(@method) + @string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar" + + c = MethodSpecs::MySub.dup + m = Module.new{def bar; end} + c.extend(m) + @string = c.method(:bar).send(@method) + @string.should.start_with? "#<Method: #<Class:#{c.inspect}>(#{m.inspect})#bar" + end + + it "returns a String containing the singleton class if method is defined in the singleton class" do + obj = MethodSpecs::MySub.new + def obj.bar; end + @m = obj.method(:bar) + @string = @m.send(@method).sub(/0x\h+/, '0xXXXXXX') + @string.should.start_with? "#<Method: #<MethodSpecs::MySub:0xXXXXXX>.bar" + end + + it "shows the metaclass and the owner for a Module instance method retrieved from a class" do + String.method(:include).inspect.should.start_with?("#<Method: #<Class:String>(Module)#include") + end +end |
