aquarium 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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