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
|
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Module#method_added" do
before :each do
ScratchPad.record []
end
it "is a private instance method" do
Module.should have_private_instance_method(:method_added)
end
it "returns nil in the default implementation" do
Module.new do
method_added(:test).should == nil
end
end
it "is called when a new instance method is defined in self" do
Module.new do
def self.method_added(name)
ScratchPad << name
end
def test() end
def test2() end
def test() end
alias_method :aliased_test, :test
alias aliased_test2 test
end
ScratchPad.recorded.should == [:test, :test2, :test, :aliased_test, :aliased_test2]
end
it "is not called when a singleton method is added" do
# obj.singleton_method_added is called instead
klass = Class.new
def klass.method_added(name)
ScratchPad << name
end
obj = klass.new
def obj.new_singleton_method
end
ScratchPad.recorded.should == []
end
it "is not called when a method is undefined in self" do
m = Module.new do
def method_to_undef
end
def self.method_added(name)
fail("method_added called by undef_method")
end
undef_method :method_to_undef
end
m.should_not have_method(:method_to_undef)
end
it "is not called when a method changes visibility" do
Module.new do
def public_method
end
def private_method
end
def self.method_added(name)
ScratchPad << name
end
public :public_method
private :public_method
private :private_method
public :private_method
end
ScratchPad.recorded.should == []
end
it "is called when using #private in a subclass" do
parent = Class.new do
def foo
end
end
Class.new(parent) do
def self.method_added(name)
ScratchPad << name
end
# Create an instance as that might initialize some method lookup caches, which is interesting to test
self.new.foo
private :foo
public :foo
end
ScratchPad.recorded.should == [:foo]
end
it "is not called when a method is copied via module_function, rather #singleton_method_added is called" do
Module.new do
def mod_function
end
def self.method_added(name)
ScratchPad << [:method_added, name]
end
def self.singleton_method_added(name)
ScratchPad << [:singleton_method_added, name]
end
ScratchPad.record []
module_function :mod_function
end
ScratchPad.recorded.should == [[:singleton_method_added, :mod_function]]
end
it "is called with a precise caller location with the line of the 'def'" do
line = nil
Module.new do
def self.method_added(name)
location = caller_locations(1, 1)[0]
ScratchPad << location.lineno
end
line = __LINE__
def first
end
def second
end
end
ScratchPad.recorded.should == [line + 1, line + 4]
end
end
|