aboutsummaryrefslogtreecommitdiffstats
path: root/spec/ruby/core/module/alias_method_spec.rb
blob: 662e91011ffddd553fd651b2f23e311abd28018a (plain)
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'

describe "Module#alias_method" do
  before :each do
    @class = Class.new(ModuleSpecs::Aliasing)
    @object = @class.new
  end

  it "makes a copy of the method" do
    @class.make_alias :uno, :public_one
    @class.make_alias :double, :public_two
    @object.uno.should == @object.public_one
    @object.double(12).should == @object.public_two(12)
  end

  it "creates methods that are == to each other" do
    @class.make_alias :uno, :public_one
    @object.method(:uno).should == @object.method(:public_one)
  end

  it "preserves the arguments information of the original methods" do
    @class.make_alias :uno, :public_one
    @class.make_alias :double, :public_two
    @class.instance_method(:uno).parameters.should == @class.instance_method(:public_one).parameters
    @class.instance_method(:double).parameters.should == @class.instance_method(:public_two).parameters
  end

  it "retains method visibility" do
    @class.make_alias :private_ichi, :private_one
    -> { @object.private_one  }.should raise_error(NameError)
    -> { @object.private_ichi }.should raise_error(NameError)
    @class.make_alias :public_ichi, :public_one
    @object.public_ichi.should == @object.public_one
    @class.make_alias :protected_ichi, :protected_one
    -> { @object.protected_ichi }.should raise_error(NameError)
  end

  it "handles aliasing a stub that changes visibility" do
    @class.__send__ :public, :private_one
    @class.make_alias :was_private_one, :private_one
    @object.was_private_one.should == 1
  end

  it "fails if origin method not found" do
    -> { @class.make_alias :ni, :san }.should raise_error(NameError) { |e|
      # a NameError and not a NoMethodError
      e.class.should == NameError
    }
  end

  it "raises #{frozen_error_class} if frozen" do
    @class.freeze
    -> { @class.make_alias :uno, :public_one }.should raise_error(frozen_error_class)
  end

  it "converts the names using #to_str" do
    @class.make_alias "un", "public_one"
    @class.make_alias :deux, "public_one"
    @class.make_alias "trois", :public_one
    @class.make_alias :quatre, :public_one
    name = mock('cinq')
    name.should_receive(:to_str).any_number_of_times.and_return("cinq")
    @class.make_alias name, "public_one"
    @class.make_alias "cinq", name
  end

  it "raises a TypeError when the given name can't be converted using to_str" do
    -> { @class.make_alias mock('x'), :public_one }.should raise_error(TypeError)
  end

  ruby_version_is ''...'2.5' do
    it "is a private method" do
      -> { @class.alias_method :ichi, :public_one }.should raise_error(NoMethodError)
    end
  end
  ruby_version_is '2.5' do
    it "is a public method" do
      Module.should have_public_instance_method(:alias_method, false)
    end
  end

  it "returns self" do
    @class.send(:alias_method, :checking_return_value, :public_one).should equal(@class)
  end

  it "works in module" do
    ModuleSpecs::Allonym.new.publish.should == :report
  end

  it "works on private module methods in a module that has been reopened" do
    ModuleSpecs::ReopeningModule.foo.should == true
    -> { ModuleSpecs::ReopeningModule.foo2 }.should_not raise_error(NoMethodError)
  end

  it "accesses a method defined on Object from Kernel" do
    Kernel.should_not have_public_instance_method(:module_specs_public_method_on_object)

    Kernel.should have_public_instance_method(:module_specs_alias_on_kernel)
    Object.should have_public_instance_method(:module_specs_alias_on_kernel)
  end

  it "can call a method with super aliased twice" do
    ModuleSpecs::AliasingSuper::Target.new.super_call(1).should == 1
  end

  it "preserves original super call after alias redefine" do
    ModuleSpecs::AliasingSuper::RedefineAfterAlias.new.alias_super_call(1).should == 1
  end

  describe "aliasing special methods" do
    before :all do
      @class = ModuleSpecs::Aliasing
      @subclass = ModuleSpecs::AliasingSubclass
    end

    it "keeps initialize private when aliasing" do
      @class.make_alias(:initialize, :public_one)
      @class.private_instance_methods.include?(:initialize).should be_true

      @subclass.make_alias(:initialize, :public_one)
      @subclass.private_instance_methods.include?(:initialize).should be_true
    end

    it "keeps initialize_copy private when aliasing" do
      @class.make_alias(:initialize_copy, :public_one)
      @class.private_instance_methods.include?(:initialize_copy).should be_true

      @subclass.make_alias(:initialize_copy, :public_one)
      @subclass.private_instance_methods.include?(:initialize_copy).should be_true
    end

    it "keeps initialize_clone private when aliasing" do
      @class.make_alias(:initialize_clone, :public_one)
      @class.private_instance_methods.include?(:initialize_clone).should be_true

      @subclass.make_alias(:initialize_clone, :public_one)
      @subclass.private_instance_methods.include?(:initialize_clone).should be_true
    end

    it "keeps initialize_dup private when aliasing" do
      @class.make_alias(:initialize_dup, :public_one)
      @class.private_instance_methods.include?(:initialize_dup).should be_true

      @subclass.make_alias(:initialize_dup, :public_one)
      @subclass.private_instance_methods.include?(:initialize_dup).should be_true
    end

    it "keeps respond_to_missing? private when aliasing" do
      @class.make_alias(:respond_to_missing?, :public_one)
      @class.private_instance_methods.include?(:respond_to_missing?).should be_true

      @subclass.make_alias(:respond_to_missing?, :public_one)
      @subclass.private_instance_methods.include?(:respond_to_missing?).should be_true
    end
  end
end