aquarium 0.1.7 → 0.1.8

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