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.
@@ -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
- it "should ignore all but the last :advice => Proc parameter." do
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 Aspect, "#new modifications to the list of methods for the advised object or type" do
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 include new public instance or class methods for the advised type." do
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 include new protected instance or class methods for the advised type." do
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 include new public methods for the advised object." do
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 include new protected methods for the advised object." do
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 Aspect, "#new with :before advice" do
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 Aspect, "#new with :after advice" do
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 Aspect, "#new with :after_returning advice" do
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 Aspect, "#new with :after_raising advice" do
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 Aspect, "#new with :before and :after advice" do
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 Aspect, "#new with :before and :after_returning advice" do
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 Aspect, "#new with :before and :after_raising advice" do
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 Aspect, "#new with :around advice" do
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 = Watchful.private_methods.sort
998
- aspect = Aspect.new :around, :type => Watchful, :method => /does_not_exist/, :advice => @advice
999
- (Watchful.private_methods.sort - expected_methods).should == []
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
- (Watchful.private_methods.sort - expected_methods).should == []
623
+ (@watchful.private_methods.sort - expected_methods).should == []
1002
624
  aspect.unadvise
1003
- (Watchful.private_methods.sort - expected_methods).should == []
625
+ (@watchful.private_methods.sort - expected_methods).should == []
1004
626
  end
1005
-
1006
- it "should remove all advice added by the aspect." do
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, :pointcut => {:type => Watchful, :method_options => :exclude_ancestor_methods}) {|jp, *args| advice_called = true}
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
- watchful = Watchful.new
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 overhead if all advices are removed." do
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
- aspect = Aspect.new(:after, :pointcut => {:type => Foo, :method_options => :exclude_ancestor_methods}) {|jp, *args| true}
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
- aspect.unadvise
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 Aspect, "Advising methods should keep the protection level of an advised methods unchanged." do
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 Aspect, "Unadvising methods should restore the original protection level of the methods." do
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 Aspect, "Advising methods with non-alphanumeric characters" do
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 <<-EOF
806
+ class_eval(<<-EOF, __FILE__, __LINE__)
1069
807
  def #{s}; "#{s}"; end
1070
808
  EOF
1071
809
  end