1 # frozen_string_literal: false
5 class TestForwardable < Test::Unit::TestCase
7 RECEIVER = BasicObject.new
8 RETURNED1 = BasicObject.new
9 RETURNED2 = BasicObject.new
20 def delegated1_kw(**kw)
25 def test_def_instance_delegator
26 %i[def_delegator def_instance_delegator].each do |m|
28 cls = forwardable_class do
29 ret = __send__ m, :@receiver, :delegated1
32 assert_same RETURNED1, cls.new.delegated1
33 assert_equal :delegated1, ret
37 def test_def_instance_delegator_constant
38 %i[def_delegator def_instance_delegator].each do |m|
39 cls = forwardable_class do
40 __send__ m, 'TestForwardable::INTEGER', :to_i
43 assert_equal 42, cls.new.to_i
47 def test_def_instance_delegator_kw
48 %i[def_delegator def_instance_delegator].each do |m|
49 cls = forwardable_class do
50 __send__ m, :@receiver, :delegated1_kw
53 ary = cls.new.delegated1_kw b: 1
54 assert_same RETURNED1, ary[0]
55 assert_equal({b: 1}, ary[1])
59 def test_def_instance_delegator_using_args_method_as_receiver
60 %i[def_delegator def_instance_delegator].each do |m|
61 cls = forwardable_class(
66 __send__ m, :args, :delegated1
69 assert_same RETURNED1, cls.new.delegated1
73 def test_def_instance_delegator_using_block_method_as_receiver
74 %i[def_delegator def_instance_delegator].each do |m|
75 cls = forwardable_class(
76 receiver_name: :block,
80 __send__ m, :block, :delegated1
83 assert_same RETURNED1, cls.new.delegated1
87 def test_def_instance_delegators
88 %i[def_delegators def_instance_delegators].each do |m|
89 cls = forwardable_class do
90 __send__ m, :@receiver, :delegated1, :delegated2
93 assert_same RETURNED1, cls.new.delegated1
94 assert_same RETURNED2, cls.new.delegated2
98 def test_def_instance_delegators_using_args_method_as_receiver
99 %i[def_delegators def_instance_delegators].each do |m|
100 cls = forwardable_class(
101 receiver_name: :args,
105 __send__ m, :args, :delegated1, :delegated2
108 assert_same RETURNED1, cls.new.delegated1
109 assert_same RETURNED2, cls.new.delegated2
113 def test_def_instance_delegators_using_block_method_as_receiver
114 %i[def_delegators def_instance_delegators].each do |m|
115 cls = forwardable_class(
116 receiver_name: :block,
120 __send__ m, :block, :delegated1, :delegated2
123 assert_same RETURNED1, cls.new.delegated1
124 assert_same RETURNED2, cls.new.delegated2
128 def test_def_instance_delegators_send_id
129 %i[def_delegators def_instance_delegators].each do |m|
130 cls = forwardable_class do
131 attr_reader :receiver
132 __send__ m, :@receiver, :__send__, :__id__
135 assert_not_equal cls.new.__id__, cls.new.receiver.__id__
136 assert_not_equal cls.new.__send__(:__id__), cls.new.receiver.__send__(:__id__)
140 def test_instance_delegate
141 %i[delegate instance_delegate].each do |m|
142 cls = forwardable_class do
143 __send__ m, delegated1: :@receiver, delegated2: :@receiver
146 assert_same RETURNED1, cls.new.delegated1
147 assert_same RETURNED2, cls.new.delegated2
149 cls = forwardable_class do
150 __send__ m, %i[delegated1 delegated2] => :@receiver
153 assert_same RETURNED1, cls.new.delegated1
154 assert_same RETURNED2, cls.new.delegated2
158 def test_def_instance_delegate_using_args_method_as_receiver
159 %i[delegate instance_delegate].each do |m|
160 cls = forwardable_class(
161 receiver_name: :args,
165 __send__ m, delegated1: :args, delegated2: :args
168 assert_same RETURNED1, cls.new.delegated1
169 assert_same RETURNED2, cls.new.delegated2
173 def test_def_instance_delegate_using_block_method_as_receiver
174 %i[delegate instance_delegate].each do |m|
175 cls = forwardable_class(
176 receiver_name: :block,
180 __send__ m, delegated1: :block, delegated2: :block
183 assert_same RETURNED1, cls.new.delegated1
184 assert_same RETURNED2, cls.new.delegated2
188 def test_class_single_delegator
189 %i[def_delegator def_single_delegator].each do |m|
191 cls = single_forwardable_class do
192 ret = __send__ m, :@receiver, :delegated1
195 assert_same RETURNED1, cls.delegated1
196 assert_equal :delegated1, ret
200 def test_class_single_delegators
201 %i[def_delegators def_single_delegators].each do |m|
202 cls = single_forwardable_class do
203 __send__ m, :@receiver, :delegated1, :delegated2
206 assert_same RETURNED1, cls.delegated1
207 assert_same RETURNED2, cls.delegated2
211 def test_class_single_delegate
212 %i[delegate single_delegate].each do |m|
213 cls = single_forwardable_class do
214 __send__ m, delegated1: :@receiver, delegated2: :@receiver
217 assert_same RETURNED1, cls.delegated1
218 assert_same RETURNED2, cls.delegated2
220 cls = single_forwardable_class do
221 __send__ m, %i[delegated1 delegated2] => :@receiver
224 assert_same RETURNED1, cls.delegated1
225 assert_same RETURNED2, cls.delegated2
229 def test_obj_single_delegator
230 %i[def_delegator def_single_delegator].each do |m|
231 obj = single_forwardable_object do
232 __send__ m, :@receiver, :delegated1
235 assert_same RETURNED1, obj.delegated1
239 def test_obj_single_delegators
240 %i[def_delegators def_single_delegators].each do |m|
241 obj = single_forwardable_object do
242 __send__ m, :@receiver, :delegated1, :delegated2
245 assert_same RETURNED1, obj.delegated1
246 assert_same RETURNED2, obj.delegated2
250 def test_obj_single_delegators_send_id
251 %i[def_delegators def_single_delegators].each do |m|
252 obj = single_forwardable_object do
253 singleton_class.__send__ :attr_reader, :receiver
254 __send__ m, :@receiver, :__send__, :__id__
257 assert_not_equal obj.__id__, obj.receiver.__id__
258 assert_not_equal obj.__send__(:__id__), obj.receiver.__send__(:__id__)
262 def test_obj_single_delegate
263 %i[delegate single_delegate].each do |m|
264 obj = single_forwardable_object do
265 __send__ m, delegated1: :@receiver, delegated2: :@receiver
268 assert_same RETURNED1, obj.delegated1
269 assert_same RETURNED2, obj.delegated2
271 obj = single_forwardable_object do
272 __send__ m, %i[delegated1 delegated2] => :@receiver
275 assert_same RETURNED1, obj.delegated1
276 assert_same RETURNED2, obj.delegated2
284 def_delegator :bar, :baz
285 def_delegator :caller, :itself, :c
288 def test_backtrace_adjustment
290 def (obj.bar = Object.new).baz
293 e = assert_raise(NameError) {
296 assert_not_match(/\/forwardable\.rb/, e.backtrace[0],
297 proc {RubyVM::InstructionSequence.of(obj.method(:baz)).disassemble})
298 assert_equal(caller(0, 1)[0], Foo.new.c[0])
301 class Foo2 < BasicObject
304 def_delegator :bar, :baz
307 def test_basicobject_subclass
308 bug11616 = '[ruby-core:71176] [Bug #11616]'
309 assert_raise_with_message(NameError, /[`']bar'/, bug11616) {
315 obj = Object.new.extend SingleForwardable
316 obj.instance_variable_set("@h", {foo: 42})
317 obj.def_delegator("@h", :[])
318 assert_equal(42, obj[:foo])
322 obj = Object.new.extend SingleForwardable
323 obj.instance_variable_set("@h", h = {foo: 0})
324 obj.def_delegator("@h", :[]=)
326 assert_equal(42, h[:foo])
330 obj = Object.new.extend SingleForwardable
331 obj.instance_variable_set("@h", 40)
332 obj.def_delegator("@h", :+)
333 assert_equal(42, obj+2)
337 obj = Object.new.extend SingleForwardable
338 obj.instance_variable_set("@h", -42)
339 obj.def_delegator("@h", :-@)
340 assert_equal(42, -obj)
343 def test_on_private_method
345 private def foo; :foo end
347 def_delegator :itself, :foo, :bar
349 assert_warn(/forwarding to private method/) do
350 assert_equal(:foo, cls.new.bar)
356 str.extend Forwardable
357 str.instance_variable_set("@h", 42)
358 str.def_delegator("@h", :to_s, :forty_two)
359 assert_equal("42", str.forty_two)
364 def forwardable_class(
365 receiver_name: :receiver,
373 define_method(:initialize) do
374 instance_variable_set("@#{receiver_name}", RECEIVER)
378 attr_reader(receiver_name)
379 __send__(visibility, receiver_name)
386 def single_forwardable_class(&block)
388 extend SingleForwardable
396 def single_forwardable_object(&block)
397 obj = Object.new.extend SingleForwardable
398 obj.instance_variable_set(:@receiver, RECEIVER)
399 obj.instance_eval(&block)