1# -*- coding: us-ascii -*-
2require 'test/unit'
3require_relative 'envutil'
4
5class TestMethod < Test::Unit::TestCase
6  def setup
7    @verbose = $VERBOSE
8    $VERBOSE = nil
9  end
10
11  def teardown
12    $VERBOSE = @verbose
13  end
14
15  def m0() end
16  def m1(a) end
17  def m2(a, b) end
18  def mo1(a = nil, &b) end
19  def mo2(a, b = nil) end
20  def mo3(*a) end
21  def mo4(a, *b, &c) end
22  def mo5(a, *b, c) end
23  def mo6(a, *b, c, &d) end
24  def mo7(a, b = nil, *c, d, &e) end
25  def ma1((a), &b) end
26
27  class Base
28    def foo() :base end
29  end
30  class Derived < Base
31    def foo() :derived end
32  end
33  class T
34    def initialize; end
35    def initialize_copy(*) super end
36    def initialize_clone(*) super end
37    def initialize_dup(*) super end
38    def respond_to_missing?(*) super end
39    def normal_method; end
40  end
41  module M
42    def func; end
43    module_function :func
44    def meth; :meth end
45  end
46
47  def mv1() end
48  def mv2() end
49  private :mv2
50  def mv3() end
51  protected :mv3
52
53  class Visibility
54    def mv1() end
55    def mv2() end
56    private :mv2
57    def mv3() end
58    protected :mv3
59  end
60
61  def test_arity
62    assert_equal(0, method(:m0).arity)
63    assert_equal(1, method(:m1).arity)
64    assert_equal(2, method(:m2).arity)
65    assert_equal(-1, method(:mo1).arity)
66    assert_equal(-2, method(:mo2).arity)
67    assert_equal(-1, method(:mo3).arity)
68    assert_equal(-2, method(:mo4).arity)
69    assert_equal(-3, method(:mo5).arity)
70    assert_equal(-3, method(:mo6).arity)
71  end
72
73  def test_arity_special
74    assert_equal(-1, method(:__send__).arity)
75  end
76
77  def test_unbind
78    assert_equal(:derived, Derived.new.foo)
79    um = Derived.new.method(:foo).unbind
80    assert_instance_of(UnboundMethod, um)
81    Derived.class_eval do
82      def foo() :changed end
83    end
84    assert_equal(:changed, Derived.new.foo)
85    assert_equal(:derived, um.bind(Derived.new).call)
86    assert_raise(TypeError) do
87      um.bind(Base.new)
88    end
89  end
90
91  def test_callee
92    assert_equal(:test_callee, __method__)
93    assert_equal(:m, Class.new {def m; __method__; end}.new.m)
94    assert_equal(:m, Class.new {def m; tap{return __method__}; end}.new.m)
95    assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m)
96    assert_equal(:m, Class.new {define_method(:m) {tap{return __method__}}}.new.m)
97    assert_nil(eval("class TestCallee; __method__; end"))
98
99    assert_equal(:test_callee, __callee__)
100    [
101      ["method",              Class.new {def m; __callee__; end},],
102      ["block",               Class.new {def m; tap{return __callee__}; end},],
103      ["define_method",       Class.new {define_method(:m) {__callee__}}],
104      ["define_method block", Class.new {define_method(:m) {tap{return __callee__}}}],
105    ].each do |mesg, c|
106      c.class_eval {alias m2 m}
107      o = c.new
108      assert_equal(:m, o.m, mesg)
109      assert_equal(:m2, o.m2, mesg)
110    end
111    assert_nil(eval("class TestCallee; __callee__; end"))
112  end
113
114  def test_method_in_define_method_block
115    bug4606 = '[ruby-core:35386]'
116    c = Class.new do
117      [:m1, :m2].each do |m|
118        define_method(m) do
119          __method__
120        end
121      end
122    end
123    assert_equal(:m1, c.new.m1, bug4606)
124    assert_equal(:m2, c.new.m2, bug4606)
125  end
126
127  def test_method_in_block_in_define_method_block
128    bug4606 = '[ruby-core:35386]'
129    c = Class.new do
130      [:m1, :m2].each do |m|
131        define_method(m) do
132          tap { return __method__ }
133        end
134      end
135    end
136    assert_equal(:m1, c.new.m1, bug4606)
137    assert_equal(:m2, c.new.m2, bug4606)
138  end
139
140  def test_body
141    o = Object.new
142    def o.foo; end
143    assert_nothing_raised { RubyVM::InstructionSequence.disasm(o.method(:foo)) }
144    assert_nothing_raised { RubyVM::InstructionSequence.disasm("x".method(:upcase)) }
145    assert_nothing_raised { RubyVM::InstructionSequence.disasm(method(:to_s).to_proc) }
146  end
147
148  def test_new
149    c1 = Class.new
150    c1.class_eval { def foo; :foo; end }
151    c2 = Class.new(c1)
152    c2.class_eval { private :foo }
153    o = c2.new
154    o.extend(Module.new)
155    assert_raise(NameError) { o.method(:bar) }
156    assert_raise(NameError) { o.public_method(:foo) }
157    assert_equal(:foo, o.method(:foo).call)
158  end
159
160  def test_eq
161    o = Object.new
162    class << o
163      def foo; end
164      alias bar foo
165      def baz; end
166    end
167    assert_not_equal(o.method(:foo), nil)
168    m = o.method(:foo)
169    def m.foo; end
170    assert_not_equal(o.method(:foo), m)
171    assert_equal(o.method(:foo), o.method(:foo))
172    assert_equal(o.method(:foo), o.method(:bar))
173    assert_not_equal(o.method(:foo), o.method(:baz))
174  end
175
176  def test_hash
177    o = Object.new
178    def o.foo; end
179    assert_kind_of(Integer, o.method(:foo).hash)
180    assert_equal(Array.instance_method(:map).hash, Array.instance_method(:collect).hash)
181  end
182
183  def test_owner
184    c = Class.new do
185      def foo; end
186    end
187    assert_equal(c, c.instance_method(:foo).owner)
188    c2 = Class.new(c)
189    assert_equal(c, c2.instance_method(:foo).owner)
190  end
191
192  def test_owner_missing
193    c = Class.new do
194      def respond_to_missing?(name, bool)
195        name == :foo
196      end
197    end
198    c2 = Class.new(c)
199    assert_equal(c, c.new.method(:foo).owner)
200    assert_equal(c2, c2.new.method(:foo).owner)
201  end
202
203  def test_receiver_name_owner
204    o = Object.new
205    def o.foo; end
206    m = o.method(:foo)
207    assert_equal(o, m.receiver)
208    assert_equal(:foo, m.name)
209    assert_equal(class << o; self; end, m.owner)
210    assert_equal(:foo, m.unbind.name)
211    assert_equal(class << o; self; end, m.unbind.owner)
212  end
213
214  def test_instance_method
215    c = Class.new
216    c.class_eval do
217      def foo; :foo; end
218      private :foo
219    end
220    o = c.new
221    o.method(:foo).unbind
222    assert_raise(NoMethodError) { o.foo }
223    c.instance_method(:foo).bind(o)
224    assert_equal(:foo, o.instance_eval { foo })
225    assert_raise(NameError) { c.public_instance_method(:foo) }
226    def o.bar; end
227    m = o.method(:bar).unbind
228    assert_raise(TypeError) { m.bind(Object.new) }
229
230    feature4254 = '[ruby-core:34267]'
231    m = M.instance_method(:meth)
232    assert_equal(:meth, m.bind(Object.new).call, feature4254)
233  end
234
235  def test_define_method
236    c = Class.new
237    c.class_eval { def foo; :foo; end }
238    o = c.new
239    def o.bar; :bar; end
240    assert_raise(TypeError) do
241      c.class_eval { define_method(:foo, :foo) }
242    end
243    assert_raise(ArgumentError) do
244      c.class_eval { define_method }
245    end
246    c2 = Class.new(c)
247    c2.class_eval { define_method(:baz, o.method(:foo)) }
248    assert_equal(:foo, c2.new.baz)
249    assert_raise(TypeError) do
250      Class.new.class_eval { define_method(:foo, o.method(:foo)) }
251    end
252    assert_raise(TypeError) do
253      Class.new.class_eval { define_method(:bar, o.method(:bar)) }
254    end
255  end
256
257  def test_define_singleton_method
258    o = Object.new
259    def o.foo(c)
260      c.class_eval { define_method(:foo) }
261    end
262    c = Class.new
263    o.foo(c) { :foo }
264    assert_equal(:foo, c.new.foo)
265
266    o = Object.new
267    o.instance_eval { define_singleton_method(:foo) { :foo } }
268    assert_equal(:foo, o.foo)
269
270    assert_raise(TypeError) do
271      Class.new.class_eval { define_method(:foo, Object.new) }
272    end
273
274    assert_raise(TypeError) do
275      Module.new.module_eval {define_method(:foo, Base.instance_method(:foo))}
276    end
277  end
278
279  def test_define_singleton_method_with_extended_method
280    bug8686 = "[ruby-core:56174]"
281
282    m = Module.new do
283      extend self
284
285      def a
286        "a"
287      end
288    end
289
290    assert_nothing_raised do
291      m.define_singleton_method(:a, m.method(:a))
292    end
293  end
294
295  def test_define_method_transplating
296    feature4254 = '[ruby-core:34267]'
297    m = Module.new {define_method(:meth, M.instance_method(:meth))}
298    assert_equal(:meth, Object.new.extend(m).meth, feature4254)
299    c = Class.new {define_method(:meth, M.instance_method(:meth))}
300    assert_equal(:meth, c.new.meth, feature4254)
301  end
302
303  def test_super_in_proc_from_define_method
304    c1 = Class.new {
305      def m
306        :m1
307      end
308    }
309    c2 = Class.new(c1) { define_method(:m) { Proc.new { super() } } }
310    # c2.new.m.call should return :m1, but currently it raise NoMethodError.
311    # see [Bug #4881] and [Bug #3136]
312    assert_raise(NoMethodError) {
313      c2.new.m.call
314    }
315  end
316
317  def test_clone
318    o = Object.new
319    def o.foo; :foo; end
320    m = o.method(:foo)
321    def m.bar; :bar; end
322    assert_equal(:foo, m.clone.call)
323    assert_equal(:bar, m.clone.bar)
324  end
325
326  def test_call
327    o = Object.new
328    def o.foo; p 1; end
329    def o.bar(x); x; end
330    m = o.method(:foo)
331    m.taint
332    assert_raise(SecurityError) { m.call }
333  end
334
335  def test_inspect
336    o = Object.new
337    def o.foo; end
338    m = o.method(:foo)
339    assert_equal("#<Method: #{ o.inspect }.foo>", m.inspect)
340    m = o.method(:foo)
341    assert_equal("#<UnboundMethod: #{ class << o; self; end.inspect }#foo>", m.unbind.inspect)
342
343    c = Class.new
344    c.class_eval { def foo; end; }
345    m = c.new.method(:foo)
346    assert_equal("#<Method: #{ c.inspect }#foo>", m.inspect)
347    m = c.instance_method(:foo)
348    assert_equal("#<UnboundMethod: #{ c.inspect }#foo>", m.inspect)
349
350    c2 = Class.new(c)
351    c2.class_eval { private :foo }
352    m2 = c2.new.method(:foo)
353    assert_equal("#<Method: #{ c2.inspect }(#{ c.inspect })#foo>", m2.inspect)
354  end
355
356  def test_callee_top_level
357    assert_in_out_err([], "p __callee__", %w(nil), [])
358  end
359
360  def test_caller_top_level
361    assert_in_out_err([], "p caller", %w([]), [])
362  end
363
364  def test_caller_negative_level
365    assert_raise(ArgumentError) { caller(-1) }
366  end
367
368  def test_attrset_ivar
369    c = Class.new
370    c.class_eval { attr_accessor :foo }
371    o = c.new
372    o.method(:foo=).call(42)
373    assert_equal(42, o.foo)
374    assert_raise(ArgumentError) { o.method(:foo=).call(1, 2, 3) }
375    assert_raise(ArgumentError) { o.method(:foo).call(1) }
376  end
377
378  def test_default_accessibility
379    assert T.public_instance_methods.include?(:normal_method), 'normal methods are public by default'
380    assert !T.public_instance_methods.include?(:initialize), '#initialize is private'
381    assert !T.public_instance_methods.include?(:initialize_copy), '#initialize_copy is private'
382    assert !T.public_instance_methods.include?(:initialize_clone), '#initialize_clone is private'
383    assert !T.public_instance_methods.include?(:initialize_dup), '#initialize_dup is private'
384    assert !T.public_instance_methods.include?(:respond_to_missing?), '#respond_to_missing? is private'
385    assert !M.public_instance_methods.include?(:func), 'module methods are private by default'
386    assert M.public_instance_methods.include?(:meth), 'normal methods are public by default'
387  end
388
389  define_method(:pm0) {||}
390  define_method(:pm1) {|a|}
391  define_method(:pm2) {|a, b|}
392  define_method(:pmo1) {|a = nil, &b|}
393  define_method(:pmo2) {|a, b = nil|}
394  define_method(:pmo3) {|*a|}
395  define_method(:pmo4) {|a, *b, &c|}
396  define_method(:pmo5) {|a, *b, c|}
397  define_method(:pmo6) {|a, *b, c, &d|}
398  define_method(:pmo7) {|a, b = nil, *c, d, &e|}
399  define_method(:pma1) {|(a), &b|}
400
401  def test_bound_parameters
402    assert_equal([], method(:m0).parameters)
403    assert_equal([[:req, :a]], method(:m1).parameters)
404    assert_equal([[:req, :a], [:req, :b]], method(:m2).parameters)
405    assert_equal([[:opt, :a], [:block, :b]], method(:mo1).parameters)
406    assert_equal([[:req, :a], [:opt, :b]], method(:mo2).parameters)
407    assert_equal([[:rest, :a]], method(:mo3).parameters)
408    assert_equal([[:req, :a], [:rest, :b], [:block, :c]], method(:mo4).parameters)
409    assert_equal([[:req, :a], [:rest, :b], [:req, :c]], method(:mo5).parameters)
410    assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:mo6).parameters)
411    assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:mo7).parameters)
412    assert_equal([[:req], [:block, :b]], method(:ma1).parameters)
413  end
414
415  def test_unbound_parameters
416    assert_equal([], self.class.instance_method(:m0).parameters)
417    assert_equal([[:req, :a]], self.class.instance_method(:m1).parameters)
418    assert_equal([[:req, :a], [:req, :b]], self.class.instance_method(:m2).parameters)
419    assert_equal([[:opt, :a], [:block, :b]], self.class.instance_method(:mo1).parameters)
420    assert_equal([[:req, :a], [:opt, :b]], self.class.instance_method(:mo2).parameters)
421    assert_equal([[:rest, :a]], self.class.instance_method(:mo3).parameters)
422    assert_equal([[:req, :a], [:rest, :b], [:block, :c]], self.class.instance_method(:mo4).parameters)
423    assert_equal([[:req, :a], [:rest, :b], [:req, :c]], self.class.instance_method(:mo5).parameters)
424    assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], self.class.instance_method(:mo6).parameters)
425    assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:mo7).parameters)
426    assert_equal([[:req], [:block, :b]], self.class.instance_method(:ma1).parameters)
427  end
428
429  def test_bmethod_bound_parameters
430    assert_equal([], method(:pm0).parameters)
431    assert_equal([[:req, :a]], method(:pm1).parameters)
432    assert_equal([[:req, :a], [:req, :b]], method(:pm2).parameters)
433    assert_equal([[:opt, :a], [:block, :b]], method(:pmo1).parameters)
434    assert_equal([[:req, :a], [:opt, :b]], method(:pmo2).parameters)
435    assert_equal([[:rest, :a]], method(:pmo3).parameters)
436    assert_equal([[:req, :a], [:rest, :b], [:block, :c]], method(:pmo4).parameters)
437    assert_equal([[:req, :a], [:rest, :b], [:req, :c]], method(:pmo5).parameters)
438    assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:pmo6).parameters)
439    assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:pmo7).parameters)
440    assert_equal([[:req], [:block, :b]], method(:pma1).parameters)
441  end
442
443  def test_bmethod_unbound_parameters
444    assert_equal([], self.class.instance_method(:pm0).parameters)
445    assert_equal([[:req, :a]], self.class.instance_method(:pm1).parameters)
446    assert_equal([[:req, :a], [:req, :b]], self.class.instance_method(:pm2).parameters)
447    assert_equal([[:opt, :a], [:block, :b]], self.class.instance_method(:pmo1).parameters)
448    assert_equal([[:req, :a], [:opt, :b]], self.class.instance_method(:pmo2).parameters)
449    assert_equal([[:rest, :a]], self.class.instance_method(:pmo3).parameters)
450    assert_equal([[:req, :a], [:rest, :b], [:block, :c]], self.class.instance_method(:pmo4).parameters)
451    assert_equal([[:req, :a], [:rest, :b], [:req, :c]], self.class.instance_method(:pmo5).parameters)
452    assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], self.class.instance_method(:pmo6).parameters)
453    assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:pmo7).parameters)
454    assert_equal([[:req], [:block, :b]], self.class.instance_method(:pma1).parameters)
455  end
456
457  def test_public_method_with_zsuper_method
458    c = Class.new
459    c.class_eval do
460      def foo
461        :ok
462      end
463      private :foo
464    end
465    d = Class.new(c)
466    d.class_eval do
467      public :foo
468    end
469    assert_equal(:ok, d.new.public_method(:foo).call)
470  end
471
472  def test_public_methods_with_extended
473    m = Module.new do def m1; end end
474    a = Class.new do def a; end end
475    bug = '[ruby-dev:41553]'
476    obj = a.new
477    assert_equal([:a], obj.public_methods(false), bug)
478    obj.extend(m)
479    assert_equal([:m1, :a], obj.public_methods(false), bug)
480  end
481
482  def test_visibility
483    assert_equal('method', defined?(mv1))
484    assert_equal('method', defined?(mv2))
485    assert_equal('method', defined?(mv3))
486
487    assert_equal('method', defined?(self.mv1))
488    assert_equal(nil,      defined?(self.mv2))
489    assert_equal('method', defined?(self.mv3))
490
491    assert_equal(true,  respond_to?(:mv1))
492    assert_equal(false, respond_to?(:mv2))
493    assert_equal(false, respond_to?(:mv3))
494
495    assert_equal(true,  respond_to?(:mv1, true))
496    assert_equal(true,  respond_to?(:mv2, true))
497    assert_equal(true,  respond_to?(:mv3, true))
498
499    assert_nothing_raised { mv1 }
500    assert_nothing_raised { mv2 }
501    assert_nothing_raised { mv3 }
502
503    assert_nothing_raised { self.mv1 }
504    assert_raise(NoMethodError) { self.mv2 }
505    assert_nothing_raised { self.mv3 }
506
507    v = Visibility.new
508
509    assert_equal('method', defined?(v.mv1))
510    assert_equal(nil,      defined?(v.mv2))
511    assert_equal(nil,      defined?(v.mv3))
512
513    assert_equal(true,  v.respond_to?(:mv1))
514    assert_equal(false, v.respond_to?(:mv2))
515    assert_equal(false, v.respond_to?(:mv3))
516
517    assert_equal(true,  v.respond_to?(:mv1, true))
518    assert_equal(true,  v.respond_to?(:mv2, true))
519    assert_equal(true,  v.respond_to?(:mv3, true))
520
521    assert_nothing_raised { v.mv1 }
522    assert_raise(NoMethodError) { v.mv2 }
523    assert_raise(NoMethodError) { v.mv3 }
524
525    assert_nothing_raised { v.__send__(:mv1) }
526    assert_nothing_raised { v.__send__(:mv2) }
527    assert_nothing_raised { v.__send__(:mv3) }
528
529    assert_nothing_raised { v.instance_eval { mv1 } }
530    assert_nothing_raised { v.instance_eval { mv2 } }
531    assert_nothing_raised { v.instance_eval { mv3 } }
532  end
533
534  def test_bound_method_entry
535    bug6171 = '[ruby-core:43383]'
536    assert_ruby_status([], <<-EOC, bug6171)
537      class Bug6171
538        def initialize(target)
539          define_singleton_method(:reverse, target.method(:reverse).to_proc)
540        end
541      end
542      100.times {p = Bug6171.new('test'); 1000.times {p.reverse}}
543      EOC
544  end
545
546  def test___dir__
547    assert_instance_of String, __dir__
548    assert_equal(File.dirname(File.realpath(__FILE__)), __dir__)
549    bug8436 = '[ruby-core:55123] [Bug #8436]'
550    assert_equal(__dir__, eval("__dir__", binding), bug8436)
551    bug8662 = '[ruby-core:56099] [Bug #8662]'
552    assert_equal("arbitrary", eval("__dir__", binding, "arbitrary/file.rb"), bug8662)
553    assert_equal("arbitrary", Object.new.instance_eval("__dir__", "arbitrary/file.rb"), bug8662)
554  end
555
556  def test_alias_owner
557    bug7613 = '[ruby-core:51105]'
558    bug7993 = '[Bug #7993]'
559    c = Class.new {
560      def foo
561      end
562      prepend Module.new
563      attr_reader :zot
564    }
565    x = c.new
566    class << x
567      alias bar foo
568    end
569    assert_equal(c, c.instance_method(:foo).owner)
570    assert_equal(c, x.method(:foo).owner)
571    assert_equal(x.singleton_class, x.method(:bar).owner)
572    assert(x.method(:foo) != x.method(:bar), bug7613)
573    assert_equal(c, x.method(:zot).owner, bug7993)
574    assert_equal(c, c.instance_method(:zot).owner, bug7993)
575  end
576
577  def test_gced_bmethod
578    assert_normal_exit %q{
579      require 'irb'
580      IRB::Irb.module_eval do
581        define_method(:eval_input) do
582          IRB::Irb.module_eval { alias_method :eval_input, :to_s }
583          GC.start
584          Kernel
585        end
586      end
587      IRB.start
588    }, '[Bug #7825]'
589  end
590
591  def test_unlinked_method_entry_in_method_object_bug
592    bug8100 = '[ruby-core:53640] [Bug #8100]'
593    assert_ruby_status [], %q{
594      loop do
595        def x
596          "hello" * 1000
597        end
598        method(:x).call
599      end
600    }, bug8100, timeout: 2
601  rescue Timeout::Error
602  end
603end
604