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
|
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
context "Creating UnboundMethods" do
specify "there is no difference between Method#unbind and Module#instance_method" do
UnboundMethodSpecs::Methods.instance_method(:foo).should be_kind_of(UnboundMethod)
UnboundMethodSpecs::Methods.new.method(:foo).unbind.should be_kind_of(UnboundMethod)
end
end
describe "UnboundMethod#==" do
before :all do
@from_module = UnboundMethodSpecs::Methods.instance_method(:foo)
@from_unbind = UnboundMethodSpecs::Methods.new.method(:foo).unbind
@with_block = UnboundMethodSpecs::Methods.instance_method(:with_block)
@includee = UnboundMethodSpecs::Mod.instance_method(:from_mod)
@includer = UnboundMethodSpecs::Methods.instance_method(:from_mod)
@alias_1 = UnboundMethodSpecs::Methods.instance_method(:alias_1)
@alias_2 = UnboundMethodSpecs::Methods.instance_method(:alias_2)
@original_body = UnboundMethodSpecs::Methods.instance_method(:original_body)
@identical_body = UnboundMethodSpecs::Methods.instance_method(:identical_body)
@parent = UnboundMethodSpecs::Parent.instance_method(:foo)
@child1 = UnboundMethodSpecs::Child1.instance_method(:foo)
@child2 = UnboundMethodSpecs::Child2.instance_method(:foo)
@child1_alt = UnboundMethodSpecs::Child1.instance_method(:foo)
@discard_1 = UnboundMethodSpecs::Methods.instance_method(:discard_1)
@discard_2 = UnboundMethodSpecs::Methods.instance_method(:discard_2)
@method_one = UnboundMethodSpecs::Methods.instance_method(:one)
@method_two = UnboundMethodSpecs::Methods.instance_method(:two)
end
it "returns true if objects refer to the same method" do
(@from_module == @from_module).should == true
(@from_unbind == @from_unbind).should == true
(@from_module == @from_unbind).should == true
(@from_unbind == @from_module).should == true
(@with_block == @with_block).should == true
end
it "returns true if either is an alias for the other" do
(@from_module == @alias_1).should == true
(@alias_1 == @from_module).should == true
end
it "returns true if both are aliases for a third method" do
(@from_module == @alias_1).should == true
(@alias_1 == @from_module).should == true
(@from_module == @alias_2).should == true
(@alias_2 == @from_module).should == true
(@alias_1 == @alias_2).should == true
(@alias_2 == @alias_1).should == true
end
it "returns true if same method is extracted from the same subclass" do
(@child1 == @child1_alt).should == true
(@child1_alt == @child1).should == true
end
it "returns false if UnboundMethods are different methods" do
(@method_one == @method_two).should == false
(@method_two == @method_one).should == false
end
it "returns false if both have identical body but are not the same" do
(@original_body == @identical_body).should == false
(@identical_body == @original_body).should == false
end
ruby_version_is ""..."3.2" do
it "returns false if same method but one extracted from a subclass" do
(@parent == @child1).should == false
(@child1 == @parent).should == false
end
it "returns false if same method but extracted from two different subclasses" do
(@child2 == @child1).should == false
(@child1 == @child2).should == false
end
it "returns false if methods are the same but added from an included Module" do
(@includee == @includer).should == false
(@includer == @includee).should == false
end
end
ruby_version_is "3.2" do
it "returns true if same method but one extracted from a subclass" do
(@parent == @child1).should == true
(@child1 == @parent).should == true
end
it "returns false if same method but extracted from two different subclasses" do
(@child2 == @child1).should == true
(@child1 == @child2).should == true
end
it "returns true if methods are the same but added from an included Module" do
(@includee == @includer).should == true
(@includer == @includee).should == true
end
end
it "returns false if both have same Module, same name, identical body but not the same" do
class UnboundMethodSpecs::Methods
def discard_1; :discard; end
end
(@discard_1 == UnboundMethodSpecs::Methods.instance_method(:discard_1)).should == false
end
it "considers methods through aliasing equal" do
c = Class.new do
class << self
alias_method :n, :new
end
end
c.method(:new).should == c.method(:n)
c.method(:n).should == Class.instance_method(:new).bind(c)
end
# On CRuby < 3.2, the 2 specs below pass due to method/instance_method skipping zsuper methods.
# We are interested in the general pattern working, i.e. the combination of method/instance_method
# and #== exposes the wanted behavior.
it "considers methods through visibility change equal" do
c = Class.new do
class << self
private :new
end
end
c.method(:new).should == Class.instance_method(:new).bind(c)
end
it "considers methods through aliasing and visibility change equal" do
c = Class.new do
class << self
alias_method :n, :new
private :new
end
end
c.method(:new).should == c.method(:n)
c.method(:n).should == Class.instance_method(:new).bind(c)
c.method(:new).should == Class.instance_method(:new).bind(c)
end
end
|