1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'minitest/autorun'
require 'rgen/util/method_delegation'
class MethodDelegationTest < Minitest::Test
include RGen
class TestDelegate
attr_accessor :mode, :callcount
def common_delegated(delegator)
@callcount ||= 0
@callcount += 1
case @mode
when :continue
throw :continue
when :delegatorId
delegator.object_id
when :return7
7
end
end
alias to_s_delegated common_delegated
alias methodInSingleton_delegated common_delegated
alias class_delegated common_delegated
alias artificialMethod_delegated common_delegated
end
class ConstPathElement < Module
def self.const_missing_delegated(delegator, const)
ConstPathElement.new(const)
end
def initialize(name, parent=nil)
@name = name.to_s
@parent = parent
end
def const_missing(const)
ConstPathElement.new(const, self)
end
def to_s
if @parent
@parent.to_s+"::"+@name
else
@name
end
end
end
# missing: check with multiple params and block param
def test_method_defined_in_singleton
# delegator is an Array
delegator = []
# delegating method is a method defined in the singleton class
class << delegator
def methodInSingleton
"result from method in singleton"
end
end
checkDelegation(delegator, "methodInSingleton", "result from method in singleton")
end
def test_method_defined_in_class
# delegator is a String
delegator = "Delegator1"
checkDelegation(delegator, "to_s", "Delegator1")
end
def test_method_defined_in_superclass
# delegator is an instance of a new anonymous class
delegator = Class.new.new
# delegating method is +object_id+ which is defined in the superclass
checkDelegation(delegator, "class", delegator.class)
end
def test_new_method
# delegator is an String
delegator = "Delegator2"
# delegating method is a new method which does not exist on String
checkDelegation(delegator, "artificialMethod", delegator.object_id, true)
end
def test_const_missing
surroundingModule = Module.nesting.first
Util::MethodDelegation.registerDelegate(ConstPathElement, surroundingModule, "const_missing")
assert_equal "SomeArbitraryConst", SomeArbitraryConst.to_s
assert_equal "AnotherConst::A::B::C", AnotherConst::A::B::C.to_s
Util::MethodDelegation.unregisterDelegate(ConstPathElement, surroundingModule, "const_missing")
assert_raises NameError do
SomeArbitraryConst
end
end
def checkDelegation(delegator, method, originalResult, newMethod=false)
delegate1 = TestDelegate.new
delegate2 = TestDelegate.new
Util::MethodDelegation.registerDelegate(delegate1, delegator, method)
Util::MethodDelegation.registerDelegate(delegate2, delegator, method)
assert delegator.respond_to?(:_methodDelegates)
if newMethod
assert !delegator.respond_to?("#{method}_delegate_original".to_sym)
else
assert delegator.respond_to?("#{method}_delegate_original".to_sym)
end
# check delegator parameter
delegate1.mode = :delegatorId
assert_equal delegator.object_id, delegator.send(method)
delegate1.callcount = 0
delegate2.callcount = 0
delegate1.mode = :return7
# delegate1 returns a value
assert_equal 7, delegator.send(method)
assert_equal 1, delegate1.callcount
# delegate2 is not called
assert_equal 0, delegate2.callcount
delegate1.mode = :nothing
# delegate1 just exits and thus returns nil
assert_nil delegator.send(method)
assert_equal 2, delegate1.callcount
# delegate2 is not called
assert_equal 0, delegate2.callcount
delegate1.mode = :continue
delegate2.mode = :return7
# delegate1 is called but continues
# delegate2 returns a value
assert_equal 7, delegator.send(method)
assert_equal 3, delegate1.callcount
assert_equal 1, delegate2.callcount
delegate1.mode = :continue
delegate2.mode = :continue
# both delegates continue, the original method returns its value
checkCallOriginal(delegator, method, originalResult, newMethod)
# both delegates are called though
assert_equal 4, delegate1.callcount
assert_equal 2, delegate2.callcount
# calling unregister with a non existing method has no effect
Util::MethodDelegation.unregisterDelegate(delegate1, delegator, "xxx")
Util::MethodDelegation.unregisterDelegate(delegate1, delegator, method)
checkCallOriginal(delegator, method, originalResult, newMethod)
# delegate1 not called any more
assert_equal 4, delegate1.callcount
# delegate2 is still called
assert_equal 3, delegate2.callcount
Util::MethodDelegation.unregisterDelegate(delegate2, delegator, method)
checkCallOriginal(delegator, method, originalResult, newMethod)
# both delegates not called any more
assert_equal 4, delegate1.callcount
assert_equal 3, delegate2.callcount
# after all delegates were unregistered, singleton class should be clean
assert !delegator.respond_to?(:_methodDelegates)
end
def checkCallOriginal(delegator, method, originalResult, newMethod)
if newMethod
assert_raises NoMethodError do
result = delegator.send(method)
end
else
result = delegator.send(method)
assert_equal originalResult, result
end
end
end
|