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.
@@ -9,7 +9,7 @@ module Aquarium
9
9
  unless defined? MAJOR
10
10
  MAJOR = 0
11
11
  MINOR = 1
12
- TINY = 7
12
+ TINY = 8
13
13
  RELEASE_CANDIDATE = nil
14
14
 
15
15
  # RANDOM_TOKEN: 0.598704893979657
@@ -2,12 +2,14 @@ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
2
  require File.dirname(__FILE__) + '/../spec_example_classes'
3
3
  require 'aquarium'
4
4
 
5
+ include Aquarium::Aspects::Advice
6
+
5
7
  # Some of AdviceChainNode and related classes are tested through advice_spec.rb. We rely on rcov to
6
8
  # tell us otherwise...
7
9
  describe Aquarium::Aspects::AdviceChainNode, "#each" do
8
10
  it "should return each node in succession" do
9
11
  static_join_point = :static_join_point
10
- advice = lambda {|jp, *args| p "none advice"}
12
+ advice = lambda {|jp, *args| p ":none advice"}
11
13
  options = {
12
14
  :advice_kind => :none,
13
15
  :advice => advice,
@@ -15,7 +17,7 @@ describe Aquarium::Aspects::AdviceChainNode, "#each" do
15
17
  :static_join_point => static_join_point}
16
18
  advice_chain = Aquarium::Aspects::AdviceChainNodeFactory.make_node options
17
19
 
18
- Aquarium::Aspects::Advice.kinds_in_priority_order.each do |advice_kind|
20
+ KINDS_IN_PRIORITY_ORDER.each do |advice_kind|
19
21
  advice = lambda {|jp, *args| p "#{advice_kind} advice"}
20
22
  options[:advice_kind] = advice_kind
21
23
  options[:advice] = advice,
@@ -24,7 +26,7 @@ describe Aquarium::Aspects::AdviceChainNode, "#each" do
24
26
  end
25
27
 
26
28
  advice_chain.size.should == 6
27
- expected_advice_kinds = Aquarium::Aspects::Advice.kinds_in_priority_order.reverse + [:none]
29
+ expected_advice_kinds = KINDS_IN_PRIORITY_ORDER.reverse + [:none]
28
30
  count = 0
29
31
  advice_chain.each do |node|
30
32
  node.advice_kind.should == expected_advice_kinds[count]
@@ -2,11 +2,36 @@ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
2
  require File.dirname(__FILE__) + '/../spec_example_classes'
3
3
  require 'aquarium/aspects/aspect'
4
4
  require 'aquarium/aspects/dsl'
5
+ require 'aquarium/utils/array_utils'
6
+
7
+ require 'profiler'
5
8
 
6
9
  include Aquarium::Aspects
10
+ include Aquarium::Utils::ArrayUtils
11
+
12
+
13
+ def aspects_should_be_equal num_jps, aspect1, aspect2
14
+ # We don't use @aspect1.should eql(@aspect2) because the "specifications" are different.
15
+ aspect1.pointcuts.size.should == 1
16
+ aspect2.pointcuts.size.should == 1
17
+ aspect1.pointcuts.should eql(aspect2.pointcuts)
18
+ aspect1.advice.should eql(@advice)
19
+ aspect2.advice.should eql(@advice)
20
+ join_points_should_be_equal num_jps, aspect1, aspect2
21
+ end
7
22
 
8
- describe Aspect, "#new with invalid invocation parameter list" do
9
- it "should have as the first parameter at least one of :around, :before, :after, :after_returning, and :after_raising." do
23
+ def join_points_should_be_equal num_jps, aspect1, aspect2
24
+ aspect1.join_points_matched.size.should == num_jps
25
+ aspect2.join_points_matched.size.should == num_jps
26
+ aspect1.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
27
+ aspect2.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
28
+ aspect1.join_points_matched.should eql(aspect2.join_points_matched)
29
+ aspect1.join_points_not_matched.should eql(aspect2.join_points_not_matched)
30
+ end
31
+
32
+
33
+ describe Aspect, "#new parameters that specify the kind of advice" do
34
+ it "should require the kind of advice as the first parameter." do
10
35
  lambda { Aspect.new :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
11
36
  end
12
37
 
@@ -22,9 +47,7 @@ describe Aspect, "#new with invalid invocation parameter list" do
22
47
  lambda { Aspect.new :after, :after_raising, :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
23
48
  lambda { Aspect.new :after_returning, :after_raising, :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
24
49
  end
25
- end
26
50
 
27
- describe Aspect, "#new, when the arguments contain more than one advice type," do
28
51
  it "should allow :before to be specified with :after." do
29
52
  lambda { Aspect.new :before, :after, :pointcut => {:type => Watchful}, :noop => true }.should_not raise_error(Aquarium::Utils::InvalidOptions)
30
53
  end
@@ -38,26 +61,753 @@ describe Aspect, "#new, when the arguments contain more than one advice type," d
38
61
  end
39
62
  end
40
63
 
41
- def aspects_should_be_equal num_jps, aspect1, aspect2
42
- # We don't use @aspect1.should eql(@aspect2) because the "specifications" are different.
43
- aspect1.pointcuts.size.should == 1
44
- aspect2.pointcuts.size.should == 1
45
- aspect1.pointcuts.should eql(aspect2.pointcuts)
46
- aspect1.advice.should eql(@advice)
47
- aspect2.advice.should eql(@advice)
48
- join_points_should_be_equal num_jps, aspect1, aspect2
64
+ describe Aspect, "#new parameters that specify join points" do
65
+ it "should contain at least one of :method(s), :pointcut(s), :type(s), or :object(s)." do
66
+ lambda {Aspect.new(:after) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
67
+ end
68
+
69
+ it "should contain at least one of :pointcut(s), :type(s), or :object(s) unless :default_object => object is given." do
70
+ aspect = Aspect.new(:after, :default_object => Watchful.new, :methods => :public_watchful_method) {|jp, *args| true}
71
+ aspect.unadvise
72
+ end
73
+
74
+ it "should not contain :pointcut(s) and either :type(s) or :object(s)." do
75
+ 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)
76
+ 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)
77
+ end
78
+
79
+ it "should include an advice block or :advice => advice parameter." do
80
+ lambda {Aspect.new(:after, :type => Watchful, :methods => :public_watchful_method)}.should raise_error(Aquarium::Utils::InvalidOptions)
81
+ end
49
82
  end
50
83
 
51
- def join_points_should_be_equal num_jps, aspect1, aspect2
52
- aspect1.join_points_matched.size.should == num_jps
53
- aspect2.join_points_matched.size.should == num_jps
54
- aspect1.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
55
- aspect2.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
56
- aspect1.join_points_matched.should eql(aspect2.join_points_matched)
57
- aspect1.join_points_not_matched.should eql(aspect2.join_points_not_matched)
84
+
85
+ describe Aspect, "#new :type parameter" do
86
+ it "should be accepted as a synonym for :types" do
87
+ @advice = Proc.new {}
88
+ @expected_methods = [:public_watchful_method]
89
+ aspect1 = Aspect.new :before, :type => Watchful, :method => @expected_methods, :advice => @advice
90
+ aspect2 = Aspect.new :before, :types => Watchful, :method => @expected_methods, :advice => @advice
91
+ aspects_should_be_equal 1, aspect1, aspect2
92
+ aspect1.unadvise
93
+ aspect2.unadvise
94
+ end
95
+ end
96
+
97
+ describe Aspect, "#new :pointcut parameter" do
98
+ it "should be accepted as a synonym for :pointcuts" do
99
+ @advice = Proc.new {}
100
+ @expected_methods = [:public_watchful_method]
101
+ aspect1 = Aspect.new :before, :pointcut => {:type => Watchful, :method => @expected_methods}, :advice => @advice
102
+ aspect2 = Aspect.new :before, :pointcuts => {:type => Watchful, :method => @expected_methods}, :advice => @advice
103
+ aspects_should_be_equal 1, aspect1, aspect2
104
+ aspect1.unadvise
105
+ aspect2.unadvise
106
+ end
107
+ end
108
+
109
+ describe Aspect, "#new :object parameter" do
110
+ it "should be accepted as a synonym for :objects" do
111
+ @advice = Proc.new {}
112
+ @expected_methods = [:public_watchful_method]
113
+ watchful = Watchful.new
114
+ aspect1 = Aspect.new :before, :object => watchful, :method => @expected_methods, :advice => @advice
115
+ aspect2 = Aspect.new :before, :objects => watchful, :method => @expected_methods, :advice => @advice
116
+ aspects_should_be_equal 1, aspect1, aspect2
117
+ aspect1.unadvise
118
+ aspect2.unadvise
119
+ end
120
+ end
121
+
122
+ describe Aspect, "#new :method parameter" do
123
+ it "should be accepted as a synonym for :methods" do
124
+ @advice = Proc.new {}
125
+ @expected_methods = [:public_watchful_method]
126
+ aspect1 = Aspect.new :before, :type => Watchful, :method => @expected_methods, :advice => @advice
127
+ aspect2 = Aspect.new :before, :type => Watchful, :methods => @expected_methods, :advice => @advice
128
+ aspects_should_be_equal 1, aspect1, aspect2
129
+ aspect1.unadvise
130
+ aspect2.unadvise
131
+ end
132
+ end
133
+
134
+ describe Aspect, "#new :attribute parameter" do
135
+ it "should be accepted as a synonym for :attributes" do
136
+ @advice = Proc.new {}
137
+ @expected_methods = [:public_watchful_method_args, :public_watchful_method_args=]
138
+ aspect1 = Aspect.new :before, :type => Watchful, :attribute => @expected_methods, :advice => @advice
139
+ aspect2 = Aspect.new :before, :type => Watchful, :attributes => @expected_methods, :advice => @advice
140
+ aspects_should_be_equal 2, aspect1, aspect2
141
+ aspect1.unadvise
142
+ aspect2.unadvise
143
+ end
144
+ end
145
+
146
+
147
+ describe Aspect, "#new with a :type(s) parameter and a :method(s) parameter" do
148
+ before :each do
149
+ @protection = 'public'
150
+ @are_class_methods = false
151
+ @method_options = []
152
+ end
153
+
154
+ def do_type_spec
155
+ aspect = nil
156
+ advice_called = false
157
+ aspect = Aspect.new :before, :types => @type_spec, :methods => @method_spec, :method_options => @method_options do |jp, *args|
158
+ advice_called = true
159
+ jp.should_not be_nil
160
+ args.size.should == 4
161
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
162
+ end
163
+ if @are_class_methods
164
+ Watchful.method("#{@protection}_class_watchful_method").call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
165
+ else
166
+ Watchful.new.method("#{@protection}_watchful_method").call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
167
+ end
168
+ advice_called.should be_true
169
+ aspect.unadvise
170
+ end
171
+
172
+ it "should accept :type(s) => [T1, ...], :methods => [m, ...]" do
173
+ @type_spec = [Watchful]
174
+ @method_spec = [:public_watchful_method]
175
+ do_type_spec
176
+ end
177
+
178
+ it "should accept :type(s) => [T1, ...], :methods => m" do
179
+ @type_spec = [Watchful]
180
+ @method_spec = :public_watchful_method
181
+ do_type_spec
182
+ end
183
+
184
+ it "should accept :type(s) => [T1, ...], :methods => /m/" do
185
+ @type_spec = [Watchful]
186
+ @method_spec = /watchful_method/
187
+ do_type_spec
188
+ end
189
+
190
+ it "should accept :type(s) => T1, :methods => [m, ...]" do
191
+ @type_spec = Watchful
192
+ @method_spec = [:public_watchful_method]
193
+ do_type_spec
194
+ end
195
+
196
+ it "should accept :type(s) => T1, :methods => m" do
197
+ @type_spec = Watchful
198
+ @method_spec = :public_watchful_method
199
+ do_type_spec
200
+ end
201
+
202
+ it "should accept :type(s) => T1, :methods => /m/" do
203
+ @type_spec = Watchful
204
+ @method_spec = /watchful_method/
205
+ do_type_spec
206
+ end
207
+
208
+ it "should accept :type(s) => /T1/, :methods => [m, ...]" do
209
+ @type_spec = /Watchful/
210
+ @method_spec = [:public_watchful_method]
211
+ do_type_spec
212
+ end
213
+
214
+ it "should accept :type(s) => /T1/, :methods => m" do
215
+ @type_spec = /Watchful/
216
+ @method_spec = :public_watchful_method
217
+ do_type_spec
218
+ end
219
+
220
+ it "should accept :type(s) => /T1/, :methods => /m/" do
221
+ @type_spec = /Watchful/
222
+ @method_spec = /watchful_method/
223
+ do_type_spec
224
+ end
225
+
226
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:exclude_ancestor_methods] to exclude methods defined in ancestors" do
227
+ @type_spec = /Watchful/
228
+ @method_spec = /watchful_method/
229
+ @method_options = [:exclude_ancestor_methods]
230
+ do_type_spec
231
+ end
232
+
233
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:instance, :public] to match only instance and public (both are the defaults) methods" do
234
+ @type_spec = /Watchful/
235
+ @method_spec = /watchful_method/
236
+ @method_options = [:instance, :public]
237
+ do_type_spec
238
+ end
239
+
240
+ %w[public protected private].each do |protection|
241
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [#{protection.intern}] to match only instance (default) #{protection} methods" do
242
+ @type_spec = /Watchful/
243
+ @method_spec = /watchful_method/
244
+ @method_options = [protection.intern]
245
+ @protection = protection
246
+ do_type_spec
247
+ end
248
+ end
249
+
250
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:class] to match only public (default) class methods" do
251
+ @type_spec = /Watchful/
252
+ @method_spec = /watchful_method/
253
+ @method_options = [:class]
254
+ @are_class_methods = true
255
+ do_type_spec
256
+ end
257
+
258
+ %w[public private].each do |protection|
259
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:class, :#{protection.intern}] to match only class #{protection} methods" do
260
+ @type_spec = /Watchful/
261
+ @method_spec = /watchful_method/
262
+ @method_options = [:class, protection.intern]
263
+ @protection = protection
264
+ @are_class_methods = true
265
+ do_type_spec
266
+ end
267
+ end
268
+ end
269
+
270
+
271
+ describe Aspect, "#new with a :type(s) parameter and a :attribute(s) parameter" do
272
+ before :each do
273
+ @protection = 'public'
274
+ @attribute_options = []
275
+ @are_class_methods = false
276
+ end
277
+
278
+ def do_type_attribute_spec
279
+ aspect = nil
280
+ advice_called = false
281
+ aspect = Aspect.new :before, :types => @type_spec, :attributes => @attribute_spec, :attribute_options => @attribute_options do |jp, *args|
282
+ advice_called = true
283
+ jp.should_not be_nil
284
+ expected_args = make_array(@expected_args)
285
+ args.should == expected_args
286
+ args.size.should == expected_args.size
287
+ end
288
+ watchful = Watchful.new
289
+ @expected_args = nil
290
+ watchful.method("#{@protection}_watchful_method_args".intern).call
291
+ @expected_args = :a1
292
+ watchful.method("#{@protection}_watchful_method_args=".intern).call @expected_args
293
+ advice_called.should be_true
294
+ aspect.unadvise
295
+ end
296
+
297
+ it "should accept :type(s) => [T1, ...], :attribute(s) => [a, ...]" do
298
+ @type_spec = [Watchful]
299
+ @attribute_spec = [:public_watchful_method_args]
300
+ do_type_attribute_spec
301
+ end
302
+
303
+ it "should accept :type(s) => [T1, ...], :attribute(s) => a" do
304
+ @type_spec = [Watchful]
305
+ @attribute_spec = :public_watchful_method_args
306
+ do_type_attribute_spec
307
+ end
308
+
309
+ it "should accept :type(s) => [T1, ...], :attribute(s) => /a/" do
310
+ @type_spec = [Watchful]
311
+ @attribute_spec = /watchful_method_args/
312
+ do_type_attribute_spec
313
+ end
314
+
315
+ it "should accept :type(s) => T1, :attribute(s) => [a]" do
316
+ @type_spec = Watchful
317
+ @attribute_spec = [:public_watchful_method_args]
318
+ do_type_attribute_spec
319
+ end
320
+
321
+ it "should accept :type(s) => T1, :attribute(s) => a" do
322
+ @type_spec = Watchful
323
+ @attribute_spec = :public_watchful_method_args
324
+ do_type_attribute_spec
325
+ end
326
+
327
+ it "should accept :type(s) => T1, :attribute(s) => /a/" do
328
+ @type_spec = Watchful
329
+ @attribute_spec = /watchful_method_args/
330
+ do_type_attribute_spec
331
+ end
332
+
333
+ it "should accept :type(s) => /T1/, :attribute(s) => [a, ...]" do
334
+ @type_spec = /Watchful/
335
+ @attribute_spec = [:public_watchful_method_args]
336
+ do_type_attribute_spec
337
+ end
338
+
339
+ it "should accept :type(s) => /T1/, :attribute(s) => a" do
340
+ @type_spec = /Watchful/
341
+ @attribute_spec = :public_watchful_method_args
342
+ do_type_attribute_spec
343
+ end
344
+
345
+ it "should accept :type(s) => /T1/, :attribute(s) => a" do
346
+ @type_spec = /Watchful/
347
+ @attribute_spec = /watchful_method_args/
348
+ do_type_attribute_spec
349
+ end
350
+
351
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:readers, :writers] to include both attribute reader and writer methods (default)" do
352
+ @type_spec = /Watchful/
353
+ @attribute_spec = /watchful_method_args/
354
+ @attribute_options = [:readers, :writers]
355
+ do_type_attribute_spec
356
+ end
357
+
358
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:readers] to include only attribute reader methods" do
359
+ @type_spec = /Watchful/
360
+ @attribute_spec = /watchful_method_args/
361
+ @attribute_options = [:readers]
362
+ do_type_attribute_spec
363
+ end
364
+
365
+ it "should accept attribute option :reader as a synonym for :readers" do
366
+ @type_spec = /Watchful/
367
+ @attribute_spec = /watchful_method_args/
368
+ @attribute_options = [:reader]
369
+ do_type_attribute_spec
370
+ end
371
+
372
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:writers] to include only attribute writer methods" do
373
+ @type_spec = /Watchful/
374
+ @attribute_spec = /watchful_method_args/
375
+ @attribute_options = [:writers]
376
+ do_type_attribute_spec
377
+ end
378
+
379
+ it "should accept attribute option :writer as a synonym for :writers" do
380
+ @type_spec = /Watchful/
381
+ @attribute_spec = /watchful_method_args/
382
+ @attribute_options = [:writer]
383
+ do_type_attribute_spec
384
+ end
385
+
386
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:class, :readers, :writers] to include both attribute reader and writer methods (default) for class methods" do
387
+ @type_spec = /Watchful/
388
+ @attribute_spec = /watchful_method_args/
389
+ @attribute_options = [:class, :readers, :writers]
390
+ do_type_attribute_spec
391
+ end
392
+
393
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:class, :readers] to include only attribute reader class methods" do
394
+ @type_spec = /Watchful/
395
+ @attribute_spec = /watchful_method_args/
396
+ @attribute_options = [:class, :readers]
397
+ do_type_attribute_spec
398
+ end
399
+
400
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:class, :writers] to include only attribute writer class methods" do
401
+ @type_spec = /Watchful/
402
+ @attribute_spec = /watchful_method_args/
403
+ @attribute_options = [:class, :writers]
404
+ do_type_attribute_spec
405
+ end
58
406
  end
59
407
 
60
- describe Aspect, "#new arguments for specifying the types and methods" do
408
+ describe Aspect, "#new with a :object(s) parameter and a :method(s) parameter" do
409
+ before :each do
410
+ @watchful1 = Watchful.new
411
+ @watchful2 = Watchful.new
412
+ @protection = 'public'
413
+ @method_options = []
414
+ end
415
+
416
+ def do_object_spec
417
+ aspect = nil
418
+ advice_called = false
419
+ aspect = Aspect.new :before, :objects => @object_spec, :methods => @method_spec, :method_options => @method_options do |jp, *args|
420
+ advice_called = true
421
+ jp.should_not be_nil
422
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
423
+ end
424
+ make_array(@object_spec).each do |object|
425
+ object.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
426
+ end
427
+ advice_called.should be_true
428
+ aspect.unadvise
429
+ end
430
+
431
+ it "should accept :object(s) => [o1, ...], :methods => [m, ...]" do
432
+ @object_spec = [@watchful1, @watchful2]
433
+ @method_spec = [:public_watchful_method]
434
+ do_object_spec
435
+ end
436
+
437
+ it "should accept :object(s) => [o1, ...], :methods => m" do
438
+ @object_spec = [@watchful1, @watchful2]
439
+ @method_spec = :public_watchful_method
440
+ do_object_spec
441
+ end
442
+
443
+ it "should accept :object(s) => [o1, ...], :methods => /m/" do
444
+ @object_spec = [@watchful1, @watchful2]
445
+ @method_spec = /watchful_method/
446
+ do_object_spec
447
+ end
448
+
449
+ it "should accept :object(s) => o1, :methods => [m, ...]" do
450
+ @object_spec = @watchful1
451
+ @method_spec = [:public_watchful_method]
452
+ do_object_spec
453
+ end
454
+
455
+ it "should accept :object(s) => o1, :methods => m" do
456
+ @object_spec = @watchful1
457
+ @method_spec = :public_watchful_method
458
+ do_object_spec
459
+ end
460
+
461
+ it "should accept :object(s) => o1, :methods => /m/" do
462
+ @object_spec = @watchful1
463
+ @method_spec = /watchful_method/
464
+ do_object_spec
465
+ end
466
+
467
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [:exclude_ancestor_methods] to exclude methods defined in ancestors" do
468
+ @object_spec = @watchful1
469
+ @method_spec = /watchful_method/
470
+ @method_options = [:exclude_ancestor_methods]
471
+ do_object_spec
472
+ end
473
+
474
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [:instance, :public] to match only instance and public (both are the defaults) methods" do
475
+ @object_spec = @watchful1
476
+ @method_spec = /watchful_method/
477
+ @method_options = [:instance, :public]
478
+ do_object_spec
479
+ end
480
+
481
+ %w[public protected private].each do |protection|
482
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [#{protection.intern}] to match only instance (default) #{protection} methods" do
483
+ @object_spec = @watchful1
484
+ @method_spec = /watchful_method/
485
+ @method_options = [protection.intern]
486
+ @protection = protection
487
+ do_object_spec
488
+ end
489
+
490
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [:instance, #{protection.intern}] to match only instance #{protection} methods" do
491
+ @object_spec = @watchful1
492
+ @method_spec = /watchful_method/
493
+ @method_options = [:instance, protection.intern]
494
+ @protection = protection
495
+ do_object_spec
496
+ end
497
+ end
498
+ end
499
+
500
+ describe Aspect, "#new with a :object(s) parameter and a :attribute(s) parameter" do
501
+ before :each do
502
+ @watchful1 = Watchful.new
503
+ @watchful2 = Watchful.new
504
+ @protection = 'public'
505
+ @attribute_options = []
506
+ end
507
+
508
+ def do_object_attribute_spec
509
+ aspect = nil
510
+ advice_called = false
511
+ aspect = Aspect.new :before, :objects => @object_spec, :attributes => @attribute_spec, :attribute_options => @attribute_options do |jp, *args|
512
+ advice_called = true
513
+ jp.should_not be_nil
514
+ expected_args = make_array(@expected_args)
515
+ args.should == expected_args
516
+ args.size.should == expected_args.size
517
+ end
518
+ make_array(@object_spec).each do |object|
519
+ @expected_args = nil
520
+ object.method("#{@protection}_watchful_method_args".intern).call
521
+ @expected_args = :a1
522
+ object.method("#{@protection}_watchful_method_args=".intern).call @expected_args
523
+ advice_called.should be_true
524
+ end
525
+ aspect.unadvise
526
+ end
527
+
528
+ it "should accept :object(s) => [T1, ...], :attribute(s) => [a, ...]" do
529
+ @object_spec = [@watchful1, @watchful2]
530
+ @attribute_spec = [:public_watchful_method_args]
531
+ do_object_attribute_spec
532
+ end
533
+
534
+ it "should accept :object(s) => [T1, ...], :attribute(s) => a" do
535
+ @object_spec = [@watchful1, @watchful2]
536
+ @attribute_spec = :public_watchful_method_args
537
+ do_object_attribute_spec
538
+ end
539
+
540
+ it "should accept :object(s) => [T1, ...], :attribute(s) => /a/" do
541
+ @object_spec = [@watchful1, @watchful2]
542
+ @attribute_spec = /watchful_method_args/
543
+ do_object_attribute_spec
544
+ end
545
+
546
+ it "should accept :object(s) => T1, :attribute(s) => [a]" do
547
+ @object_spec = @watchful1
548
+ @attribute_spec = [:public_watchful_method_args]
549
+ do_object_attribute_spec
550
+ end
551
+
552
+ it "should accept :object(s) => T1, :attribute(s) => a" do
553
+ @object_spec = @watchful1
554
+ @attribute_spec = :public_watchful_method_args
555
+ do_object_attribute_spec
556
+ end
557
+
558
+ it "should accept :object(s) => T1, :attribute(s) => /a/" do
559
+ @object_spec = @watchful1
560
+ @attribute_spec = /watchful_method_args/
561
+ do_object_attribute_spec
562
+ end
563
+
564
+ it "should accept :object(s) => ..., :attributes => ..., :attribute_options => [:readers, :writers] to include both attribute reader and writer methods (default)" do
565
+ @object_spec = @watchful1
566
+ @attribute_spec = /watchful_method_args/
567
+ @attribute_options = [:readers, :writers]
568
+ do_object_attribute_spec
569
+ end
570
+
571
+ it "should accept :object(s) => ..., :attributes => ..., :attribute_options => [:readers] to include only attribute reader methods" do
572
+ @object_spec = @watchful1
573
+ @attribute_spec = /watchful_method_args/
574
+ @attribute_options = [:readers]
575
+ do_object_attribute_spec
576
+ end
577
+
578
+ it "should accept attribute option :reader as a synonym for :readers" do
579
+ @object_spec = @watchful1
580
+ @attribute_spec = /watchful_method_args/
581
+ @attribute_options = [:reader]
582
+ do_object_attribute_spec
583
+ end
584
+
585
+ it "should accept :object(s) => ..., :attributes => ..., :attribute_options => [:writers] to include only attribute writer methods" do
586
+ @object_spec = @watchful1
587
+ @attribute_spec = /watchful_method_args/
588
+ @attribute_options = [:writers]
589
+ do_object_attribute_spec
590
+ end
591
+
592
+ it "should accept attribute option :writer as a synonym for :writers" do
593
+ @object_spec = @watchful1
594
+ @attribute_spec = /watchful_method_args/
595
+ @attribute_options = [:writer]
596
+ do_object_attribute_spec
597
+ end
598
+ end
599
+
600
+ describe Aspect, "#new with a :pointcut parameter taking a hash with type specifications" do
601
+ before :each do
602
+ @protection = 'public'
603
+ @are_class_methods = false
604
+ end
605
+
606
+ def do_type_pointcut_spec
607
+ aspect = nil
608
+ advice_called = false
609
+ aspect = Aspect.new :before, :pointcut => @pointcut_hash do |jp, *args|
610
+ advice_called = true
611
+ jp.should_not be_nil
612
+ args.size.should == 4
613
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
614
+ end
615
+ if @are_class_methods
616
+ Watchful.method("#{@protection}_class_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
617
+ else
618
+ Watchful.new.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
619
+ end
620
+ advice_called.should be_true
621
+ aspect.unadvise
622
+ end
623
+
624
+ it "should accept {:type(s) => [T1, ...], :methods => [m, ...]} " do
625
+ @pointcut_hash = {:type => [Watchful], :methods => [:public_watchful_method]}
626
+ do_type_pointcut_spec
627
+ end
628
+
629
+ it "should accept {:type(s) => [T1, ...], :methods => m} " do
630
+ @pointcut_hash = {:type => [Watchful], :methods => :public_watchful_method}
631
+ do_type_pointcut_spec
632
+ end
633
+
634
+ it "should accept {:type(s) => [T1, ...], :methods => /m/} " do
635
+ @pointcut_hash = {:type => [Watchful], :methods => /watchful_method/}
636
+ do_type_pointcut_spec
637
+ end
638
+
639
+ it "should accept {:type(s) => T1, :methods => [m, ...]} " do
640
+ @pointcut_hash = {:type => Watchful, :methods => [:public_watchful_method]}
641
+ do_type_pointcut_spec
642
+ end
643
+
644
+ it "should accept {:type(s) => T1, :methods => m} " do
645
+ @pointcut_hash = {:type => Watchful, :methods => :public_watchful_method}
646
+ do_type_pointcut_spec
647
+ end
648
+
649
+ it "should accept {:type(s) => T1, :methods => /m/} " do
650
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/}
651
+ do_type_pointcut_spec
652
+ end
653
+
654
+ it "should accept {:type(s) => /T1/, :methods => [m, ...]} " do
655
+ @pointcut_hash = {:type => /Watchful/, :methods => [:public_watchful_method]}
656
+ do_type_pointcut_spec
657
+ end
658
+
659
+ it "should accept {:type(s) => /T1/, :methods => m} " do
660
+ @pointcut_hash = {:type => /Watchful/, :methods => :public_watchful_method}
661
+ do_type_pointcut_spec
662
+ end
663
+
664
+ it "should accept {:type(s) => /T1/, :methods => /m/} " do
665
+ @pointcut_hash = {:type => /Watchful/, :methods => /watchful_method/}
666
+ do_type_pointcut_spec
667
+ end
668
+
669
+ %w[public protected private].each do |protection|
670
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:instance, #{protection}]} " do
671
+ @protection = protection
672
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/, :method_options =>[:instance, protection.intern]}
673
+ do_type_pointcut_spec
674
+ end
675
+ end
676
+
677
+ %w[public private].each do |protection|
678
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:class, #{protection}]} " do
679
+ @pointcut_hash = {:type => Watchful, :methods => /class_watchful_method/, :method_options =>[:class, protection.intern]}
680
+ @protection = protection
681
+ @are_class_methods = true
682
+ do_type_pointcut_spec
683
+ end
684
+ end
685
+
686
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:instance]} defaults to public methods" do
687
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/, :method_options =>[:instance]}
688
+ do_type_pointcut_spec
689
+ end
690
+
691
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:class]} defaults to public class methods" do
692
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/, :method_options =>[:class]}
693
+ @are_class_methods = true
694
+ do_type_pointcut_spec
695
+ end
696
+ end
697
+
698
+ describe Aspect, "#new with a :pointcut parameter taking a hash with object specifications" do
699
+ before :each do
700
+ @protection = 'public'
701
+ @expected_advice_count = 2
702
+ @watchful1 = Watchful.new
703
+ @watchful2 = Watchful.new
704
+ end
705
+
706
+ def do_object_pointcut_spec
707
+ aspect = nil
708
+ advice_count = 0
709
+ aspect = Aspect.new :before, :pointcut => @pointcut_hash do |jp, *args|
710
+ advice_count += 1
711
+ jp.should_not be_nil
712
+ args.size.should == 4
713
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
714
+ end
715
+ @watchful1.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
716
+ @watchful2.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
717
+ advice_count.should == @expected_advice_count
718
+ aspect.unadvise
719
+ end
720
+
721
+ it "should accept {:objects => [o1, ...], :methods => [m, ...]} " do
722
+ @pointcut_hash = {:objects => [@watchful1, @watchful2], :methods => [:public_watchful_method]}
723
+ do_object_pointcut_spec
724
+ end
725
+
726
+ it "should accept {:objects => [o1, ...], :methods => m} " do
727
+ @pointcut_hash = {:objects => [@watchful1, @watchful2], :methods => :public_watchful_method}
728
+ do_object_pointcut_spec
729
+ end
730
+
731
+ it "should accept {:objects => [o1, ...], :methods => /m/} " do
732
+ @pointcut_hash = {:objects => [@watchful1, @watchful2], :methods => /watchful_method/}
733
+ do_object_pointcut_spec
734
+ end
735
+
736
+ it "should accept {:object => o1, :methods => [m, ...]} " do
737
+ @expected_advice_count = 1
738
+ @pointcut_hash = {:object => @watchful1, :methods => [:public_watchful_method]}
739
+ do_object_pointcut_spec
740
+ end
741
+
742
+ it "should accept {:objects => o1, :methods => m} " do
743
+ @expected_advice_count = 1
744
+ @pointcut_hash = {:objects => @watchful1, :methods => :public_watchful_method}
745
+ do_object_pointcut_spec
746
+ end
747
+
748
+ it "should accept {:objects => o1, :methods => /m/} " do
749
+ @expected_advice_count = 1
750
+ @pointcut_hash = {:objects => @watchful1, :methods => /watchful_method/}
751
+ do_object_pointcut_spec
752
+ end
753
+ end
754
+
755
+ describe Aspect, "#new with a :pointcut parameter and a Pointcut object or an array of Pointcuts" do
756
+ def do_pointcut_pointcut_spec
757
+ aspect = nil
758
+ advice_called = false
759
+ aspect = Aspect.new :before, :pointcut => @pointcuts do |jp, *args|
760
+ advice_called = true
761
+ jp.should_not be_nil
762
+ args.size.should == 4
763
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
764
+ end
765
+ Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
766
+ advice_called.should be_true
767
+ aspect.unadvise
768
+ end
769
+
770
+ it "should accept a single Pointcut object." do
771
+ @pointcuts = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
772
+ do_pointcut_pointcut_spec
773
+ end
774
+
775
+ it "should accept an array of Pointcut objects." do
776
+ pointcut1 = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
777
+ pointcut2 = Pointcut.new :type => [Watchful], :methods => :public_class_watchful_method, :method_options => [:class]
778
+ @pointcuts = [pointcut1, pointcut2]
779
+ do_pointcut_pointcut_spec
780
+ end
781
+ end
782
+
783
+ describe Aspect, "#new with a :pointcut parameter and an array of Pointcuts" do
784
+ it "should treat the array as if it is one Pointcut \"or'ed\" together." do
785
+ advice_called = 0
786
+ advice = Proc.new {|jp, *args|
787
+ advice_called += 1
788
+ jp.should_not be_nil
789
+ args.size.should == 4
790
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
791
+ }
792
+ pointcut1 = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
793
+ pointcut2 = Pointcut.new :type => [Watchful], :methods => :public_class_watchful_method, :method_options => [:class]
794
+ pointcut12 = pointcut1.or pointcut2
795
+ aspect1 = Aspect.new :before, :pointcut => [pointcut1, pointcut2], :advice => advice
796
+ Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
797
+ Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
798
+ advice_called.should == 2
799
+ aspect1.unadvise
800
+ advice_called = 0
801
+ aspect2 = Aspect.new :before, :pointcut => pointcut12, :advice => advice
802
+ Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
803
+ Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
804
+ advice_called.should == 2
805
+ aspect2.unadvise
806
+ aspect1.join_points_matched.should eql(aspect2.join_points_matched)
807
+ end
808
+ end
809
+
810
+ describe Aspect, "#new with a :type(s) parameter and a :method(s) parameter or one of several equivalent :pointcut parameters" do
61
811
  before :each do
62
812
  @advice = proc {|jp,*args| "advice"}
63
813
  @expected_methods = [:public_watchful_method]
@@ -79,7 +829,7 @@ describe Aspect, "#new arguments for specifying the types and methods" do
79
829
  @aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
80
830
  aspects_should_be_equal 1, @aspect1, @aspect2
81
831
  end
82
-
832
+
83
833
  it "should advise equivalent join points when :pointcut =>{:type => T, :method => m} is used or :pointcut => pointcut is used, where pointcut matches :type => T and :method => m." do
84
834
  @aspect1 = Aspect.new :after, :pointcut => {:type => Watchful, :method => :public_watchful_method}, &@advice
85
835
  pointcut = Aquarium::Aspects::Pointcut.new :type => Watchful, :method => :public_watchful_method
@@ -95,11 +845,8 @@ describe Aspect, "#new arguments for specifying the types and methods" do
95
845
  end
96
846
  end
97
847
 
98
- describe Aspect, "#new arguments for specifying the types and attributes" do
848
+ describe Aspect, "#new with a :type(s) parameter and an :attributes(s) parameter or one of several equivalent :pointcut parameters" do
99
849
  class ClassWithAttrib1
100
- def initialize *args
101
- @state = args
102
- end
103
850
  def dummy; end
104
851
  attr_accessor :state
105
852
  end
@@ -140,7 +887,6 @@ describe Aspect, "#new arguments for specifying the types and attributes" do
140
887
  end
141
888
 
142
889
  it "should advise equivalent join points when :type => T and :attribute => a (the attribute's reader and writer) is used or :pointcut => [join_points] is used, where the join_points match :type => T and :method => :a and :method => :a=." do
143
- # pending "working on Pointcut.new first."
144
890
  @aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, &@advice
145
891
  join_point1 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state
146
892
  join_point2 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state=
@@ -149,7 +895,6 @@ describe Aspect, "#new arguments for specifying the types and attributes" do
149
895
  end
150
896
 
151
897
  it "should advise an equivalent join point when :type => T and :method => :a= (the attribute's writer) is used or :pointcut => join_point is used, where join_point matches :type => T and :method => a=." do
152
- # pending "working on Pointcut.new first."
153
898
  @aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, :attribute_options => [:writer], &@advice
154
899
  join_point = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state=
155
900
  @aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
@@ -157,7 +902,7 @@ describe Aspect, "#new arguments for specifying the types and attributes" do
157
902
  end
158
903
  end
159
904
 
160
- describe Aspect, "#new arguments for specifying the objects and methods" do
905
+ describe Aspect, "#new with a :object(s) parameter and a :method(s) parameter or one of several equivalent :pointcut parameters" do
161
906
  before :each do
162
907
  @advice = proc {|jp,*args| "advice"}
163
908
  @expected_methods = [:public_watchful_method]
@@ -191,7 +936,7 @@ describe Aspect, "#new arguments for specifying the objects and methods" do
191
936
  end
192
937
  end
193
938
 
194
- describe Aspect, "#new arguments for specifying the objects and attributes" do
939
+ describe Aspect, "#new with a :object(s) parameter and an :attributes(s) parameter or one of several equivalent :pointcut parameters" do
195
940
  class ClassWithAttrib2
196
941
  def initialize *args
197
942
  @state = args
@@ -237,7 +982,6 @@ describe Aspect, "#new arguments for specifying the objects and attributes" do
237
982
  end
238
983
 
239
984
  it "should advise equivalent join points when :type => T and :attribute => a (the attribute's reader and writer) is used or :pointcut => [join_points] is used, where the join_points match :type => T and :method => :a and :method => :a=." do
240
- # pending "working on Pointcut.new first."
241
985
  @aspect1 = Aspect.new :after, :object => @object, :attribute => :state, &@advice
242
986
  join_point1 = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state
243
987
  join_point2 = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state=
@@ -246,7 +990,6 @@ describe Aspect, "#new arguments for specifying the objects and attributes" do
246
990
  end
247
991
 
248
992
  it "should advise an equivalent join point when :type => T and :method => :a= (the attribute's writer) is used or :pointcut => join_point is used, where join_point matches :type => T and :method => a=." do
249
- # pending "working on Pointcut.new first."
250
993
  @aspect1 = Aspect.new :after, :object => @object, :attribute => :state, :attribute_options => [:writer], &@advice
251
994
  join_point = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state=
252
995
  @aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
@@ -254,3 +997,563 @@ describe Aspect, "#new arguments for specifying the objects and attributes" do
254
997
  end
255
998
  end
256
999
 
1000
+ describe Aspect, "#new block for advice" do
1001
+ it "should accept a block as the advice to use." do
1002
+ watchful = Watchful.new
1003
+ advice_called = false
1004
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method do |jp, *args|
1005
+ advice_called = true
1006
+ jp.should_not be_nil
1007
+ args.size.should == 4
1008
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
1009
+ end
1010
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
1011
+ advice_called.should be_true
1012
+ aspect.unadvise
1013
+ end
1014
+
1015
+ it "should accept an :advice => Proc parameter indicating the advice to use." do
1016
+ watchful = Watchful.new
1017
+ advice_called = false
1018
+ advice = Proc.new {|jp, *args|
1019
+ advice_called = true
1020
+ jp.should_not be_nil
1021
+ args.size.should == 4
1022
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
1023
+ }
1024
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice
1025
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
1026
+ advice_called.should be_true
1027
+ aspect.unadvise
1028
+ end
1029
+
1030
+ it "should accept a :call => Proc parameter as a synonym for :advice." do
1031
+ watchful = Watchful.new
1032
+ advice_called = false
1033
+ advice = Proc.new {|jp, *args|
1034
+ advice_called = true
1035
+ jp.should_not be_nil
1036
+ args.size.should == 4
1037
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
1038
+ }
1039
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :call => advice
1040
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
1041
+ advice_called.should be_true
1042
+ aspect.unadvise
1043
+ end
1044
+
1045
+ it "should accept a :invoke => Proc parameter as a synonym for :advice." do
1046
+ watchful = Watchful.new
1047
+ advice_called = false
1048
+ advice = Proc.new {|jp, *args|
1049
+ advice_called = true
1050
+ jp.should_not be_nil
1051
+ args.size.should == 4
1052
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
1053
+ }
1054
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :invoke => advice
1055
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
1056
+ advice_called.should be_true
1057
+ aspect.unadvise
1058
+ end
1059
+
1060
+ it "should accept a :advise_with => Proc parameter as a synonym for :advice." do
1061
+ watchful = Watchful.new
1062
+ advice_called = false
1063
+ advice = Proc.new {|jp, *args|
1064
+ advice_called = true
1065
+ jp.should_not be_nil
1066
+ args.size.should == 4
1067
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
1068
+ }
1069
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advise_with => advice
1070
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
1071
+ advice_called.should be_true
1072
+ aspect.unadvise
1073
+ end
1074
+
1075
+ it "should ignore all other advice parameters if a block is given." do
1076
+ watchful = Watchful.new
1077
+ advice_called = false
1078
+ advice1 = Proc.new {|jp, *args| fail "advice1"}
1079
+ advice2 = Proc.new {|jp, *args| fail "advice2"}
1080
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice1, :invoke => advice2 do |jp, *args|
1081
+ advice_called = true
1082
+ end
1083
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
1084
+ advice_called.should be_true
1085
+ aspect.unadvise
1086
+ end
1087
+
1088
+ it "should ignore all but the last advice parameter, using any synonym, if there is no advice block." do
1089
+ watchful = Watchful.new
1090
+ advice_called = false
1091
+ advice1 = Proc.new {|jp, *args|
1092
+ advice_called = true
1093
+ jp.should_not be_nil
1094
+ args.size.should == 4
1095
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
1096
+ }
1097
+ advice2 = Proc.new {|jp, *args| raise "should not be called"}
1098
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice2, :advice => advice1
1099
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
1100
+ advice_called.should be_true
1101
+ aspect.unadvise
1102
+ end
1103
+ end
1104
+
1105
+
1106
+ class ExcludeBase
1107
+ def doit; end
1108
+ def initialize arg; @value = arg; end
1109
+ attr_accessor :value
1110
+ def inspect; "(#{self.class}: #{@value})"; end
1111
+ def eql? other
1112
+ return false unless other.kind_of?(self.class)
1113
+ @value == other.value
1114
+ end
1115
+ alias_method :==, :eql?
1116
+ end
1117
+ class DontExclude1 < ExcludeBase; end
1118
+ class DontExclude2 < ExcludeBase; end
1119
+ class Exclude1 < ExcludeBase; end
1120
+ class Exclude2 < ExcludeBase; end
1121
+
1122
+ class Exclude1b < Exclude1
1123
+ def initialize arg; super(arg); end
1124
+ def doit2; end
1125
+ end
1126
+ class Exclude1c < Exclude1
1127
+ def initialize arg; super(arg); end
1128
+ def doit3; end
1129
+ end
1130
+
1131
+ describe Aspect, "#new with a :type(s) parameter and an :exclude_type(s) parameter" do
1132
+ def do_exclude_types exclude_type_sym
1133
+ included_types = [DontExclude1, DontExclude2]
1134
+ excluded_types = [Exclude1, Exclude2]
1135
+ aspect = nil
1136
+ advice_called = false
1137
+ aspect = Aspect.new :before, :types => (included_types + excluded_types), exclude_type_sym => excluded_types, :methods => :doit do |jp, *args|
1138
+ advice_called = true
1139
+ excluded_types.should_not include(jp.target_type)
1140
+ end
1141
+ included_types.each do |type|
1142
+ advice_called = false
1143
+ type.new(1).doit
1144
+ advice_called.should be_true
1145
+ end
1146
+ excluded_types.each do |type|
1147
+ advice_called = false
1148
+ type.new(1).doit
1149
+ advice_called.should_not be_true
1150
+ end
1151
+ aspect.unadvise
1152
+ end
1153
+
1154
+ it "should accept :type(s) => [T1, ...], :exclude_type(s) => [T2, ...] and exclude join points in the excluded types" do
1155
+ do_exclude_types :exclude_types
1156
+ end
1157
+
1158
+ it "should accept :exclude_type as a synonym for :exclude_types" do
1159
+ do_exclude_types :exclude_type
1160
+ end
1161
+ end
1162
+
1163
+
1164
+ describe Aspect, "#new with a :object(s) parameter and an :exclude_object(s) parameter" do
1165
+ def do_exclude_objects exclude_object_sym
1166
+ dontExclude1 = DontExclude1.new(1)
1167
+ dontExclude2 = DontExclude1.new(2)
1168
+ exclude1 = DontExclude1.new(3)
1169
+ exclude2 = DontExclude1.new(4)
1170
+ included_objects = [dontExclude1, dontExclude2]
1171
+ excluded_objects = [exclude1, exclude2]
1172
+ aspect = nil
1173
+ advice_called = false
1174
+ aspect = Aspect.new :before, :objects => (included_objects + excluded_objects), exclude_object_sym => excluded_objects, :methods => :doit do |jp, *args|
1175
+ advice_called = true
1176
+ excluded_objects.should_not include(jp.context.advised_object)
1177
+ end
1178
+ included_objects.each do |object|
1179
+ advice_called = false
1180
+ object.doit
1181
+ advice_called.should be_true
1182
+ end
1183
+ excluded_objects.each do |object|
1184
+ advice_called = false
1185
+ object.doit
1186
+ advice_called.should_not be_true
1187
+ end
1188
+ aspect.unadvise
1189
+ end
1190
+
1191
+ it "should accept :object(s) => [o1, ...], :exclude_object(s) => [o2, ...] and exclude join points in the excluded objects" do
1192
+ do_exclude_objects :exclude_objects
1193
+ end
1194
+
1195
+ it "should accept :exclude_object as a synonym for :exclude_objects" do
1196
+ do_exclude_objects :exclude_object
1197
+ end
1198
+ end
1199
+
1200
+
1201
+ describe Aspect, "#new with a :pointcut(s), :type(s), :object(s), and :method(s) parameter and an :exclude_join_point(s) parameter" do
1202
+ def do_exclude_join_points exclude_join_points_sym
1203
+ dontExclude1 = DontExclude1.new(1)
1204
+ dontExclude2 = DontExclude1.new(2)
1205
+ exclude1 = DontExclude1.new(3)
1206
+ exclude2 = DontExclude1.new(4)
1207
+ included_objects = [dontExclude1, dontExclude2]
1208
+ excluded_objects = [exclude1, exclude2]
1209
+ excluded_join_point1 = JoinPoint.new :object => exclude1, :method => :doit
1210
+ excluded_join_point2 = JoinPoint.new :object => exclude2, :method => :doit
1211
+ excluded_join_points = [excluded_join_point1, excluded_join_point2]
1212
+ aspect = nil
1213
+ advice_called = false
1214
+ aspect = Aspect.new :before, :objects => (included_objects + excluded_objects), exclude_join_points_sym => excluded_join_points, :methods => :doit do |jp, *args|
1215
+ advice_called = true
1216
+ excluded_objects.should_not include(jp.context.advised_object)
1217
+ end
1218
+
1219
+ included_objects.each do |object|
1220
+ advice_called = false
1221
+ object.doit
1222
+ advice_called.should be_true
1223
+ end
1224
+ excluded_objects.each do |object|
1225
+ advice_called = false
1226
+ object.doit
1227
+ advice_called.should_not be_true
1228
+ end
1229
+ aspect.unadvise
1230
+ end
1231
+
1232
+ it "should accept :exclude_join_point as a synonym for :exclude_join_points" do
1233
+ do_exclude_join_points :exclude_join_point
1234
+ end
1235
+
1236
+ it "should accept :object(s) => [o1, ...], :exclude_join_point(s) => [jps], where [jps] are the list of join points for the objects and methods to exclude" do
1237
+ do_exclude_join_points :exclude_join_points
1238
+ end
1239
+
1240
+ it "should accept :type(s) => [T1, ...], :exclude_join_point(s) => [jps], where [jps] are the list of join points for the types and methods to exclude" do
1241
+ included_types = [DontExclude1, DontExclude2]
1242
+ excluded_types = [Exclude1, Exclude2]
1243
+ excluded_join_point1 = JoinPoint.new :type => Exclude1, :method => :doit
1244
+ excluded_join_point2 = JoinPoint.new :type => Exclude2, :method => :doit
1245
+ excluded_join_points = [excluded_join_point1, excluded_join_point2]
1246
+ aspect = nil
1247
+ advice_called = false
1248
+ aspect = Aspect.new :before, :types => (included_types + excluded_types), :exclude_join_points => excluded_join_points, :methods => :doit do |jp, *args|
1249
+ advice_called = true
1250
+ excluded_types.should_not include(jp.target_type)
1251
+ end
1252
+
1253
+ included_types.each do |type|
1254
+ advice_called = false
1255
+ type.new(1).doit
1256
+ advice_called.should be_true
1257
+ end
1258
+ excluded_types.each do |type|
1259
+ advice_called = false
1260
+ type.new(1).doit
1261
+ advice_called.should_not be_true
1262
+ end
1263
+ aspect.unadvise
1264
+ end
1265
+
1266
+ it "should accept :pointcut(s) => [P1, ...], :exclude_join_point(s) => [jps], where [jps] are the list of join points for the types and methods to exclude" do
1267
+ included_types = [DontExclude1, DontExclude2]
1268
+ excluded_types = [Exclude1, Exclude2]
1269
+ excluded_join_point1 = JoinPoint.new :type => Exclude1, :method => :doit
1270
+ excluded_join_point2 = JoinPoint.new :type => Exclude2, :method => :doit
1271
+ excluded_join_points = [excluded_join_point1, excluded_join_point2]
1272
+ pointcut1 = Pointcut.new :types => included_types, :method => :doit
1273
+ pointcut2 = Pointcut.new :types => excluded_types, :method => :doit
1274
+ aspect = nil
1275
+ advice_called = false
1276
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_join_points => excluded_join_points do |jp, *args|
1277
+ advice_called = true
1278
+ excluded_types.should_not include(jp.target_type)
1279
+ end
1280
+ included_types.each do |type|
1281
+ advice_called = false
1282
+ type.new(1).doit
1283
+ advice_called.should be_true
1284
+ end
1285
+ excluded_types.each do |type|
1286
+ advice_called = false
1287
+ type.new(1).doit
1288
+ advice_called.should_not be_true
1289
+ end
1290
+ aspect.unadvise
1291
+ end
1292
+ end
1293
+
1294
+ describe Aspect, "#new with a :pointcut(s), :type(s), :object(s), and :method(s) parameter and an :exclude_pointcut(s) parameter" do
1295
+ def do_exclude_pointcuts exclude_pointcuts_sym
1296
+ dontExclude1 = DontExclude1.new(1)
1297
+ dontExclude2 = DontExclude1.new(2)
1298
+ exclude1 = DontExclude1.new(3)
1299
+ exclude2 = DontExclude1.new(4)
1300
+ included_objects = [dontExclude1, dontExclude2]
1301
+ excluded_objects = [exclude1, exclude2]
1302
+ excluded_pointcut1 = Pointcut.new :object => exclude1, :method => :doit
1303
+ excluded_pointcut2 = Pointcut.new :object => exclude2, :method => :doit
1304
+ excluded_pointcuts = [excluded_pointcut1, excluded_pointcut2]
1305
+ aspect = nil
1306
+ advice_called = false
1307
+ aspect = Aspect.new :before, :objects => (included_objects + excluded_objects), exclude_pointcuts_sym => excluded_pointcuts, :methods => :doit do |jp, *args|
1308
+ advice_called = true
1309
+ excluded_objects.should_not include(jp.context.advised_object)
1310
+ end
1311
+
1312
+ included_objects.each do |object|
1313
+ advice_called = false
1314
+ object.doit
1315
+ advice_called.should be_true
1316
+ end
1317
+ excluded_objects.each do |object|
1318
+ advice_called = false
1319
+ object.doit
1320
+ advice_called.should_not be_true
1321
+ end
1322
+ aspect.unadvise
1323
+ end
1324
+
1325
+ it "should accept :exclude_pointcut as a synonym for :exclude_pointcuts" do
1326
+ do_exclude_pointcuts :exclude_pointcut
1327
+ end
1328
+
1329
+ it "should accept :object(s) => [o1, ...], :exclude_pointcut(s) => [pcs], where [pcs] are the list of pointcuts for the objects and methods to exclude" do
1330
+ do_exclude_pointcuts :exclude_pointcuts
1331
+ end
1332
+
1333
+ it "should accept :type(s) => [T1, ...], :exclude_pointcut(s) => [pcs], where [pcs] are the list of pointcuts for the types and methods to exclude" do
1334
+ included_types = [DontExclude1, DontExclude2]
1335
+ excluded_types = [Exclude1, Exclude2]
1336
+ excluded_pointcut1 = Pointcut.new :type => Exclude1, :method => :doit
1337
+ excluded_pointcut2 = Pointcut.new :type => Exclude2, :method => :doit
1338
+ excluded_pointcuts = [excluded_pointcut1, excluded_pointcut2]
1339
+ aspect = nil
1340
+ advice_called = false
1341
+ aspect = Aspect.new :before, :types => (included_types + excluded_types), :exclude_pointcuts => excluded_pointcuts, :methods => :doit do |jp, *args|
1342
+ advice_called = true
1343
+ excluded_types.should_not include(jp.target_type)
1344
+ end
1345
+
1346
+ included_types.each do |type|
1347
+ advice_called = false
1348
+ type.new(1).doit
1349
+ advice_called.should be_true
1350
+ end
1351
+ excluded_types.each do |type|
1352
+ advice_called = false
1353
+ type.new(1).doit
1354
+ advice_called.should_not be_true
1355
+ end
1356
+ aspect.unadvise
1357
+ end
1358
+
1359
+ it "should accept :pointcut(s) => [P1, ...], :exclude_pointcut(s) => [pcs], where [pcs] are the list of pointcuts for the types and methods to exclude" do
1360
+ included_types = [DontExclude1, DontExclude2]
1361
+ excluded_types = [Exclude1, Exclude2]
1362
+ excluded_pointcut1 = Pointcut.new :type => Exclude1, :method => :doit
1363
+ excluded_pointcut2 = Pointcut.new :type => Exclude2, :method => :doit
1364
+ excluded_pointcuts = [excluded_pointcut1, excluded_pointcut2]
1365
+ pointcut1 = Pointcut.new :types => included_types, :method => :doit
1366
+ pointcut2 = Pointcut.new :types => excluded_types, :method => :doit
1367
+ aspect = nil
1368
+ advice_called = false
1369
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_pointcuts => excluded_pointcuts do |jp, *args|
1370
+ advice_called = true
1371
+ excluded_types.should_not include(jp.target_type)
1372
+ end
1373
+ included_types.each do |type|
1374
+ advice_called = false
1375
+ type.new(1).doit
1376
+ advice_called.should be_true
1377
+ end
1378
+ excluded_types.each do |type|
1379
+ advice_called = false
1380
+ type.new(1).doit
1381
+ advice_called.should_not be_true
1382
+ end
1383
+ aspect.unadvise
1384
+ end
1385
+ end
1386
+
1387
+ describe Aspect, "#new with type-based :pointcut(s) and :exclude_type(s) parameter" do
1388
+
1389
+ it "should accept :pointcut(s) => [P1, ...], :exclude_type(s) => [types], where join points with [types] are excluded" do
1390
+ included_types = [DontExclude1, DontExclude2]
1391
+ excluded_types = [Exclude1, Exclude2]
1392
+ pointcut1 = Pointcut.new :types => included_types, :method => :doit
1393
+ pointcut2 = Pointcut.new :types => excluded_types, :method => :doit
1394
+ aspect = nil
1395
+ advice_called = false
1396
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_types => excluded_types do |jp, *args|
1397
+ advice_called = true
1398
+ excluded_types.should_not include(jp.target_type)
1399
+ end
1400
+
1401
+ included_types.each do |type|
1402
+ advice_called = false
1403
+ type.new(1).doit
1404
+ advice_called.should be_true
1405
+ end
1406
+ excluded_types.each do |type|
1407
+ advice_called = false
1408
+ type.new(1).doit
1409
+ advice_called.should_not be_true
1410
+ end
1411
+ aspect.unadvise
1412
+ end
1413
+ end
1414
+
1415
+
1416
+ describe Aspect, "#new with object-based :pointcut(s) and :exclude_object(s) or :exclude_method(s) parameter" do
1417
+
1418
+ it "should accept :pointcut(s) => [P1, ...], :exclude_object(s) => [objects], where join points with [objects] are excluded" do
1419
+ dontExclude1 = DontExclude1.new(1)
1420
+ dontExclude2 = DontExclude1.new(2)
1421
+ exclude1 = DontExclude1.new(3)
1422
+ exclude2 = DontExclude1.new(4)
1423
+ included_objects = [dontExclude1, dontExclude2]
1424
+ excluded_objects = [exclude1, exclude2]
1425
+ pointcut1 = Pointcut.new :objects => included_objects, :method => :doit
1426
+ pointcut2 = Pointcut.new :objects => excluded_objects, :method => :doit
1427
+ aspect = nil
1428
+ advice_called = false
1429
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_objects => excluded_objects do |jp, *args|
1430
+ advice_called = true
1431
+ excluded_objects.should_not include(jp.context.advised_object)
1432
+ end
1433
+ included_objects.each do |object|
1434
+ advice_called = false
1435
+ object.doit
1436
+ advice_called.should be_true
1437
+ end
1438
+ excluded_objects.each do |object|
1439
+ advice_called = false
1440
+ object.doit
1441
+ advice_called.should_not be_true
1442
+ end
1443
+ aspect.unadvise
1444
+ end
1445
+ end
1446
+
1447
+ describe Aspect, "#new with :method(s) and :exclude_method(s) parameter" do
1448
+ before :each do
1449
+ @dontExclude1 = DontExclude1.new(1)
1450
+ @dontExclude2 = DontExclude1.new(2)
1451
+ @exclude1 = DontExclude1.new(3)
1452
+ @exclude2 = DontExclude1.new(4)
1453
+ @exclude1c = Exclude1c.new(5)
1454
+ @included_objects = [@dontExclude1, @dontExclude2, @exclude1, @exclude2]
1455
+ @excluded_objects = [@exclude1c]
1456
+ @included_types = [DontExclude1, DontExclude2, Exclude1, Exclude2]
1457
+ @excluded_types = [Exclude1c]
1458
+ @excluded_methods = [:doit3]
1459
+ @pointcut1 = Pointcut.new :objects => @included_objects, :method => /doit/
1460
+ @pointcut2 = Pointcut.new :objects => @excluded_objects, :method => /doit/
1461
+ @pointcut3 = Pointcut.new :types => @included_types, :method => /doit/
1462
+ @pointcut4 = Pointcut.new :types => @excluded_types, :method => /doit/
1463
+ end
1464
+
1465
+ def do_method_exclusion parameter_hash, types_were_specified
1466
+ parameter_hash[:before] = ''
1467
+ parameter_hash[:exclude_method] = :doit3
1468
+ aspect = nil
1469
+ advice_called = false
1470
+ aspect = Aspect.new parameter_hash do |jp, *args|
1471
+ advice_called = true
1472
+ @excluded_methods.should_not include(jp.method_name)
1473
+ end
1474
+ if types_were_specified
1475
+ (@included_types + @excluded_types).each do |type|
1476
+ advice_called = false
1477
+ type.new(1).doit
1478
+ advice_called.should be_true
1479
+ end
1480
+ @excluded_types.each do |type|
1481
+ advice_called = false
1482
+ type.new(1).doit3
1483
+ advice_called.should_not be_true
1484
+ end
1485
+ end
1486
+ (@included_objects + @excluded_objects).each do |object|
1487
+ advice_called = false
1488
+ object.doit
1489
+ advice_called.should be_true
1490
+ end
1491
+ @excluded_objects.each do |object|
1492
+ advice_called = false
1493
+ object.doit3
1494
+ advice_called.should_not be_true
1495
+ end
1496
+ aspect.unadvise
1497
+ end
1498
+
1499
+ it "should accept :exclude_method as a synonym for exclude_methods" do
1500
+ parameter_hash = { :pointcuts => [@pointcut1, @pointcut2, @pointcut3, @pointcut4] }
1501
+ do_method_exclusion parameter_hash, true
1502
+ end
1503
+
1504
+ it "should accept :pointcut(s) => [P1, ...], :exclude_method(s) => [methods], where join points with [methods] are excluded" do
1505
+ parameter_hash = { :pointcuts => [@pointcut1, @pointcut2, @pointcut3, @pointcut4] }
1506
+ do_method_exclusion parameter_hash, true
1507
+ end
1508
+
1509
+ it "should accept :type(s) => ..., :method(s) => ..., :exclude_method(s) => [methods], where join points with [methods] are excluded" do
1510
+ parameter_hash = { :types => (@included_types + @excluded_types), :methods => /doit/ }
1511
+ do_method_exclusion parameter_hash, true
1512
+ end
1513
+
1514
+ # it "should accept :object(s) => ..., :method(s) => ..., :exclude_method(s) => [methods], where join points with [methods] are excluded" do
1515
+ # pending "bug fix"
1516
+ # Aspect.echo = true
1517
+ # parameter_hash = { :objects => (@included_objects + @excluded_objects), :methods => /doit/ }
1518
+ # do_method_exclusion parameter_hash, false
1519
+ # Aspect.echo = false
1520
+ # end
1521
+ #
1522
+ # def do_method_exclusion2 parameter_hash, types_were_specified
1523
+ # parameter_hash[:before] = ''
1524
+ # parameter_hash[:exclude_method] = :doit3
1525
+ # parameter_hash[:method] = /doit/
1526
+ # aspect = nil
1527
+ # advice_called = false
1528
+ # aspect = Aspect.new parameter_hash do |jp, *args|
1529
+ # advice_called = true
1530
+ # @excluded_methods.should_not include(jp.method_name)
1531
+ # end
1532
+ # (@excluded_objects).each do |object|
1533
+ # advice_called = false
1534
+ # object.doit
1535
+ # advice_called.should be_true
1536
+ # end
1537
+ # aspect.unadvise
1538
+ # end
1539
+ #
1540
+ # def buggy parameter_hash
1541
+ # parameter_hash[:before] = ''
1542
+ # parameter_hash[:exclude_method] = :doit3
1543
+ # aspect = Aspect.new parameter_hash do |jp, *args|
1544
+ # end
1545
+ # @excluded_objects.each do |object|
1546
+ # object.doit
1547
+ # end
1548
+ # aspect.unadvise
1549
+ # end
1550
+ #
1551
+ # it "#15202 bug..." do
1552
+ # pending "bug fix"
1553
+ # @pointcut5 = Pointcut.new :types => [Exclude1, Exclude1c], :method => /doit/
1554
+ # parameter_hash = { :pointcuts => [@pointcut5] } #[@pointcut1, @pointcut2, @pointcut3, @pointcut4] }
1555
+ # buggy parameter_hash
1556
+ # parameter_hash = { :objects => (@excluded_objects), :method => /doit/ }
1557
+ # buggy parameter_hash
1558
+ # end
1559
+ end