1require 'test/unit'
2require_relative 'envutil'
3
4class TestSuper < Test::Unit::TestCase
5  class Base
6    def single(a) a end
7    def double(a, b) [a,b] end
8    def array(*a) a end
9    def optional(a = 0) a end
10    def keyword(**a) a end
11  end
12  class Single1 < Base
13    def single(*) super end
14  end
15  class Single2 < Base
16    def single(a,*) super end
17  end
18  class Double1 < Base
19    def double(*) super end
20  end
21  class Double2 < Base
22    def double(a,*) super end
23  end
24  class Double3 < Base
25    def double(a,b,*) super end
26  end
27  class Array1 < Base
28    def array(*) super end
29  end
30  class Array2 < Base
31    def array(a,*) super end
32  end
33  class Array3 < Base
34    def array(a,b,*) super end
35  end
36  class Array4 < Base
37    def array(a,b,c,*) super end
38  end
39  class Optional1 < Base
40    def optional(a = 1) super end
41  end
42  class Optional2 < Base
43    def optional(a, b = 1) super end
44  end
45  class Optional3 < Base
46    def single(a = 1) super end
47  end
48  class Optional4 < Base
49    def array(a = 1, *) super end
50  end
51  class Optional5 < Base
52    def array(a = 1, b = 2, *) super end
53  end
54  class Keyword1 < Base
55    def keyword(foo: "keyword1") super end
56  end
57  class Keyword2 < Base
58    def keyword(foo: "keyword2")
59      foo = "changed1"
60      x = super
61      foo = "changed2"
62      y = super
63      [x, y]
64    end
65  end
66
67  def test_single1
68    assert_equal(1, Single1.new.single(1))
69  end
70  def test_single2
71    assert_equal(1, Single2.new.single(1))
72  end
73  def test_double1
74    assert_equal([1, 2], Double1.new.double(1, 2))
75  end
76  def test_double2
77    assert_equal([1, 2], Double2.new.double(1, 2))
78  end
79  def test_double3
80    assert_equal([1, 2], Double3.new.double(1, 2))
81  end
82  def test_array1
83    assert_equal([], Array1.new.array())
84    assert_equal([1], Array1.new.array(1))
85  end
86  def test_array2
87    assert_equal([1], Array2.new.array(1))
88    assert_equal([1,2], Array2.new.array(1, 2))
89  end
90  def test_array3
91    assert_equal([1,2], Array3.new.array(1, 2))
92    assert_equal([1,2,3], Array3.new.array(1, 2, 3))
93  end
94  def test_array4
95    assert_equal([1,2,3], Array4.new.array(1, 2, 3))
96    assert_equal([1,2,3,4], Array4.new.array(1, 2, 3, 4))
97  end
98  def test_optional1
99    assert_equal(9, Optional1.new.optional(9))
100    assert_equal(1, Optional1.new.optional)
101  end
102  def test_optional2
103    assert_raise(ArgumentError) do
104      # call Base#optional with 2 arguments; the 2nd arg is supplied
105      assert_equal(9, Optional2.new.optional(9))
106    end
107    assert_raise(ArgumentError) do
108      # call Base#optional with 2 arguments
109      assert_equal(9, Optional2.new.optional(9, 2))
110    end
111  end
112  def test_optional3
113    assert_equal(9, Optional3.new.single(9))
114    # call Base#single with 1 argument; the arg is supplied
115    assert_equal(1, Optional3.new.single)
116  end
117  def test_optional4
118    assert_equal([1], Optional4.new.array)
119    assert_equal([9], Optional4.new.array(9))
120    assert_equal([9, 8], Optional4.new.array(9, 8))
121  end
122  def test_optional5
123    assert_equal([1, 2], Optional5.new.array)
124    assert_equal([9, 2], Optional5.new.array(9))
125    assert_equal([9, 8], Optional5.new.array(9, 8))
126    assert_equal([9, 8, 7], Optional5.new.array(9, 8, 7))
127  end
128  def test_keyword1
129    assert_equal({foo: "keyword1"}, Keyword1.new.keyword)
130    bug8008 = '[ruby-core:53114] [Bug #8008]'
131    assert_equal({foo: bug8008}, Keyword1.new.keyword(foo: bug8008))
132  end
133  def test_keyword2
134    assert_equal([{foo: "changed1"}, {foo: "changed2"}], Keyword2.new.keyword)
135  end
136
137  class A
138    def tt(aa)
139      "A#tt"
140    end
141
142    def uu(a)
143      class << self
144        define_method(:tt) do |sym|
145          super(sym)
146        end
147      end
148    end
149  end
150
151  def test_define_method
152    a = A.new
153    a.uu(12)
154    assert_equal("A#tt", a.tt(12), "[ruby-core:3856]")
155    e = assert_raise(RuntimeError, "[ruby-core:24244]") {
156      lambda {
157        Class.new {
158          define_method(:a) {super}
159        }.new.a
160      }.call
161    }
162    assert_match(/implicit argument passing of super from method defined by define_method/, e.message)
163  end
164
165  class SubSeq
166    def initialize
167      @first=11
168      @first or fail
169    end
170
171    def subseq
172      @first or fail
173    end
174  end
175
176  class Indexed
177    def subseq
178      SubSeq.new
179    end
180  end
181
182  Overlaid = proc do
183    class << self
184      def subseq
185        super.instance_eval(& Overlaid)
186      end
187    end
188  end
189
190  def test_overlaid
191    assert_nothing_raised('[ruby-dev:40959]') do
192      overlaid = proc do |obj|
193        def obj.reverse
194          super
195        end
196      end
197      overlaid.call(str = "123")
198      overlaid.call(ary = [1,2,3])
199      str.reverse
200    end
201
202    assert_nothing_raised('[ruby-core:27230]') do
203      mid=Indexed.new
204      mid.instance_eval(&Overlaid)
205      mid.subseq
206      mid.subseq
207    end
208  end
209
210  module DoubleInclude
211    class Base
212      def foo
213        [:Base]
214      end
215    end
216
217    module Override
218      def foo
219        super << :Override
220      end
221    end
222
223    class A < Base
224    end
225
226    class B < A
227    end
228
229    B.send(:include, Override)
230    A.send(:include, Override)
231  end
232
233  # [Bug #3351]
234  def test_double_include
235    assert_equal([:Base, :Override], DoubleInclude::B.new.foo)
236    # should be changed as follows?
237    # assert_equal([:Base, :Override, :Override], DoubleInclude::B.new.foo)
238  end
239
240  module DoubleInclude2
241    class Base
242      def foo
243        [:Base]
244      end
245    end
246
247    module Override
248      def foo
249        super << :Override
250      end
251    end
252
253    class A < Base
254      def foo
255        super << :A
256      end
257    end
258
259    class B < A
260      def foo
261        super << :B
262      end
263    end
264
265    B.send(:include, Override)
266    A.send(:include, Override)
267  end
268
269  def test_double_include2
270    assert_equal([:Base, :Override, :A, :Override, :B],
271                 DoubleInclude2::B.new.foo)
272  end
273
274  def test_super_in_instance_eval
275    super_class = Class.new {
276      def foo
277        return [:super, self]
278      end
279    }
280    sub_class = Class.new(super_class) {
281      def foo
282        x = Object.new
283        x.instance_eval do
284          super()
285        end
286      end
287    }
288    obj = sub_class.new
289    assert_raise(TypeError) do
290      obj.foo
291    end
292  end
293
294  def test_super_in_instance_eval_with_define_method
295    super_class = Class.new {
296      def foo
297        return [:super, self]
298      end
299    }
300    sub_class = Class.new(super_class) {
301      define_method(:foo) do
302        x = Object.new
303        x.instance_eval do
304          super()
305        end
306      end
307    }
308    obj = sub_class.new
309    assert_raise(TypeError) do
310      obj.foo
311    end
312  end
313
314  def test_super_in_orphan_block
315    super_class = Class.new {
316      def foo
317        return [:super, self]
318      end
319    }
320    sub_class = Class.new(super_class) {
321      def foo
322        x = Object.new
323        lambda { super() }
324      end
325    }
326    obj = sub_class.new
327    assert_equal([:super, obj], obj.foo.call)
328  end
329
330  def test_super_in_orphan_block_with_instance_eval
331    super_class = Class.new {
332      def foo
333        return [:super, self]
334      end
335    }
336    sub_class = Class.new(super_class) {
337      def foo
338        x = Object.new
339        x.instance_eval do
340          lambda { super() }
341        end
342      end
343    }
344    obj = sub_class.new
345    assert_raise(TypeError) do
346      obj.foo.call
347    end
348  end
349
350  def test_yielding_super
351    a = Class.new { def yielder; yield; end }
352    x = Class.new { define_singleton_method(:hello) { 'hi' } }
353    y = Class.new(x) {
354      define_singleton_method(:hello) {
355        m = a.new
356        m.yielder { super() }
357      }
358    }
359    assert_equal 'hi', y.hello
360  end
361
362  def test_super_in_thread
363    hoge = Class.new {
364      def bar; 'hoge'; end
365    }
366    foo = Class.new(hoge) {
367      def bar; Thread.new { super }.join.value; end
368    }
369
370    assert_equal 'hoge', foo.new.bar
371  end
372
373  def assert_super_in_block(type)
374    bug7064 = '[ruby-core:47680]'
375    assert_normal_exit "#{type} {super}", bug7064
376  end
377
378  def test_super_in_at_exit
379    assert_super_in_block("at_exit")
380  end
381  def test_super_in_END
382    assert_super_in_block("END")
383  end
384
385  def test_super_in_BEGIN
386    assert_super_in_block("BEGIN")
387  end
388
389  class X
390    def foo(*args)
391      args
392    end
393  end
394
395  class Y < X
396    define_method(:foo) do |*args|
397      super(*args)
398    end
399  end
400
401  def test_super_splat
402    # [ruby-list:49575] 
403    y = Y.new
404    assert_equal([1, 2], y.foo(1, 2))
405    assert_equal([1, false], y.foo(1, false))
406    assert_equal([1, 2, 3, 4, 5], y.foo(1, 2, 3, 4, 5))
407    assert_equal([false, true], y.foo(false, true))
408    assert_equal([false, false], y.foo(false, false))
409    assert_equal([1, 2, 3, false, 5], y.foo(1, 2, 3, false, 5))
410  end
411
412  def test_missing_super_in_method_module
413    bug9315 = '[ruby-core:59358] [Bug #9315]'
414    a = Module.new do
415      def foo
416        super
417      end
418    end
419    b = Class.new do
420      include a
421    end
422    assert_raise(NoMethodError, bug9315) do
423      b.new.method(:foo).call
424    end
425  end
426
427  def test_module_super_in_method_module
428    bug9315 = '[ruby-core:59589] [Bug #9315]'
429    a = Module.new do
430      def foo
431        super
432      end
433    end
434    c = Class.new do
435      def foo
436        :ok
437      end
438    end
439    o = c.new.extend(a)
440    assert_nothing_raised(NoMethodError, bug9315) do
441      assert_equal(:ok, o.method(:foo).call, bug9315)
442    end
443  end
444
445  def test_missing_super_in_module_unbound_method
446    bug9377 = '[ruby-core:59619] [Bug #9377]'
447
448    a = Module.new do
449      def foo; super end
450    end
451
452    m = a.instance_method(:foo).bind(Object.new.extend(a))
453    assert_raise(NoMethodError, bug9377) do
454      m.call
455    end
456  end
457end
458