641979d716563509954eac9c43f9d6ba0dafed5f
[platform/upstream/nghttp2.git] / third-party / mruby / mrbgems / mruby-method / test / method.rb
1 class Base
2   def foo() :base end
3 end
4
5 class Derived < Base
6   def foo() :derived end
7 end
8
9 class Interpreter
10   attr_accessor :ret
11
12   def do_a() @ret += "there, "; end
13   def do_d() @ret += "Hello ";  end
14   def do_e() @ret += "!\n";     end
15   def do_v() @ret += "Dave";    end
16   Dispatcher = {
17     "a" => instance_method(:do_a),
18     "d" => instance_method(:do_d),
19     "e" => instance_method(:do_e),
20     "v" => instance_method(:do_v)
21   }
22   def interpret(string)
23     @ret = ""
24     string.split("").each {|b| Dispatcher[b].bind(self).call }
25   end
26 end
27
28 assert 'demo' do
29   interpreter = Interpreter.new
30   interpreter.interpret('dave')
31   assert_equal "Hello there, Dave!\n", interpreter.ret
32 end
33
34 assert 'Method#arity' do
35   Class.new {
36     attr_accessor :done
37     def initialize; @done = false; end
38     def m0() end
39     def m1(a) end
40     def m2(a, b) end
41     def mo1(a = nil, &b) end
42     def mo2(a, b = nil) end
43     def mo3(*a) end
44     def mo4(a, *b, &c) end
45     def mo5(a, *b, c) end
46     def mo6(a, *b, c, &d) end
47     def mo7(a, b = nil, *c, d, &e) end
48     def ma1((a), &b) nil && a end
49
50     def run
51       assert_equal(0, method(:m0).arity)
52       assert_equal(1, method(:m1).arity)
53       assert_equal(2, method(:m2).arity)
54       assert_equal(-1, method(:mo1).arity)
55       assert_equal(-2, method(:mo2).arity)
56       assert_equal(-1, method(:mo3).arity)
57       assert_equal(-2, method(:mo4).arity)
58       assert_equal(-3, method(:mo5).arity)
59       assert_equal(-3, method(:mo6).arity)
60       assert_equal(-3, method(:mo7).arity)
61       assert_equal(1, method(:ma1).arity)
62
63       assert_equal(-1, method(:__send__).arity)
64       assert_equal(-1, method(:nothing).arity)
65     end
66
67     def respond_to_missing?(m, b)
68       m == :nothing
69     end
70   }.new.run
71 end
72
73 assert 'Method and UnboundMethod should not be have a `new` method' do
74   assert_raise(NoMethodError){ Method.new }
75   assert_raise(NoMethodError){ UnboundMethod.new }
76 end
77
78 assert 'instance' do
79   assert_kind_of Method, 1.method(:+)
80   assert_kind_of UnboundMethod, Fixnum.instance_method(:+)
81 end
82
83 assert 'Method#call' do
84   assert_equal 3, 1.method(:+).call(2)
85   assert_equal "ab", "a".method(:+)["b"]
86   klass = Class.new {
87     def foo; 42; end
88   }
89   klass2 = Class.new(klass) {
90     def foo; super; end
91   }
92   assert_equal 42, klass2.new.method(:foo).call
93
94   i = Class.new {
95    def bar
96      yield 3
97    end
98   }.new
99   assert_raise(LocalJumpError) { i.method(:bar).call }
100   assert_equal 3, i.method(:bar).call { |i| i }
101 end
102
103 assert 'Method#call for regression' do
104   obj = BasicObject.new
105   assert_equal String, Kernel.instance_method(:inspect).bind(obj).call().class, "https://github.com/ksss/mruby-method/issues/4"
106 end
107
108 assert 'Method#call with undefined method' do
109   c = Class.new {
110     attr_accessor :m, :argv
111     def respond_to_missing?(m, b)
112       m == :foo
113     end
114
115     def method_missing(m, *argv)
116       @m = m
117       @argv = argv
118       super
119     end
120   }
121   cc = c.new
122   assert_raise(NameError) { cc.method(:nothing) }
123   assert_kind_of Method, cc.method(:foo)
124   assert_raise(NoMethodError) { cc.method(:foo).call(:arg1, :arg2) }
125   assert_equal :foo, cc.m
126   assert_equal [:arg1, :arg2], cc.argv
127
128   cc = c.new
129   m = cc.method(:foo)
130   c.class_eval do
131     def foo
132       :ng
133     end
134   end
135   assert_raise(NoMethodError) { m.call(:arg1, :arg2) }
136 end
137
138 assert 'Method#source_location' do
139   skip if proc{}.source_location.nil?
140
141   filename = __FILE__
142   klass = Class.new
143
144   lineno = __LINE__ + 1
145   klass.define_method(:find_me_if_you_can) {}
146   assert_equal [filename, lineno], klass.new.method(:find_me_if_you_can).source_location
147
148   lineno = __LINE__ + 1
149   class <<klass; define_method(:s_find_me_if_you_can) {}; end
150   assert_equal [filename, lineno], klass.method(:s_find_me_if_you_can).source_location
151
152   klass = Class.new { def respond_to_missing?(m, b); m == :nothing; end }
153   assert_nil klass.new.method(:nothing).source_location
154 end
155
156 assert 'UnboundMethod#source_location' do
157   skip if proc{}.source_location.nil?
158
159   filename = __FILE__
160   klass = Class.new {
161     def respond_to_missing?(m, b)
162       m == :nothing
163     end
164   }
165
166   lineno = __LINE__ + 1
167   klass.define_method(:find_me_if_you_can) {}
168   assert_equal [filename, lineno], klass.instance_method(:find_me_if_you_can).source_location
169   assert_nil klass.new.method(:nothing).unbind.source_location
170 end
171
172 assert 'Method#parameters' do
173   klass = Class.new {
174     def foo(a, b=nil, *c) end
175     def respond_to_missing?(m, b)
176       m == :missing
177     end
178   }
179   assert_equal [[:req, :a], [:opt, :b], [:rest, :c]], klass.new.method(:foo).parameters
180   assert_equal [[:rest]], klass.new.method(:missing).parameters
181 end
182
183 assert 'UnboundMethod#parameters' do
184   klass = Class.new {
185     def foo(a, b=nil, *c) end
186     def respond_to_missing?(m, b)
187       m == :nothing
188     end
189   }
190   assert_equal [[:req, :a], [:opt, :b], [:rest, :c]], klass.instance_method(:foo).parameters
191   assert_equal [[:rest]], klass.new.method(:nothing).unbind.parameters
192 end
193
194 assert 'Method#to_proc' do
195   m = 3.method(:+)
196   assert_kind_of Proc, m.to_proc
197   assert_equal 7, m.call(4)
198
199   o = Object.new
200   def o.foo(a, b=nil, *c)
201     [a, b, c]
202   end
203   assert_equal [:bar, nil, []], o.method(:foo).to_proc.call(:bar)
204 #  We can fix this issue but leave until the problem
205 #  assert_equal o.method(:foo).arity, o.method(:foo).to_proc.arity
206
207   def o.bar
208     yield 39
209   end
210   assert_equal 42, o.bar(&3.method(:+))
211 end
212
213 assert 'to_s' do
214   o = Object.new
215   def o.foo; end
216   m = o.method(:foo)
217   assert_equal("#<UnboundMethod: #{ class << o; self; end.inspect }#foo>", m.unbind.inspect)
218
219   c = Class.new
220   c.class_eval { def foo; end; }
221   m = c.new.method(:foo)
222   assert_equal("#<Method: #{ c.inspect }#foo>", m.inspect)
223   m = c.instance_method(:foo)
224   assert_equal("#<UnboundMethod: #{ c.inspect }#foo>", m.inspect)
225 end
226
227 assert 'owner' do
228   c = Class.new do
229     def foo; end
230     def self.bar; end
231   end
232   m = Module.new do
233     def baz; end
234   end
235   c.include(m)
236   c2 = Class.new(c)
237
238   assert_equal(c, c.instance_method(:foo).owner)
239   assert_equal(c, c2.instance_method(:foo).owner)
240
241   assert_equal(c, c.new.method(:foo).owner)
242   assert_equal(c, c2.new.method(:foo).owner)
243   assert_equal((class <<c; self; end), c2.method(:bar).owner)
244 end
245
246 assert 'owner missing' do
247   c = Class.new do
248     def respond_to_missing?(name, bool)
249       name == :foo
250     end
251   end
252   c2 = Class.new(c)
253   assert_equal(c, c.new.method(:foo).owner)
254   assert_equal(c2, c2.new.method(:foo).owner)
255 end
256
257 assert 'receiver name owner' do
258   o = Object.new
259   def o.foo; end
260   m = o.method(:foo)
261   assert_equal(o, m.receiver)
262   assert_equal(:foo, m.name)
263   assert_equal(class << o; self; end, m.owner)
264   assert_equal(:foo, m.unbind.name)
265   assert_equal(class << o; self; end, m.unbind.owner)
266 end
267
268 assert 'Method#unbind' do
269   assert_equal(:derived, Derived.new.foo)
270   um = Derived.new.method(:foo).unbind
271   assert_kind_of(UnboundMethod, um)
272   Derived.class_eval do
273     def foo() :changed end
274   end
275   assert_equal(:changed, Derived.new.foo)
276   assert_equal(:changed, Derived.new.foo{})
277   assert_equal(:derived, um.bind(Derived.new).call)
278   assert_raise(TypeError) do
279     um.bind(Base.new)
280   end
281
282   # TODO:
283   #  Block passed method not handled correctly with workaround.
284   #  See comment near `mrb_funcall_with_block` for detail.
285   # assert_equal(:derived, um.bind(Derived.new).call{})
286 end
287
288 assert 'Kernel#method' do
289   c1 = Class.new {
290     def foo; :foo; end
291   }
292   o = c1.new
293   assert_kind_of Method, o.method(:foo)
294   assert_kind_of Method, o.method('foo')
295   assert_raise(TypeError) { o.method(nil) }
296   assert_raise(NameError) { o.method('bar') }
297   assert_raise(NameError) { o.method(:bar) }
298 end
299
300 assert "Module#instance_method" do
301   assert_kind_of UnboundMethod, Object.instance_method(:object_id)
302   assert_raise(NameError) { Object.instance_method(:nothing) }
303   c = Class.new {
304     def respond_to_missing?(m, b)
305       false
306     end
307   }
308   assert_raise(NameError) { c.instance_method(:nothing) }
309 end
310
311 assert 'Kernel#singleton_method' do
312   c1 = Class.new {
313     def foo; :foo; end
314   }
315   o = c1.new
316   def o.bar; :bar; end
317   assert_kind_of Method, o.method(:foo)
318   assert_raise(NameError) { o.singleton_method(:foo) }
319   assert_kind_of Method, o.singleton_method(:bar)
320   assert_raise(TypeError) { o.singleton_method(nil) }
321   m = assert_nothing_raised(NameError) { break o.singleton_method(:bar) }
322   assert_equal(:bar, m.call)
323 end
324
325 assert 'Method#super_method' do
326   o = Derived.new
327   m = o.method(:foo).super_method
328   assert_equal(Base, m.owner)
329   assert_true(o.equal? m.receiver)
330   assert_equal(:foo, m.name)
331   assert_nil(m.super_method)
332
333   c = Class.new {
334     def foo; end
335   }
336   o = c.new
337   o.extend Module.new {
338     def foo; end
339   }
340   assert_equal c, o.method(:foo).super_method.owner
341   assert_equal :foo, o.method(:foo).super_method.name
342   assert_equal o, o.method(:foo).super_method.receiver
343 end
344
345 assert 'Method#==' do
346   o = Object.new
347   class << o
348     def foo; end
349   end
350   assert_not_equal(o.method(:foo), nil)
351   m = o.method(:foo)
352   def m.foo; end
353   # TODO: assert_not_equal(o.method(:foo), m)
354   assert_equal(o.method(:foo), o.method(:foo))
355   # TODO: assert_false(o.method(:foo).eql? m)
356   assert_true(o.method(:foo).eql? o.method(:foo))
357
358   assert_false(0.method(:+) == 1.method(:+))
359   assert_false(0.method(:+) == 0.method(:-))
360   a = 0.method(:+)
361   assert_true(a.method(:==) == a.method(:eql?))
362 end
363
364 assert "Method#initialize_copy" do
365   c = Class.new {
366     def foo
367     end
368   }.new
369   m1 = c.method(:foo)
370   m2 = m1.clone
371   assert_equal(m1, m2)
372 end
373
374 assert "Method#<< and Method#>>" do
375   obj = Object.new
376   class << obj
377     def mul2(n); n * 2; end
378     def add3(n); n + 3; end
379   end
380
381   f = obj.method(:mul2)
382   g = obj.method(:add3)
383
384   m1 = f << g
385   assert_kind_of Proc, m1
386   assert_equal 16, m1.call(5)
387
388   m2 = f >> g
389   assert_kind_of Proc, m2
390   assert_equal 13, m2.call(5)
391 end
392
393 assert 'UnboundMethod#arity' do
394   c = Class.new {
395     def foo(a, b)
396     end
397
398     def respond_to_missing?(m, b)
399       m == :nothing
400     end
401   }
402   assert_equal 2, c.instance_method(:foo).arity
403   assert_equal(-1, c.new.method(:nothing).unbind.arity)
404 end
405
406 assert 'UnboundMethod#==' do
407   assert_false(Fixnum.instance_method(:+) == Fixnum.instance_method(:-))
408   assert_true(Fixnum.instance_method(:+) == Fixnum.instance_method(:+))
409   assert_false(Fixnum.instance_method(:+) == Float.instance_method(:+))
410   assert_true(UnboundMethod.instance_method(:==) == UnboundMethod.instance_method(:eql?))
411 end
412
413 assert 'UnboundMethod#super_method' do
414   m = Derived.instance_method(:foo)
415   m = m.super_method
416   assert_equal(Base.instance_method(:foo), m)
417   assert_nil(m.super_method)
418
419   m = Object.instance_method(:object_id)
420   assert_nil(m.super_method)
421 end
422
423 assert 'UnboundMethod#bind' do
424   m = Module.new{ def meth() :meth end }.instance_method(:meth)
425   assert_raise(ArgumentError) { m.bind }
426   assert_kind_of Method, m.bind(1)
427   assert_kind_of Method, m.bind(:sym)
428   assert_kind_of Method, m.bind(Object.new)
429   assert_equal(:meth, m.bind(1).call)
430   assert_equal(:meth, m.bind(:sym).call)
431   assert_equal(:meth, m.bind(Object.new).call)
432   sc = nil
433   Class.new {
434     sc = class << self
435       def foo
436       end
437       self
438     end
439   }
440   assert_raise(TypeError) { sc.instance_method(:foo).bind([]) }
441   assert_raise(TypeError) { Array.instance_method(:each).bind(1) }
442   assert_kind_of Method, Object.instance_method(:object_id).bind(Object.new)
443 end
444
445 assert 'UnboundMethod#bind_call' do
446   m = Array.instance_method(:size)
447   assert_equal(:size, m.name)
448   assert_equal(0, m.bind_call([]))
449   assert_equal(1, m.bind_call([1]))
450   assert_equal(2, m.bind_call([1,2]))
451 end