aquarium 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +20 -0
- data/README +17 -0
- data/UPGRADE +5 -0
- data/lib/aquarium/aspects/advice.rb +10 -9
- data/lib/aquarium/aspects/aspect.rb +274 -199
- data/lib/aquarium/aspects/default_object_handler.rb +22 -10
- data/lib/aquarium/aspects/exclusion_handler.rb +61 -0
- data/lib/aquarium/aspects/join_point.rb +18 -17
- data/lib/aquarium/aspects/pointcut.rb +44 -49
- data/lib/aquarium/finders/method_finder.rb +1 -1
- data/lib/aquarium/finders/object_finder.rb +1 -0
- data/lib/aquarium/utils/method_utils.rb +49 -8
- data/lib/aquarium/version.rb +1 -1
- data/spec/aquarium/aspects/advice_chain_node_spec.rb +5 -3
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +1334 -31
- data/spec/aquarium/aspects/aspect_spec.rb +164 -426
- data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +18 -2
- data/spec/aquarium/aspects/join_point_spec.rb +46 -4
- data/spec/aquarium/aspects/pointcut_spec.rb +80 -39
- data/spec/aquarium/finders/method_finder_spec.rb +25 -2
- data/spec/aquarium/finders/type_finder_spec.rb +1 -1
- data/spec/aquarium/spec_example_classes.rb +17 -0
- data/spec/aquarium/utils/method_utils_spec.rb +270 -46
- metadata +4 -3
@@ -5,397 +5,8 @@ require 'aquarium/aspects'
|
|
5
5
|
|
6
6
|
include Aquarium::Aspects
|
7
7
|
|
8
|
-
# TODO Could refactor this whole file to use "behave_like", etc.
|
9
|
-
describe Aspect, "#new parameters that configure advice" do
|
10
|
-
it "should require the kind of advice as the first parameter." do
|
11
|
-
lambda {Aspect.new(:pointcuts => {:type => Watchful, :methods => :public_watchful_method}) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should at least one of :method(s), :pointcut(s), :type(s), or :object(s)." do
|
15
|
-
lambda {Aspect.new(:after) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should at least one of :pointcut(s), :type(s), or :object(s) unless :default_object => object is given." do
|
19
|
-
aspect = Aspect.new(:after, :default_object => Watchful.new, :methods => :public_watchful_method) {|jp, *args| true}
|
20
|
-
aspect.unadvise
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should not contain :pointcut(s) and either :type(s) or :object(s)." do
|
24
|
-
lambda {Aspect.new(:after, :pointcuts => {:type => Watchful, :methods => :public_watchful_method}, :type => Watchful, :methods => :public_watchful_method) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
|
25
|
-
lambda {Aspect.new(:after, :pointcuts => {:type => Watchful, :methods => :public_watchful_method}, :object => Watchful.new, :methods => :public_watchful_method) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should include an advice block or :advice => advice parameter." do
|
29
|
-
lambda {Aspect.new(:after, :type => Watchful, :methods => :public_watchful_method)}.should raise_error(Aquarium::Utils::InvalidOptions)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe Aspect, "#new :pointcut parameter with a hash of :type(s), :object(s), and/or :method(s)" do
|
34
|
-
it "should accept a {:type(s) => [T1, ...], :methods = [...]} hash, indicating the types and methods to advise." do
|
35
|
-
advice_called = false
|
36
|
-
aspect = Aspect.new :before, :pointcut => {:type => [Watchful], :methods => :public_watchful_method} do |jp, *args|
|
37
|
-
advice_called = true
|
38
|
-
jp.should_not == nil
|
39
|
-
args.size.should == 4
|
40
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
41
|
-
end
|
42
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
43
|
-
advice_called.should be_true
|
44
|
-
aspect.unadvise
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should accept a {:type(s) => T, :methods = [...]} hash, indicating the type and methods to advise." do
|
48
|
-
advice_called = false
|
49
|
-
aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_watchful_method} do |jp, *args|
|
50
|
-
advice_called = true
|
51
|
-
jp.should_not == nil
|
52
|
-
args.size.should == 4
|
53
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
54
|
-
end
|
55
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
56
|
-
advice_called.should be_true
|
57
|
-
aspect.unadvise
|
58
|
-
end
|
59
|
-
|
60
|
-
%w[public protected private].each do |protection|
|
61
|
-
it "should accept a {:type(s) => T, :methods = [...], :method_options =>[:instance, #{protection}]} hash, indicating the type and #{protection} instance methods to advise." do
|
62
|
-
advice_called = false
|
63
|
-
aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => /watchful_method/, :method_options =>[:instance, protection.intern]} do |jp, *args|
|
64
|
-
advice_called = true
|
65
|
-
jp.should_not == nil
|
66
|
-
args.size.should == 4
|
67
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
68
|
-
end
|
69
|
-
Watchful.new.method("#{protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
70
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
71
|
-
advice_called.should be_true
|
72
|
-
aspect.unadvise
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should accept a {:type(s) => T, :methods = [...], :method_options =>[:instance]} hash, indicating the type and (public) instance methods to advise." do
|
77
|
-
advice_called = false
|
78
|
-
aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_watchful_method} do |jp, *args|
|
79
|
-
advice_called = true
|
80
|
-
jp.should_not == nil
|
81
|
-
args.size.should == 4
|
82
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
83
|
-
end
|
84
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
85
|
-
advice_called.should be_true
|
86
|
-
aspect.unadvise
|
87
|
-
end
|
88
|
-
|
89
|
-
%w[public private].each do |protection|
|
90
|
-
it "should accept a {:type(s) => T, :methods = [...], :method_options =>[:class, :#{protection}]} hash, indicating the type and #{protection} class methods to advise." do
|
91
|
-
advice_called = false
|
92
|
-
aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => /class_watchful_method$/, :method_options =>[:class, protection.intern]} do |jp, *args|
|
93
|
-
advice_called = true
|
94
|
-
jp.should_not == nil
|
95
|
-
args.size.should == 4
|
96
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
97
|
-
end
|
98
|
-
Watchful.method("#{protection}_class_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
99
|
-
advice_called.should be_true
|
100
|
-
aspect.unadvise
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should accept a {:type(s) => T, :methods = [...], :method_options =>:class} hash, indicating the type and (public) class methods to advise." do
|
105
|
-
advice_called = false
|
106
|
-
aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_class_watchful_method, :method_options =>:class} do |jp, *args|
|
107
|
-
advice_called = true
|
108
|
-
jp.should_not == nil
|
109
|
-
args.size.should == 4
|
110
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
111
|
-
end
|
112
|
-
Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
113
|
-
advice_called.should be_true
|
114
|
-
aspect.unadvise
|
115
|
-
end
|
116
|
-
|
117
|
-
it "should accept a {:objects(s) => [O1, ...], :methods = [...]} hash, indicating the objects and methods to advise." do
|
118
|
-
watchful1 = Watchful.new
|
119
|
-
watchful2 = Watchful.new
|
120
|
-
advice_called = false
|
121
|
-
aspect = Aspect.new :before, :pointcut => {:objects => [watchful1, watchful2], :methods => :public_watchful_method} do |jp, *args|
|
122
|
-
advice_called = true
|
123
|
-
jp.should_not == nil
|
124
|
-
args.size.should == 4
|
125
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
126
|
-
end
|
127
|
-
watchful1.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
128
|
-
watchful2.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
129
|
-
advice_called.should be_true
|
130
|
-
aspect.unadvise
|
131
|
-
end
|
132
|
-
|
133
|
-
it "should accept a {:objects(s) => O, :methods = [...]} hash, indicating the objects and methods to advise." do
|
134
|
-
watchful = Watchful.new
|
135
|
-
advice_called = false
|
136
|
-
aspect = Aspect.new :before, :pointcut => {:objects => watchful, :methods => :public_watchful_method} do |jp, *args|
|
137
|
-
advice_called = true
|
138
|
-
jp.should_not == nil
|
139
|
-
args.size.should == 4
|
140
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
141
|
-
end
|
142
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
143
|
-
advice_called.should be_true
|
144
|
-
aspect.unadvise
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
describe Aspect, "#new :pointcut parameter with a PointCut object or an array of Pointcuts" do
|
149
|
-
it "should accept a single Pointcut object." do
|
150
|
-
advice_called = false
|
151
|
-
pointcut = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
|
152
|
-
aspect = Aspect.new :before, :pointcut => pointcut do |jp, *args|
|
153
|
-
advice_called = true
|
154
|
-
jp.should_not == nil
|
155
|
-
args.size.should == 4
|
156
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
157
|
-
end
|
158
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
159
|
-
advice_called.should be_true
|
160
|
-
aspect.unadvise
|
161
|
-
end
|
162
|
-
|
163
|
-
it "should accept an array of Pointcut objects." do
|
164
|
-
advice_called = 0
|
165
|
-
pointcut1 = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
|
166
|
-
pointcut2 = Pointcut.new :type => [Watchful], :methods => :public_class_watchful_method, :method_options => [:class]
|
167
|
-
aspect = Aspect.new :before, :pointcut => [pointcut1, pointcut2] do |jp, *args|
|
168
|
-
advice_called += 1
|
169
|
-
jp.should_not == nil
|
170
|
-
args.size.should == 4
|
171
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
172
|
-
end
|
173
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
174
|
-
Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
175
|
-
advice_called.should == 2
|
176
|
-
aspect.unadvise
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should treat an array of Pointcuts as if they are one Pointcut \"or'ed\" together." do
|
180
|
-
advice_called = 0
|
181
|
-
advice = Proc.new {|jp, *args|
|
182
|
-
advice_called += 1
|
183
|
-
jp.should_not == nil
|
184
|
-
args.size.should == 4
|
185
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
186
|
-
}
|
187
|
-
pointcut1 = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
|
188
|
-
pointcut2 = Pointcut.new :type => [Watchful], :methods => :public_class_watchful_method, :method_options => [:class]
|
189
|
-
pointcut12 = pointcut1.or pointcut2
|
190
|
-
aspect1 = Aspect.new :before, :pointcut => [pointcut1, pointcut2], :advice => advice
|
191
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
192
|
-
Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
193
|
-
advice_called.should == 2
|
194
|
-
aspect1.unadvise
|
195
|
-
advice_called = 0
|
196
|
-
aspect2 = Aspect.new :before, :pointcut => pointcut12, :advice => advice
|
197
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
198
|
-
Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
199
|
-
advice_called.should == 2
|
200
|
-
aspect2.unadvise
|
201
|
-
aspect1.join_points_matched.should eql(aspect2.join_points_matched)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
describe Aspect, "#new :type(s), :object(s), and :method(s) parameters" do
|
206
|
-
it "should accept :type(s) => [T1, ...] and :methods => [...] parameters indicating the types to advise." do
|
207
|
-
advice_called = false
|
208
|
-
aspect = Aspect.new :before, :types => [Watchful], :methods => :public_watchful_method do |jp, *args|
|
209
|
-
advice_called = true
|
210
|
-
jp.should_not == nil
|
211
|
-
args.size.should == 4
|
212
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
213
|
-
end
|
214
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
215
|
-
advice_called.should be_true
|
216
|
-
aspect.unadvise
|
217
|
-
end
|
218
|
-
|
219
|
-
it "should accept :type(s) => T and :methods => [...] parameters indicating the types to advise." do
|
220
|
-
advice_called = false
|
221
|
-
aspect = Aspect.new :before, :type => Watchful, :methods => :public_watchful_method do |jp, *args|
|
222
|
-
advice_called = true
|
223
|
-
jp.should_not == nil
|
224
|
-
args.size.should == 4
|
225
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
226
|
-
end
|
227
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
228
|
-
advice_called.should be_true
|
229
|
-
aspect.unadvise
|
230
|
-
end
|
231
|
-
|
232
|
-
it "should accept :type(s) => /regexp/ and :methods => [...] parameters indicating the types to advise." do
|
233
|
-
advice_called = false
|
234
|
-
aspect = Aspect.new :before, :type => /^Watchful/, :methods => :public_watchful_method do |jp, *args|
|
235
|
-
advice_called = true
|
236
|
-
jp.should_not == nil
|
237
|
-
args.size.should == 4
|
238
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
239
|
-
end
|
240
|
-
Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
241
|
-
advice_called.should be_true
|
242
|
-
aspect.unadvise
|
243
|
-
end
|
244
|
-
|
245
|
-
it "should accept :object(s) => [O1, ...] and :methods => [...] parameters indicating the objects to advise." do
|
246
|
-
watchful1 = Watchful.new
|
247
|
-
watchful2 = Watchful.new
|
248
|
-
advice_called = false
|
249
|
-
aspect = Aspect.new :before, :object => [watchful1, watchful2], :methods => :public_watchful_method do |jp, *args|
|
250
|
-
advice_called = true
|
251
|
-
jp.should_not == nil
|
252
|
-
args.size.should == 4
|
253
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
254
|
-
end
|
255
|
-
watchful1.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
256
|
-
watchful2.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
257
|
-
advice_called.should be_true
|
258
|
-
aspect.unadvise
|
259
|
-
end
|
260
|
-
|
261
|
-
it "should accept :object(s) => O and :methods => [...] parameters indicating the objects to advise." do
|
262
|
-
watchful = Watchful.new
|
263
|
-
advice_called = false
|
264
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method do |jp, *args|
|
265
|
-
advice_called = true
|
266
|
-
jp.should_not == nil
|
267
|
-
args.size.should == 4
|
268
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
269
|
-
end
|
270
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
271
|
-
advice_called.should be_true
|
272
|
-
aspect.unadvise
|
273
|
-
end
|
274
|
-
|
275
|
-
it "should accept :object(s) => O and :methods => [...] parameters indicating the objects to advise." do
|
276
|
-
watchful = Watchful.new
|
277
|
-
advice_called = false
|
278
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method do |jp, *args|
|
279
|
-
advice_called = true
|
280
|
-
jp.should_not == nil
|
281
|
-
args.size.should == 4
|
282
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
283
|
-
end
|
284
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
285
|
-
advice_called.should be_true
|
286
|
-
aspect.unadvise
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
describe Aspect, "#new block parameter" do
|
291
|
-
it "should accept a block as the advice to use." do
|
292
|
-
watchful = Watchful.new
|
293
|
-
advice_called = false
|
294
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method do |jp, *args|
|
295
|
-
advice_called = true
|
296
|
-
jp.should_not == nil
|
297
|
-
args.size.should == 4
|
298
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
299
|
-
end
|
300
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
301
|
-
advice_called.should be_true
|
302
|
-
aspect.unadvise
|
303
|
-
end
|
304
|
-
|
305
|
-
it "should accept an :advice => Proc parameter indicating the advice to use." do
|
306
|
-
watchful = Watchful.new
|
307
|
-
advice_called = false
|
308
|
-
advice = Proc.new {|jp, *args|
|
309
|
-
advice_called = true
|
310
|
-
jp.should_not == nil
|
311
|
-
args.size.should == 4
|
312
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
313
|
-
}
|
314
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice
|
315
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
316
|
-
advice_called.should be_true
|
317
|
-
aspect.unadvise
|
318
|
-
end
|
319
|
-
|
320
|
-
it "should accept a :call => Proc parameter as a synonym for :advice." do
|
321
|
-
watchful = Watchful.new
|
322
|
-
advice_called = false
|
323
|
-
advice = Proc.new {|jp, *args|
|
324
|
-
advice_called = true
|
325
|
-
jp.should_not == nil
|
326
|
-
args.size.should == 4
|
327
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
328
|
-
}
|
329
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :call => advice
|
330
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
331
|
-
advice_called.should be_true
|
332
|
-
aspect.unadvise
|
333
|
-
end
|
334
|
-
|
335
|
-
it "should accept a :invoke => Proc parameter as a synonym for :advice." do
|
336
|
-
watchful = Watchful.new
|
337
|
-
advice_called = false
|
338
|
-
advice = Proc.new {|jp, *args|
|
339
|
-
advice_called = true
|
340
|
-
jp.should_not == nil
|
341
|
-
args.size.should == 4
|
342
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
343
|
-
}
|
344
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :invoke => advice
|
345
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
346
|
-
advice_called.should be_true
|
347
|
-
aspect.unadvise
|
348
|
-
end
|
349
|
-
|
350
|
-
it "should accept a :advise_with => Proc parameter as a synonym for :advice." do
|
351
|
-
watchful = Watchful.new
|
352
|
-
advice_called = false
|
353
|
-
advice = Proc.new {|jp, *args|
|
354
|
-
advice_called = true
|
355
|
-
jp.should_not == nil
|
356
|
-
args.size.should == 4
|
357
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
358
|
-
}
|
359
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advise_with => advice
|
360
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
361
|
-
advice_called.should be_true
|
362
|
-
aspect.unadvise
|
363
|
-
end
|
364
|
-
|
365
|
-
it "should ignore all synonyms if there is an :advice => Proc parameter." do
|
366
|
-
watchful = Watchful.new
|
367
|
-
advice_called = false
|
368
|
-
advice = Proc.new {|jp, *args|
|
369
|
-
advice_called = true
|
370
|
-
jp.should_not == nil
|
371
|
-
args.size.should == 4
|
372
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
373
|
-
}
|
374
|
-
advice2 = Proc.new {|jp, *args| raise "should not be called"}
|
375
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :invoke => advice2, :advice => advice
|
376
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
377
|
-
advice_called.should be_true
|
378
|
-
aspect.unadvise
|
379
|
-
end
|
380
8
|
|
381
|
-
|
382
|
-
watchful = Watchful.new
|
383
|
-
advice_called = false
|
384
|
-
advice = Proc.new {|jp, *args|
|
385
|
-
advice_called = true
|
386
|
-
jp.should_not == nil
|
387
|
-
args.size.should == 4
|
388
|
-
args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
|
389
|
-
}
|
390
|
-
advice2 = Proc.new {|jp, *args| raise "should not be called"}
|
391
|
-
aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice2, :advice => advice
|
392
|
-
watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
|
393
|
-
advice_called.should be_true
|
394
|
-
aspect.unadvise
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
describe Aspect, "#new invoked for the private implementation methods inserted by other aspects" do
|
9
|
+
describe "Aspects that specify the private implementation methods inserted by other aspects" do
|
399
10
|
it "should have no affect." do
|
400
11
|
class WithAspectLikeMethod
|
401
12
|
def _aspect_foo; end
|
@@ -406,7 +17,7 @@ describe Aspect, "#new invoked for the private implementation methods inserted b
|
|
406
17
|
end
|
407
18
|
end
|
408
19
|
|
409
|
-
describe
|
20
|
+
describe "When an aspect advises a type" do
|
410
21
|
before(:all) do
|
411
22
|
@advice = Proc.new {}
|
412
23
|
end
|
@@ -414,26 +25,35 @@ describe Aspect, "#new modifications to the list of methods for the advised obje
|
|
414
25
|
@aspect.unadvise
|
415
26
|
end
|
416
27
|
|
417
|
-
it "should not
|
28
|
+
it "should not add new public instance or class methods that the advised type responds to." do
|
418
29
|
all_public_methods_before = all_public_methods_of_type Watchful
|
419
30
|
@aspect = Aspect.new :after, :pointcut => {:type => Watchful, :method_options => :exclude_ancestor_methods}, :advice => @advice
|
420
31
|
(all_public_methods_of_type(Watchful) - all_public_methods_before).should == []
|
421
32
|
end
|
422
33
|
|
423
|
-
it "should not
|
34
|
+
it "should not add new protected instance methods that the advised type responds to." do
|
424
35
|
all_protected_methods_before = all_protected_methods_of_type Watchful
|
425
36
|
@aspect = Aspect.new :after, :pointcut => {:type => Watchful, :method_options => :exclude_ancestor_methods}, :advice => @advice
|
426
37
|
(all_protected_methods_of_type(Watchful) - all_protected_methods_before).should == []
|
427
38
|
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "When an aspect advises an object" do
|
42
|
+
before(:all) do
|
43
|
+
@advice = Proc.new {}
|
44
|
+
end
|
45
|
+
after(:each) do
|
46
|
+
@aspect.unadvise
|
47
|
+
end
|
428
48
|
|
429
|
-
it "should not
|
49
|
+
it "should not add new public instance or class methods that the advised object responds to." do
|
430
50
|
watchful = Watchful.new
|
431
51
|
all_public_methods_before = all_public_methods_of_object Watchful
|
432
52
|
@aspect = Aspect.new :after, :pointcut => {:object => watchful, :method_options => :exclude_ancestor_methods}, :advice => @advice
|
433
53
|
(all_public_methods_of_object(Watchful) - all_public_methods_before).should == []
|
434
54
|
end
|
435
55
|
|
436
|
-
it "should not
|
56
|
+
it "should not add new protected instance or class methods that the advised object responds to." do
|
437
57
|
watchful = Watchful.new
|
438
58
|
all_protected_methods_before = all_protected_methods_of_object Watchful
|
439
59
|
@aspect = Aspect.new :after, :pointcut => {:object => watchful, :method_options => :exclude_ancestor_methods}, :advice => @advice
|
@@ -441,7 +61,7 @@ describe Aspect, "#new modifications to the list of methods for the advised obje
|
|
441
61
|
end
|
442
62
|
end
|
443
63
|
|
444
|
-
describe
|
64
|
+
describe "Aspects with :before advice" do
|
445
65
|
after(:each) do
|
446
66
|
@aspect.unadvise if @aspect
|
447
67
|
end
|
@@ -470,7 +90,7 @@ describe Aspect, "#new with :before advice" do
|
|
470
90
|
end
|
471
91
|
end
|
472
92
|
|
473
|
-
describe
|
93
|
+
describe "Aspects with :after advice" do
|
474
94
|
after(:each) do
|
475
95
|
@aspect.unadvise if @aspect
|
476
96
|
end
|
@@ -512,6 +132,7 @@ describe Aspect, "#new with :after advice" do
|
|
512
132
|
end
|
513
133
|
do_watchful_public_protected_private
|
514
134
|
end
|
135
|
+
|
515
136
|
it "should ignore the value returned by the advice" do
|
516
137
|
class ReturningValue
|
517
138
|
def doit args
|
@@ -541,7 +162,7 @@ describe Aspect, "#new with :after advice" do
|
|
541
162
|
end
|
542
163
|
end
|
543
164
|
|
544
|
-
describe
|
165
|
+
describe "Aspects with :after_returning advice" do
|
545
166
|
after(:each) do
|
546
167
|
@aspect.unadvise if @aspect
|
547
168
|
end
|
@@ -598,7 +219,7 @@ describe Aspect, "#new with :after_returning advice" do
|
|
598
219
|
end
|
599
220
|
end
|
600
221
|
|
601
|
-
describe
|
222
|
+
describe "Aspects with :after_raising advice" do
|
602
223
|
after(:each) do
|
603
224
|
@aspect.unadvise if @aspect
|
604
225
|
end
|
@@ -667,7 +288,7 @@ describe Aspect, "#new with :after_raising advice" do
|
|
667
288
|
end
|
668
289
|
end
|
669
290
|
|
670
|
-
describe
|
291
|
+
describe "Aspects with :before and :after advice" do
|
671
292
|
after(:each) do
|
672
293
|
@aspect.unadvise if @aspect
|
673
294
|
end
|
@@ -708,7 +329,7 @@ describe Aspect, "#new with :before and :after advice" do
|
|
708
329
|
end
|
709
330
|
end
|
710
331
|
|
711
|
-
describe
|
332
|
+
describe "Aspects with :before and :after_returning advice" do
|
712
333
|
after(:each) do
|
713
334
|
@aspect.unadvise if @aspect
|
714
335
|
end
|
@@ -742,7 +363,7 @@ describe Aspect, "#new with :before and :after_returning advice" do
|
|
742
363
|
end
|
743
364
|
end
|
744
365
|
|
745
|
-
describe
|
366
|
+
describe "Aspects with :before and :after_raising advice" do
|
746
367
|
after(:each) do
|
747
368
|
@aspect.unadvise if @aspect
|
748
369
|
end
|
@@ -776,7 +397,7 @@ describe Aspect, "#new with :before and :after_raising advice" do
|
|
776
397
|
end
|
777
398
|
end
|
778
399
|
|
779
|
-
describe
|
400
|
+
describe "Aspects with :around advice" do
|
780
401
|
after(:each) do
|
781
402
|
@aspect.unadvise if @aspect
|
782
403
|
end
|
@@ -978,58 +599,144 @@ end
|
|
978
599
|
|
979
600
|
|
980
601
|
|
981
|
-
describe Aspect, "#unadvise" do
|
602
|
+
describe Aspect, "#unadvise for 'empty' aspects" do
|
982
603
|
before(:all) do
|
983
604
|
@advice = Proc.new {}
|
984
605
|
end
|
606
|
+
|
985
607
|
it "should do nothing for unadvised types." do
|
986
|
-
expected_methods = Watchful.private_methods.sort
|
608
|
+
expected_methods = (Watchful.private_methods + Watchful.private_instance_methods).sort
|
987
609
|
aspect = Aspect.new :around, :type => Watchful, :method => /does_not_exist/, :advice => @advice
|
988
|
-
(Watchful.private_methods.sort - expected_methods).should == []
|
610
|
+
((Watchful.private_methods + Watchful.private_instance_methods).sort - expected_methods).should == []
|
989
611
|
aspect.unadvise
|
990
|
-
(Watchful.private_methods.sort - expected_methods).should == []
|
612
|
+
((Watchful.private_methods + Watchful.private_instance_methods).sort - expected_methods).should == []
|
991
613
|
aspect.unadvise
|
992
|
-
(Watchful.private_methods.sort - expected_methods).should == []
|
614
|
+
((Watchful.private_methods + Watchful.private_instance_methods).sort - expected_methods).should == []
|
993
615
|
end
|
994
616
|
|
995
617
|
it "should do nothing for unadvised objects." do
|
996
|
-
watchful = Watchful.new
|
997
|
-
expected_methods =
|
998
|
-
aspect = Aspect.new :around, :
|
999
|
-
(
|
618
|
+
@watchful = Watchful.new
|
619
|
+
expected_methods = @watchful.private_methods.sort
|
620
|
+
aspect = Aspect.new :around, :object => @watchful, :method => /does_not_exist/, :advice => @advice
|
621
|
+
(@watchful.private_methods.sort - expected_methods).should == []
|
1000
622
|
aspect.unadvise
|
1001
|
-
(
|
623
|
+
(@watchful.private_methods.sort - expected_methods).should == []
|
1002
624
|
aspect.unadvise
|
1003
|
-
(
|
625
|
+
(@watchful.private_methods.sort - expected_methods).should == []
|
1004
626
|
end
|
1005
|
-
|
1006
|
-
|
627
|
+
end
|
628
|
+
|
629
|
+
describe Aspect, "#unadvise for removes all traces of the aspect" do
|
630
|
+
before(:all) do
|
631
|
+
@advice = Proc.new {}
|
632
|
+
@watchful = Watchful.new
|
633
|
+
end
|
634
|
+
|
635
|
+
def get_type_methods
|
636
|
+
public_methods = (Watchful.public_methods + Watchful.public_instance_methods).sort
|
637
|
+
protected_methods = (Watchful.protected_methods + Watchful.protected_instance_methods).sort
|
638
|
+
private_methods = (Watchful.private_methods + Watchful.private_instance_methods).sort
|
639
|
+
[public_methods, protected_methods, private_methods]
|
640
|
+
end
|
641
|
+
|
642
|
+
def get_object_methods
|
643
|
+
public_methods = @watchful.public_methods.sort
|
644
|
+
protected_methods = @watchful.protected_methods.sort
|
645
|
+
private_methods = @watchful.private_methods.sort
|
646
|
+
[public_methods, protected_methods, private_methods]
|
647
|
+
end
|
648
|
+
|
649
|
+
def diff_methods actual, expected, private_should_not_be_equal = false
|
650
|
+
3.times do |i|
|
651
|
+
if i==2 && private_should_not_be_equal
|
652
|
+
actual[i].should_not == expected[i]
|
653
|
+
else
|
654
|
+
actual[i].should == expected[i]
|
655
|
+
end
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
def do_unadvise_spec parameters, which_get_methods
|
660
|
+
parameters[:after] = ''
|
661
|
+
expected_methods = send(which_get_methods)
|
1007
662
|
advice_called = false
|
1008
|
-
aspect = Aspect.new(:after,
|
663
|
+
aspect = Aspect.new(:after, parameters) {|jp, *args| advice_called = true}
|
664
|
+
diff_methods send(which_get_methods), expected_methods, true
|
1009
665
|
aspect.unadvise
|
1010
|
-
|
666
|
+
diff_methods send(which_get_methods), expected_methods
|
1011
667
|
|
1012
668
|
%w[public protected private].each do |protection|
|
1013
669
|
advice_called = false
|
1014
670
|
block_called = false
|
1015
|
-
watchful.send("#{protection}_watchful_method".intern, :a1, :a2, :a3) {|*args| block_called = true}
|
671
|
+
@watchful.send("#{protection}_watchful_method".intern, :a1, :a2, :a3) {|*args| block_called = true}
|
1016
672
|
advice_called.should be_false
|
1017
673
|
block_called.should be_true
|
1018
674
|
end
|
1019
675
|
end
|
1020
676
|
|
1021
|
-
it "should remove all advice
|
677
|
+
it "should remove all advice added by a pointcut-based aspect." do
|
678
|
+
do_unadvise_spec({:pointcut => {:type => Watchful, :method_options => :exclude_ancestor_methods}}, :get_type_methods)
|
679
|
+
end
|
680
|
+
|
681
|
+
it "should remove all advice added by a type-based aspect." do
|
682
|
+
do_unadvise_spec({:type => Watchful, :method_options => :exclude_ancestor_methods}, :get_type_methods)
|
683
|
+
end
|
684
|
+
|
685
|
+
it "should remove all advice added by an object-based aspect." do
|
686
|
+
do_unadvise_spec({:object => @watchful, :method_options => :exclude_ancestor_methods}, :get_object_methods)
|
687
|
+
end
|
688
|
+
|
689
|
+
it "should remove all advice overhead if all advices are removed for pointcut-based aspects." do
|
1022
690
|
class Foo
|
1023
691
|
def bar; end
|
1024
692
|
end
|
1025
693
|
before = Foo.private_instance_methods.sort
|
1026
|
-
|
694
|
+
aspect1 = Aspect.new(:before, :pointcut => {:type => Foo, :method_options => :exclude_ancestor_methods}) {|jp, *args| true}
|
695
|
+
aspect2 = Aspect.new(:after, :pointcut => {:type => Foo, :method_options => :exclude_ancestor_methods}) {|jp, *args| true}
|
1027
696
|
after = Foo.private_instance_methods
|
1028
697
|
(after - before).should_not == []
|
1029
|
-
|
698
|
+
aspect1.unadvise
|
699
|
+
after = Foo.private_instance_methods
|
700
|
+
(after - before).should_not == []
|
701
|
+
aspect2.unadvise
|
702
|
+
after = Foo.private_instance_methods
|
703
|
+
(after - before).should == []
|
704
|
+
end
|
705
|
+
|
706
|
+
it "should remove all advice overhead if all advices are removed for type-based aspects." do
|
707
|
+
class Foo
|
708
|
+
def bar; end
|
709
|
+
end
|
710
|
+
before = Foo.private_instance_methods.sort
|
711
|
+
aspect1 = Aspect.new(:before, :type => Foo, :method_options => :exclude_ancestor_methods) {|jp, *args| true}
|
712
|
+
aspect2 = Aspect.new(:after, :type => Foo, :method_options => :exclude_ancestor_methods) {|jp, *args| true}
|
713
|
+
after = Foo.private_instance_methods
|
714
|
+
(after - before).should_not == []
|
715
|
+
aspect1.unadvise
|
716
|
+
after = Foo.private_instance_methods
|
717
|
+
(after - before).should_not == []
|
718
|
+
aspect2.unadvise
|
1030
719
|
after = Foo.private_instance_methods
|
1031
720
|
(after - before).should == []
|
1032
721
|
end
|
722
|
+
|
723
|
+
it "should remove all advice overhead if all advices are removed for object-based aspects." do
|
724
|
+
class Overhead
|
725
|
+
def over; end
|
726
|
+
end
|
727
|
+
overhead = Overhead.new
|
728
|
+
before = overhead.private_methods.sort
|
729
|
+
aspect1 = Aspect.new(:before, :object => overhead, :method_options => :exclude_ancestor_methods) {|jp, *args| true}
|
730
|
+
aspect2 = Aspect.new(:after, :object => overhead, :method_options => :exclude_ancestor_methods) {|jp, *args| true}
|
731
|
+
after = overhead.private_methods
|
732
|
+
(after - before).should_not == []
|
733
|
+
aspect1.unadvise
|
734
|
+
after = overhead.private_methods
|
735
|
+
(after - before).should_not == []
|
736
|
+
aspect2.unadvise
|
737
|
+
after = overhead.private_methods
|
738
|
+
(after - before).should == []
|
739
|
+
end
|
1033
740
|
end
|
1034
741
|
|
1035
742
|
describe "invariant protection level of methods under advising and unadvising", :shared => true do
|
@@ -1046,15 +753,46 @@ describe "invariant protection level of methods under advising and unadvising",
|
|
1046
753
|
end
|
1047
754
|
end
|
1048
755
|
|
1049
|
-
describe
|
756
|
+
describe "Aspects advising methods should keep the protection level of an advised methods unchanged." do
|
1050
757
|
it_should_behave_like("invariant protection level of methods under advising and unadvising")
|
1051
758
|
end
|
1052
|
-
describe
|
759
|
+
describe "Aspects unadvising methods should restore the original protection level of the methods." do
|
1053
760
|
it_should_behave_like("invariant protection level of methods under advising and unadvising")
|
1054
761
|
end
|
1055
762
|
|
763
|
+
describe "Aspects unadvising methods for instance-type pointcuts for type-defined methods" do
|
764
|
+
class TypeDefinedMethodClass
|
765
|
+
def inititalize; @called = false; end
|
766
|
+
def m; @called = true; end
|
767
|
+
attr_reader :called
|
768
|
+
end
|
769
|
+
|
770
|
+
it "should cause the object to respond to the type's original method." do
|
771
|
+
object = TypeDefinedMethodClass.new
|
772
|
+
aspect = Aspect.new(:before, :object => object, :method => :m) {true}
|
773
|
+
aspect.unadvise
|
774
|
+
object.m
|
775
|
+
object.called.should be_true
|
776
|
+
end
|
777
|
+
end
|
778
|
+
|
779
|
+
describe "Aspects unadvising methods for instance-type pointcuts for instance-defined methods" do
|
780
|
+
class InstanceDefinedMethodClass
|
781
|
+
def inititalize; @called = false; end
|
782
|
+
attr_reader :called
|
783
|
+
end
|
784
|
+
|
785
|
+
it "should cause the object to respond to the object's original method." do
|
786
|
+
object = TypeDefinedMethodClass.new
|
787
|
+
def object.m; @called = true; end
|
788
|
+
aspect = Aspect.new(:before, :object => object, :method => :m) {true}
|
789
|
+
aspect.unadvise
|
790
|
+
object.m
|
791
|
+
object.called.should be_true
|
792
|
+
end
|
793
|
+
end
|
1056
794
|
|
1057
|
-
describe
|
795
|
+
describe "Aspects advising methods with non-alphanumeric characters" do
|
1058
796
|
module Aquarium::Aspects
|
1059
797
|
class ClassWithMethodNamesContainingOddChars
|
1060
798
|
@@method_names = []
|
@@ -1065,7 +803,7 @@ describe Aspect, "Advising methods with non-alphanumeric characters" do
|
|
1065
803
|
@@method_names << s
|
1066
804
|
end
|
1067
805
|
@@method_names.each do |s|
|
1068
|
-
class_eval
|
806
|
+
class_eval(<<-EOF, __FILE__, __LINE__)
|
1069
807
|
def #{s}; "#{s}"; end
|
1070
808
|
EOF
|
1071
809
|
end
|