* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / test_delegate.rb
blob57480b18ea674cfb240c369a38c63ebb915504d5
1 # frozen_string_literal: true
2 require 'test/unit'
3 require 'delegate'
5 class TestDelegateClass < Test::Unit::TestCase
6   module PP
7     def mu_pp(obj)
8       str = super
9       str = "#<#{obj.class}: #{str}>" if Delegator === obj
10       str
11     end
12   end
14   module M
15     attr_reader :m
16   end
18   def test_extend
19     obj = DelegateClass(Array).new([])
20     obj.instance_eval { @m = :m }
21     obj.extend M
22     assert_equal(:m, obj.m, "[ruby-dev:33116]")
23   end
25   def test_delegate_class_block
26     klass = DelegateClass(Array) do
27       alias foo first
28     end
29     assert_equal(1, klass.new([1]).foo)
30   end
32   def test_systemcallerror_eq
33     e = SystemCallError.new(0)
34     assert((SimpleDelegator.new(e) == e) == (e == SimpleDelegator.new(e)), "[ruby-dev:34808]")
35   end
37   class Myclass < DelegateClass(Array);end
39   def test_delegateclass_class
40     myclass=Myclass.new([])
41     assert_equal(Myclass,myclass.class)
42     assert_equal(Myclass,myclass.dup.class,'[ruby-dev:40313]')
43     assert_equal(Myclass,myclass.clone.class,'[ruby-dev:40313]')
44   end
46   def test_simpledelegator_class
47     simple=SimpleDelegator.new([])
48     assert_equal(SimpleDelegator,simple.class)
49     assert_equal(SimpleDelegator,simple.dup.class)
50     assert_equal(SimpleDelegator,simple.clone.class)
51   end
53   def test_simpledelegator_clone
54     simple=SimpleDelegator.new([])
55     simple.freeze
57     clone = simple.clone
58     assert_predicate clone, :frozen?
59     assert_predicate clone.__getobj__, :frozen?
60     assert_equal true, Kernel.instance_method(:frozen?).bind(clone).call
62     clone = simple.clone(freeze: false)
63     assert_not_predicate clone, :frozen?
64     assert_not_predicate clone.__getobj__, :frozen?
65     assert_equal false, Kernel.instance_method(:frozen?).bind(clone).call
66   end
68   class Object
69     def m
70       :o
71     end
72     private
73     def delegate_test_m
74       :o
75     end
76   end
78   class Foo
79     def m
80       :m
81     end
82     def delegate_test_m
83       :m
84     end
85   end
87   class Bar < DelegateClass(Foo)
88   end
90   def test_override
91     foo = Foo.new
92     foo2 = SimpleDelegator.new(foo)
93     bar = Bar.new(foo)
94     assert_equal(:o, Object.new.m)
95     assert_equal(:m, foo.m)
96     assert_equal(:m, foo2.m)
97     assert_equal(:m, bar.m)
98     bug = '[ruby-dev:39154]'
99     assert_equal(:m, foo2.send(:delegate_test_m), bug)
100     assert_equal(:m, bar.send(:delegate_test_m), bug)
101   end
103   class Parent
104     def parent_public; end
106     protected
108     def parent_protected; end
110     private
112     def parent_private; end
113   end
115   class Child < DelegateClass(Parent)
116   end
118   class Parent
119     def parent_public_added; end
121     protected
123     def parent_protected_added; end
125     private
127     def parent_private_added; end
128   end
130   def test_public_instance_methods
131     ignores = Object.public_instance_methods | Delegator.public_instance_methods
132     assert_equal([:parent_public, :parent_public_added], (Child.public_instance_methods - ignores).sort)
133     assert_equal([:parent_public, :parent_public_added], (Child.new(Parent.new).public_methods - ignores).sort)
134   end
136   def test_protected_instance_methods
137     ignores = Object.protected_instance_methods | Delegator.protected_instance_methods
138     assert_equal([:parent_protected, :parent_protected_added], (Child.protected_instance_methods - ignores).sort)
139     assert_equal([:parent_protected, :parent_protected_added], (Child.new(Parent.new).protected_methods - ignores).sort)
140   end
142   def test_instance_methods
143     ignores = Object.instance_methods | Delegator.instance_methods
144     assert_equal([:parent_protected, :parent_protected_added, :parent_public, :parent_public_added], (Child.instance_methods - ignores).sort)
145     assert_equal([:parent_protected, :parent_protected_added, :parent_public, :parent_public_added], (Child.new(Parent.new).methods - ignores).sort)
146   end
148   def test_DelegateClass_instance_method
149     assert_instance_of UnboundMethod, Child.instance_method(:parent_public)
150     assert_instance_of UnboundMethod, Child.instance_method(:parent_public_added)
151     assert_instance_of UnboundMethod, Child.instance_method(:parent_protected)
152     assert_instance_of UnboundMethod, Child.instance_method(:parent_protected_added)
153     assert_raise(NameError) { Child.instance_method(:parent_private) }
154     assert_raise(NameError) { Child.instance_method(:parent_private_added) }
155     assert_instance_of UnboundMethod, Child.instance_method(:to_s)
156   end
158   def test_DelegateClass_public_instance_method
159     assert_instance_of UnboundMethod, Child.public_instance_method(:parent_public)
160     assert_instance_of UnboundMethod, Child.public_instance_method(:parent_public_added)
161     assert_raise(NameError) { Child.public_instance_method(:parent_protected) }
162     assert_raise(NameError) { Child.public_instance_method(:parent_protected_added) }
163     assert_raise(NameError) { Child.instance_method(:parent_private) }
164     assert_raise(NameError) { Child.instance_method(:parent_private_added) }
165     assert_instance_of UnboundMethod, Child.public_instance_method(:to_s)
166   end
168   class IV < DelegateClass(Integer)
169     attr_accessor :var
171     def initialize
172       @var = 1
173       super(0)
174     end
175   end
177   def test_marshal
178     bug1744 = '[ruby-core:24211]'
179     c = IV.new
180     assert_equal(1, c.var)
181     d = Marshal.load(Marshal.dump(c))
182     assert_equal(1, d.var, bug1744)
183   end
185   def test_copy_frozen
186     bug2679 = '[ruby-dev:40242]'
187     a = [42, :hello].freeze
188     d = SimpleDelegator.new(a)
189     assert_nothing_raised(bug2679) {d.dup[0] += 1}
190     assert_raise(FrozenError) {d.clone[0] += 1}
191     d.freeze
192     assert(d.clone.frozen?)
193     assert(!d.dup.frozen?)
194   end
196   def test_frozen
197     d = SimpleDelegator.new([1, :foo])
198     d.freeze
199     assert_raise(FrozenError, '[ruby-dev:40314]#1') {d.__setobj__("foo")}
200     assert_equal([1, :foo], d)
201   end
203   def test_instance_method
204     s = SimpleDelegator.new("foo")
205     m = s.method("upcase")
206     s.__setobj__([1,2,3])
207     assert_raise(NoMethodError, '[ruby-dev:40314]#3') {m.call}
208   end
210   def test_methods
211     s = SimpleDelegator.new("foo")
212     assert_equal([], s.methods(false))
213     def s.bar; end
214     assert_equal([:bar], s.methods(false))
215   end
217   def test_eql?
218     extend PP
219     s0 = SimpleDelegator.new("foo")
220     s1 = SimpleDelegator.new("bar")
221     s2 = SimpleDelegator.new("foo")
222     assert_operator(s0, :eql?, s0)
223     assert_operator(s0, :eql?, "foo")
224     assert_operator(s0, :eql?, s2)
225     assert_not_operator(s0, :eql?, s1)
226     assert_not_operator(s0, :eql?, "bar")
227   end
229   def test_keyword_and_hash
230     foo = Object.new
231     def foo.bar(*args)
232       args
233     end
234     def foo.foo(*args, **kw)
235       [args, kw]
236     end
237     d = SimpleDelegator.new(foo)
238     assert_equal([[], {}], d.foo)
239     assert_equal([], d.bar)
240     assert_equal([[], {:a=>1}], d.foo(:a=>1))
241     assert_equal([{:a=>1}], d.bar(:a=>1))
242     assert_equal([[{:a=>1}], {}], d.foo({:a=>1}))
243     assert_equal([{:a=>1}], d.bar({:a=>1}))
244   end
246   class Foo
247     private
248     def delegate_test_private
249       :m
250     end
251   end
253   def test_private_method
254     foo = Foo.new
255     d = SimpleDelegator.new(foo)
256     assert_raise(NoMethodError) {foo.delegate_test_private}
257     assert_equal(:m, foo.send(:delegate_test_private))
258     assert_raise(NoMethodError, '[ruby-dev:40314]#4') {d.delegate_test_private}
259     assert_raise(NoMethodError, '[ruby-dev:40314]#5') {d.send(:delegate_test_private)}
260   end
262   def test_global_function
263     klass = Class.new do
264       def open
265       end
266     end
267     obj = klass.new
268     d = SimpleDelegator.new(obj)
269     assert_nothing_raised(ArgumentError) {obj.open}
270     assert_nothing_raised(ArgumentError) {d.open}
271     assert_nothing_raised(ArgumentError) {d.send(:open)}
272   end
274   def test_send_method_in_delegator
275     d = Class.new(SimpleDelegator) do
276       def foo
277         "foo"
278       end
279     end.new(Object.new)
280     assert_equal("foo", d.send(:foo))
281   end
283   def test_unset_simple_delegator
284     d = SimpleDelegator.allocate
285     assert_raise_with_message(ArgumentError, /not delegated/) {
286       d.__getobj__
287     }
288   end
290   def test_unset_delegate_class
291     d = IV.allocate
292     assert_raise_with_message(ArgumentError, /not delegated/) {
293       d.__getobj__
294     }
295   end
297   class Bug9155 < DelegateClass(Integer)
298     def initialize(value)
299       super(Integer(value))
300     end
301   end
303   def test_global_method_if_no_target
304     bug9155 = '[ruby-core:58572] [Bug #9155]'
305     x = assert_nothing_raised(ArgumentError, bug9155) {break Bug9155.new(1)}
306     assert_equal(1, x.to_i, bug9155)
307   end
309   class Bug9403
310     Name = '[ruby-core:59718] [Bug #9403]'
311     SD = SimpleDelegator.new(new)
312     class << SD
313       def method_name
314         __method__
315       end
316       def callee_name
317         __callee__
318       end
319       alias aliased_name callee_name
320       def dir_name
321         __dir__
322       end
323     end
324     dc = DelegateClass(self)
325     dc.class_eval do
326       def method_name
327         __method__
328       end
329       def callee_name
330         __callee__
331       end
332       alias aliased_name callee_name
333       def dir_name
334         __dir__
335       end
336     end
337     DC = dc.new(new)
338   end
340   def test_method_in_simple_delegator
341     assert_equal(:method_name, Bug9403::SD.method_name, Bug9403::Name)
342   end
344   def test_callee_in_simple_delegator
345     assert_equal(:callee_name, Bug9403::SD.callee_name, Bug9403::Name)
346     assert_equal(:aliased_name, Bug9403::SD.aliased_name, Bug9403::Name)
347   end
349   def test_dir_in_simple_delegator
350     assert_equal(__dir__, Bug9403::SD.dir_name, Bug9403::Name)
351   end
353   def test_method_in_delegator_class
354     assert_equal(:method_name, Bug9403::DC.method_name, Bug9403::Name)
355   end
357   def test_callee_in_delegator_class
358     assert_equal(:callee_name, Bug9403::DC.callee_name, Bug9403::Name)
359     assert_equal(:aliased_name, Bug9403::DC.aliased_name, Bug9403::Name)
360   end
362   def test_dir_in_delegator_class
363     assert_equal(__dir__, Bug9403::DC.dir_name, Bug9403::Name)
364   end
366   def test_module_methods_vs_kernel_methods
367     delegate = SimpleDelegator.new(Object.new)
368     assert_raise(NoMethodError) do
369       delegate.constants
370     end
371   end
373   def test_basicobject
374     o = BasicObject.new
375     def o.bar; 1; end
376     delegate = SimpleDelegator.new(o)
377     assert_equal(1, delegate.bar)
378     assert_raise(NoMethodError, /undefined method `foo' for/) { delegate.foo }
379   end
381   def test_basicobject_respond_to
382     o = BasicObject.new
383     def o.bar
384       nil
385     end
387     def o.respond_to?(method, include_private=false)
388       return false if method == :bar
389       ::Kernel.instance_method(:respond_to?).bind_call(self, method, include_private)
390     end
391     delegate = SimpleDelegator.new(o)
392     refute delegate.respond_to?(:bar)
393   end
395   def test_keyword_argument
396     k = EnvUtil.labeled_class("Target") do
397       def test(a, k:) [a, k]; end
398     end
399     a = DelegateClass(k).new(k.new)
400     assert_equal([1, 0], a.test(1, k: 0))
401   end