summaryrefslogtreecommitdiff
path: root/test/ruby/test_method.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_method.rb')
-rw-r--r--test/ruby/test_method.rb351
1 files changed, 343 insertions, 8 deletions
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index ef28098dce..d0eaf6118a 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -1,6 +1,16 @@
require 'test/unit'
+require_relative 'envutil'
class TestMethod < Test::Unit::TestCase
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
def m0() end
def m1(a) end
def m2(a, b) end
@@ -8,18 +18,26 @@ class TestMethod < Test::Unit::TestCase
def mo2(a, b = nil) end
def mo3(*a) end
def mo4(a, *b, &c) end
+ def mo5(a, *b, c) end
+ def mo6(a, *b, c, &d) end
+ def mo7(a, b = nil, *c, d, &e) end
+ def ma1((a), &b) end
class Base
def foo() :base end
- def bar() :bar end
- end
- module SuperBar
- def bar() super end
end
class Derived < Base
- include SuperBar
def foo() :derived end
end
+ class T
+ def initialize; end
+ def normal_method; end
+ end
+ module M
+ def func; end
+ module_function :func
+ def meth; end
+ end
def test_arity
assert_equal(0, method(:m0).arity)
@@ -29,6 +47,12 @@ class TestMethod < Test::Unit::TestCase
assert_equal(-2, method(:mo2).arity)
assert_equal(-1, method(:mo3).arity)
assert_equal(-2, method(:mo4).arity)
+ assert_equal(-3, method(:mo5).arity)
+ assert_equal(-3, method(:mo6).arity)
+ end
+
+ def test_arity_special
+ assert_equal(-1, method(:__send__).arity)
end
def test_unbind
@@ -45,9 +69,320 @@ class TestMethod < Test::Unit::TestCase
end
end
- def test_method_super
- assert_nothing_raised do
- assert_equal(:bar, Derived.new.method(:bar).call)
+ def test_callee
+ assert_equal(:test_callee, __method__)
+ assert_equal(:m, Class.new {def m; __method__; end}.new.m)
+ assert_equal(:m, Class.new {def m; tap{return __method__}; end}.new.m)
+ assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m)
+ assert_equal(:m, Class.new {define_method(:m) {tap{return __method__}}}.new.m)
+ assert_nil(eval("class TestCallee; __method__; end"))
+ end
+
+ def test_method_in_define_method_block
+ bug4606 = '[ruby-core:35386]'
+ c = Class.new do
+ [:m1, :m2].each do |m|
+ define_method(m) do
+ __method__
+ end
+ end
+ end
+ assert_equal(:m1, c.new.m1, bug4606)
+ assert_equal(:m2, c.new.m2, bug4606)
+ end
+
+ def test_method_in_block_in_define_method_block
+ bug4606 = '[ruby-core:35386]'
+ c = Class.new do
+ [:m1, :m2].each do |m|
+ define_method(m) do
+ tap { return __method__ }
+ end
+ end
+ end
+ assert_equal(:m1, c.new.m1, bug4606)
+ assert_equal(:m2, c.new.m2, bug4606)
+ end
+
+ def test_body
+ o = Object.new
+ def o.foo; end
+ assert_nothing_raised { RubyVM::InstructionSequence.disasm(o.method(:foo)) }
+ assert_nothing_raised { RubyVM::InstructionSequence.disasm("x".method(:upcase)) }
+ end
+
+ def test_new
+ c1 = Class.new
+ c1.class_eval { def foo; :foo; end }
+ c2 = Class.new(c1)
+ c2.class_eval { private :foo }
+ o = c2.new
+ o.extend(Module.new)
+ assert_raise(NameError) { o.method(:bar) }
+ assert_raise(NameError) { o.public_method(:foo) }
+ assert_equal(:foo, o.method(:foo).call)
+ end
+
+ def test_eq
+ o = Object.new
+ class << o
+ def foo; end
+ alias bar foo
+ def baz; end
+ end
+ assert_not_equal(o.method(:foo), nil)
+ m = o.method(:foo)
+ def m.foo; end
+ assert_not_equal(o.method(:foo), m)
+ assert_equal(o.method(:foo), o.method(:foo))
+ assert_equal(o.method(:foo), o.method(:bar))
+ assert_not_equal(o.method(:foo), o.method(:baz))
+ end
+
+ def test_hash
+ o = Object.new
+ def o.foo; end
+ assert_kind_of(Integer, o.method(:foo).hash)
+ end
+
+ def test_receiver_name_owner
+ o = Object.new
+ def o.foo; end
+ m = o.method(:foo)
+ assert_equal(o, m.receiver)
+ assert_equal(:foo, m.name)
+ assert_equal(class << o; self; end, m.owner)
+ assert_equal(:foo, m.unbind.name)
+ assert_equal(class << o; self; end, m.unbind.owner)
+ end
+
+ def test_instance_method
+ c = Class.new
+ c.class_eval do
+ def foo; :foo; end
+ private :foo
+ end
+ o = c.new
+ o.method(:foo).unbind
+ assert_raise(NoMethodError) { o.foo }
+ c.instance_method(:foo).bind(o)
+ assert_equal(:foo, o.instance_eval { foo })
+ assert_raise(NameError) { c.public_instance_method(:foo) }
+ def o.bar; end
+ m = o.method(:bar).unbind
+ assert_raise(TypeError) { m.bind(Object.new) }
+ end
+
+ def test_define_method
+ c = Class.new
+ c.class_eval { def foo; :foo; end }
+ o = c.new
+ def o.bar; :bar; end
+ assert_raise(TypeError) do
+ c.class_eval { define_method(:foo, :foo) }
+ end
+ assert_raise(ArgumentError) do
+ c.class_eval { define_method }
+ end
+ c2 = Class.new(c)
+ c2.class_eval { define_method(:baz, o.method(:foo)) }
+ assert_equal(:foo, c2.new.baz)
+ assert_raise(TypeError) do
+ Class.new.class_eval { define_method(:foo, o.method(:foo)) }
+ end
+ assert_raise(TypeError) do
+ Class.new.class_eval { define_method(:bar, o.method(:bar)) }
+ end
+
+ o = Object.new
+ def o.foo(c)
+ c.class_eval { define_method(:foo) }
+ end
+ c = Class.new
+ o.foo(c) { :foo }
+ assert_equal(:foo, c.new.foo)
+
+ o = Object.new
+ o.instance_eval { define_singleton_method(:foo) { :foo } }
+ assert_equal(:foo, o.foo)
+
+ assert_raise(TypeError) do
+ Class.new.class_eval { define_method(:foo, Object.new) }
+ end
+ end
+
+ def test_super_in_proc_from_define_method
+ c1 = Class.new {
+ def m
+ :m1
+ end
+ }
+ c2 = Class.new(c1) { define_method(:m) { Proc.new { super() } } }
+ # c2.new.m.call should return :m1, but currently it raise NoMethodError.
+ # see [Bug #4881] and [Bug #3136]
+ assert_raise(NoMethodError) {
+ c2.new.m.call
+ }
+ end
+
+ def test_clone
+ o = Object.new
+ def o.foo; :foo; end
+ m = o.method(:foo)
+ def m.bar; :bar; end
+ assert_equal(:foo, m.clone.call)
+ assert_equal(:bar, m.clone.bar)
+ end
+
+ def test_call
+ o = Object.new
+ def o.foo; p 1; end
+ def o.bar(x); x; end
+ m = o.method(:foo)
+ m.taint
+ assert_raise(SecurityError) { m.call }
+ end
+
+ def test_inspect
+ o = Object.new
+ def o.foo; end
+ m = o.method(:foo)
+ assert_equal("#<Method: #{ o.inspect }.foo>", m.inspect)
+ m = o.method(:foo)
+ assert_equal("#<UnboundMethod: #{ class << o; self; end.inspect }#foo>", m.unbind.inspect)
+
+ c = Class.new
+ c.class_eval { def foo; end; }
+ m = c.new.method(:foo)
+ assert_equal("#<Method: #{ c.inspect }#foo>", m.inspect)
+ m = c.instance_method(:foo)
+ assert_equal("#<UnboundMethod: #{ c.inspect }#foo>", m.inspect)
+
+ c2 = Class.new(c)
+ c2.class_eval { private :foo }
+ m2 = c2.new.method(:foo)
+ assert_equal("#<Method: #{ c2.inspect }(#{ c.inspect })#foo>", m2.inspect)
+ end
+
+ def test_callee_top_level
+ assert_in_out_err([], "p __callee__", %w(nil), [])
+ end
+
+ def test_caller_top_level
+ assert_in_out_err([], "p caller", %w([]), [])
+ end
+
+ def test_caller_negative_level
+ assert_raise(ArgumentError) { caller(-1) }
+ end
+
+ def test_attrset_ivar
+ c = Class.new
+ c.class_eval { attr_accessor :foo }
+ o = c.new
+ o.method(:foo=).call(42)
+ assert_equal(42, o.foo)
+ assert_raise(ArgumentError) { o.method(:foo=).call(1, 2, 3) }
+ assert_raise(ArgumentError) { o.method(:foo).call(1) }
+ end
+
+ def test_default_accessibility
+ assert T.public_instance_methods.include?(:normal_method), 'normal methods are public by default'
+ assert !T.public_instance_methods.include?(:initialize), '#initialize is private'
+ assert !M.public_instance_methods.include?(:func), 'module methods are private by default'
+ assert M.public_instance_methods.include?(:meth), 'normal methods are public by default'
+ end
+
+ define_method(:pm0) {||}
+ define_method(:pm1) {|a|}
+ define_method(:pm2) {|a, b|}
+ define_method(:pmo1) {|a = nil, &b|}
+ define_method(:pmo2) {|a, b = nil|}
+ define_method(:pmo3) {|*a|}
+ define_method(:pmo4) {|a, *b, &c|}
+ define_method(:pmo5) {|a, *b, c|}
+ define_method(:pmo6) {|a, *b, c, &d|}
+ define_method(:pmo7) {|a, b = nil, *c, d, &e|}
+ define_method(:pma1) {|(a), &b|}
+
+ def test_bound_parameters
+ assert_equal([], method(:m0).parameters)
+ assert_equal([[:req, :a]], method(:m1).parameters)
+ assert_equal([[:req, :a], [:req, :b]], method(:m2).parameters)
+ assert_equal([[:opt, :a], [:block, :b]], method(:mo1).parameters)
+ assert_equal([[:req, :a], [:opt, :b]], method(:mo2).parameters)
+ assert_equal([[:rest, :a]], method(:mo3).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:block, :c]], method(:mo4).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c]], method(:mo5).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:mo6).parameters)
+ assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:mo7).parameters)
+ assert_equal([[:req], [:block, :b]], method(:ma1).parameters)
+ end
+
+ def test_unbound_parameters
+ assert_equal([], self.class.instance_method(:m0).parameters)
+ assert_equal([[:req, :a]], self.class.instance_method(:m1).parameters)
+ assert_equal([[:req, :a], [:req, :b]], self.class.instance_method(:m2).parameters)
+ assert_equal([[:opt, :a], [:block, :b]], self.class.instance_method(:mo1).parameters)
+ assert_equal([[:req, :a], [:opt, :b]], self.class.instance_method(:mo2).parameters)
+ assert_equal([[:rest, :a]], self.class.instance_method(:mo3).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:block, :c]], self.class.instance_method(:mo4).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c]], self.class.instance_method(:mo5).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], self.class.instance_method(:mo6).parameters)
+ assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:mo7).parameters)
+ assert_equal([[:req], [:block, :b]], self.class.instance_method(:ma1).parameters)
+ end
+
+ def test_bmethod_bound_parameters
+ assert_equal([], method(:pm0).parameters)
+ assert_equal([[:req, :a]], method(:pm1).parameters)
+ assert_equal([[:req, :a], [:req, :b]], method(:pm2).parameters)
+ assert_equal([[:opt, :a], [:block, :b]], method(:pmo1).parameters)
+ assert_equal([[:req, :a], [:opt, :b]], method(:pmo2).parameters)
+ assert_equal([[:rest, :a]], method(:pmo3).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:block, :c]], method(:pmo4).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c]], method(:pmo5).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:pmo6).parameters)
+ assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:pmo7).parameters)
+ assert_equal([[:req], [:block, :b]], method(:pma1).parameters)
+ end
+
+ def test_bmethod_unbound_parameters
+ assert_equal([], self.class.instance_method(:pm0).parameters)
+ assert_equal([[:req, :a]], self.class.instance_method(:pm1).parameters)
+ assert_equal([[:req, :a], [:req, :b]], self.class.instance_method(:pm2).parameters)
+ assert_equal([[:opt, :a], [:block, :b]], self.class.instance_method(:pmo1).parameters)
+ assert_equal([[:req, :a], [:opt, :b]], self.class.instance_method(:pmo2).parameters)
+ assert_equal([[:rest, :a]], self.class.instance_method(:pmo3).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:block, :c]], self.class.instance_method(:pmo4).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c]], self.class.instance_method(:pmo5).parameters)
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], self.class.instance_method(:pmo6).parameters)
+ assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:pmo7).parameters)
+ assert_equal([[:req], [:block, :b]], self.class.instance_method(:pma1).parameters)
+ end
+
+ def test_public_method_with_zsuper_method
+ c = Class.new
+ c.class_eval do
+ def foo
+ :ok
+ end
+ private :foo
+ end
+ d = Class.new(c)
+ d.class_eval do
+ public :foo
end
+ assert_equal(:ok, d.new.public_method(:foo).call)
+ end
+
+ def test_public_methods_with_extended
+ m = Module.new do def m1; end end
+ a = Class.new do def a; end end
+ bug = '[ruby-dev:41553]'
+ obj = a.new
+ assert_equal([:a], obj.public_methods(false), bug)
+ obj.extend(m)
+ assert_equal([:m1, :a], obj.public_methods(false), bug)
end
end