aquarium 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +59 -2
- data/README +33 -16
- data/RELEASE-PLAN +28 -5
- data/UPGRADE +11 -0
- data/examples/aspect_design_example.rb +2 -2
- data/examples/aspect_design_example_spec.rb +2 -2
- data/examples/design_by_contract_example.rb +4 -4
- data/examples/design_by_contract_example_spec.rb +4 -4
- data/examples/method_missing_example.rb +4 -1
- data/examples/method_missing_example_spec.rb +4 -1
- data/examples/method_tracing_example.rb +2 -2
- data/examples/method_tracing_example_spec.rb +16 -16
- data/lib/aquarium/aspects/advice.rb +47 -25
- data/lib/aquarium/aspects/aspect.rb +81 -39
- data/lib/aquarium/aspects/dsl/aspect_dsl.rb +1 -1
- data/lib/aquarium/aspects/exclusion_handler.rb +2 -2
- data/lib/aquarium/aspects/join_point.rb +28 -28
- data/lib/aquarium/aspects/pointcut.rb +61 -15
- data/lib/aquarium/extras/design_by_contract.rb +7 -7
- data/lib/aquarium/finders.rb +0 -1
- data/lib/aquarium/finders/method_finder.rb +10 -20
- data/lib/aquarium/finders/type_finder.rb +141 -75
- data/lib/aquarium/utils.rb +1 -0
- data/lib/aquarium/utils/logic_error.rb +9 -0
- data/lib/aquarium/utils/method_utils.rb +4 -3
- data/lib/aquarium/utils/nil_object.rb +1 -0
- data/lib/aquarium/utils/type_utils.rb +19 -0
- data/lib/aquarium/version.rb +2 -2
- data/spec/aquarium/aspects/advice_chain_node_spec.rb +2 -2
- data/spec/aquarium/aspects/advice_spec.rb +28 -5
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +522 -289
- data/spec/aquarium/aspects/aspect_spec.rb +59 -41
- data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +7 -7
- data/spec/aquarium/aspects/aspect_with_subtypes_spec.rb +2 -2
- data/spec/aquarium/aspects/concurrent_aspects_spec.rb +1 -2
- data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +1 -1
- data/spec/aquarium/aspects/dsl/aspect_dsl_spec.rb +34 -34
- data/spec/aquarium/aspects/join_point_spec.rb +79 -0
- data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +13 -3
- data/spec/aquarium/aspects/pointcut_spec.rb +310 -63
- data/spec/aquarium/extras/design_by_contract_spec.rb +4 -4
- data/spec/aquarium/finders/method_finder_spec.rb +208 -54
- data/spec/aquarium/finders/type_finder_spec.rb +24 -88
- data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +206 -0
- data/spec/aquarium/spec_example_classes.rb +75 -12
- data/spec/aquarium/utils/logic_error_spec.rb +10 -0
- data/spec/aquarium/utils/type_utils_sample_classes.rb +203 -0
- data/spec/aquarium/utils/type_utils_spec.rb +47 -1
- metadata +48 -39
- data/lib/aquarium/finders/object_finder.rb +0 -75
- data/spec/aquarium/finders/object_finder_spec.rb +0 -231
@@ -8,7 +8,7 @@ end
|
|
8
8
|
|
9
9
|
describe "DSL method #before" do
|
10
10
|
before :each do
|
11
|
-
@advice = proc {|jp
|
11
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
12
12
|
@aspects = []
|
13
13
|
end
|
14
14
|
after :each do
|
@@ -24,7 +24,7 @@ end
|
|
24
24
|
|
25
25
|
describe "DSL method #after" do
|
26
26
|
before :each do
|
27
|
-
@advice = proc {|jp
|
27
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
28
28
|
@aspects = []
|
29
29
|
end
|
30
30
|
after :each do
|
@@ -41,7 +41,7 @@ end
|
|
41
41
|
describe "DSL method #after_raising_within_or_returning_from" do
|
42
42
|
before :each do
|
43
43
|
@dsl = DSLClass.new
|
44
|
-
@advice = proc {|jp
|
44
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
45
45
|
@aspects = []
|
46
46
|
end
|
47
47
|
after :each do
|
@@ -58,7 +58,7 @@ end
|
|
58
58
|
describe "DSL method #after_returning" do
|
59
59
|
before :each do
|
60
60
|
@dsl = DSLClass.new
|
61
|
-
@advice = proc {|jp
|
61
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
62
62
|
@aspects = []
|
63
63
|
end
|
64
64
|
after :each do
|
@@ -75,7 +75,7 @@ end
|
|
75
75
|
describe "DSL method #after_returning_from" do
|
76
76
|
before :each do
|
77
77
|
@dsl = DSLClass.new
|
78
|
-
@advice = proc {|jp
|
78
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
79
79
|
@aspects = []
|
80
80
|
end
|
81
81
|
after :each do
|
@@ -92,7 +92,7 @@ end
|
|
92
92
|
describe "DSL method #after_raising" do
|
93
93
|
before :each do
|
94
94
|
@dsl = DSLClass.new
|
95
|
-
@advice = proc {|jp
|
95
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
96
96
|
@aspects = []
|
97
97
|
end
|
98
98
|
after :each do
|
@@ -112,7 +112,7 @@ end
|
|
112
112
|
describe "DSL method #after_raising_within" do
|
113
113
|
before :each do
|
114
114
|
@dsl = DSLClass.new
|
115
|
-
@advice = proc {|jp
|
115
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
116
116
|
@aspects = []
|
117
117
|
end
|
118
118
|
after :each do
|
@@ -132,7 +132,7 @@ end
|
|
132
132
|
describe "DSL method #before_and_after" do
|
133
133
|
before :each do
|
134
134
|
@dsl = DSLClass.new
|
135
|
-
@advice = proc {|jp
|
135
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
136
136
|
@aspects = []
|
137
137
|
end
|
138
138
|
after :each do
|
@@ -149,7 +149,7 @@ end
|
|
149
149
|
describe "DSL method #before_and_after_raising_within_or_returning_from" do
|
150
150
|
before :each do
|
151
151
|
@dsl = DSLClass.new
|
152
|
-
@advice = proc {|jp
|
152
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
153
153
|
@aspects = []
|
154
154
|
end
|
155
155
|
after :each do
|
@@ -166,7 +166,7 @@ end
|
|
166
166
|
describe "DSL method #before_and_after_returning" do
|
167
167
|
before :each do
|
168
168
|
@dsl = DSLClass.new
|
169
|
-
@advice = proc {|jp
|
169
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
170
170
|
@aspects = []
|
171
171
|
end
|
172
172
|
after :each do
|
@@ -183,7 +183,7 @@ end
|
|
183
183
|
describe "DSL method #before_and_after_returning_from" do
|
184
184
|
before :each do
|
185
185
|
@dsl = DSLClass.new
|
186
|
-
@advice = proc {|jp
|
186
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
187
187
|
@aspects = []
|
188
188
|
end
|
189
189
|
after :each do
|
@@ -200,7 +200,7 @@ end
|
|
200
200
|
describe "DSL method #before_and_after_raising" do
|
201
201
|
before :each do
|
202
202
|
@dsl = DSLClass.new
|
203
|
-
@advice = proc {|jp
|
203
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
204
204
|
@aspects = []
|
205
205
|
end
|
206
206
|
after :each do
|
@@ -217,7 +217,7 @@ end
|
|
217
217
|
describe "DSL method #around" do
|
218
218
|
before :each do
|
219
219
|
@dsl = DSLClass.new
|
220
|
-
@advice = proc {|jp
|
220
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
221
221
|
@aspects = []
|
222
222
|
end
|
223
223
|
after :each do
|
@@ -243,11 +243,11 @@ describe "DSL method #advise, when determining the \"self\" to advise," do
|
|
243
243
|
class Watchful1
|
244
244
|
include Aquarium::Aspects::DSL::AspectDSL
|
245
245
|
@@watchful = Watchful1.new
|
246
|
-
@@aspect = after(:object => @@watchful, :method => :public_watchful_method) {|jp
|
246
|
+
@@aspect = after(:object => @@watchful, :method => :public_watchful_method) {|jp, obj, *args|}
|
247
247
|
def self.watchful; @@watchful; end
|
248
248
|
def self.aspect; @@aspect; end
|
249
249
|
end
|
250
|
-
@aspects << DSLClass.after(:object => Watchful1.watchful, :method => :public_watchful_method) {|jp
|
250
|
+
@aspects << DSLClass.after(:object => Watchful1.watchful, :method => :public_watchful_method) {|jp, obj, *args|}
|
251
251
|
@aspects << Watchful1.aspect
|
252
252
|
@aspects[1].join_points_matched.should == @aspects[0].join_points_matched
|
253
253
|
@aspects[1].pointcuts.should == @aspects[0].pointcuts
|
@@ -256,10 +256,10 @@ describe "DSL method #advise, when determining the \"self\" to advise," do
|
|
256
256
|
it "should ignore the default object \"self\" when a :type is specified." do
|
257
257
|
class Watchful2
|
258
258
|
include Aquarium::Aspects::DSL::AspectDSL
|
259
|
-
@@aspect = after(:type => Watchful2, :method => :public_watchful_method) {|jp
|
259
|
+
@@aspect = after(:type => Watchful2, :method => :public_watchful_method) {|jp, obj, *args|}
|
260
260
|
def self.aspect; @@aspect; end
|
261
261
|
end
|
262
|
-
@aspects << DSLClass.after(:type => Watchful2, :method => :public_watchful_method) {|jp
|
262
|
+
@aspects << DSLClass.after(:type => Watchful2, :method => :public_watchful_method) {|jp, obj, *args|}
|
263
263
|
@aspects << Watchful2.aspect
|
264
264
|
@aspects[1].join_points_matched.should == @aspects[0].join_points_matched
|
265
265
|
@aspects[1].pointcuts.should == @aspects[0].pointcuts
|
@@ -282,9 +282,9 @@ describe "DSL method #advise, when determining the type or object to advise," do
|
|
282
282
|
end
|
283
283
|
|
284
284
|
it "should infer the type as \"self\" when no :object, :type, or :pointcut is specified." do
|
285
|
-
@aspects << DSLClass.after(:type => WatchfulSelf, :method => :public_watchful_method) {|jp
|
285
|
+
@aspects << DSLClass.after(:type => WatchfulSelf, :method => :public_watchful_method) {|jp, obj, *args|}
|
286
286
|
class WatchfulSelf
|
287
|
-
@@aspect = after(:method => :public_watchful_method) {|jp
|
287
|
+
@@aspect = after(:method => :public_watchful_method) {|jp, obj, *args|}
|
288
288
|
end
|
289
289
|
@aspects << WatchfulSelf.aspect
|
290
290
|
@aspects[1].join_points_matched.should == @aspects[0].join_points_matched
|
@@ -294,14 +294,14 @@ describe "DSL method #advise, when determining the type or object to advise," do
|
|
294
294
|
it "should infer the object as \"self\" when no :object, :type, or :pointcut is specified." do
|
295
295
|
watchful_self = WatchfulSelf.new
|
296
296
|
watchful_self.extend Aquarium::Aspects::DSL::AspectDSL
|
297
|
-
@aspects <<
|
298
|
-
@aspects <<
|
297
|
+
@aspects << DSLClass.advise(:after, :pointcut => {:object => watchful_self, :method => :public_watchful_method}) {|jp, obj, *args|}
|
298
|
+
@aspects << watchful_self.after(:method => :public_watchful_method) {|jp, obj, *args|}
|
299
299
|
@aspects[1].join_points_matched.should == @aspects[0].join_points_matched
|
300
300
|
@aspects[1].pointcuts.should == @aspects[0].pointcuts
|
301
301
|
end
|
302
302
|
|
303
303
|
it "should infer no types or objects if a :pointcut => {...} parameter is used and it does not specify a type or object." do
|
304
|
-
@aspects << DSLClass.after(:pointcut => {:method => /method/}) {|jp
|
304
|
+
@aspects << DSLClass.after(:pointcut => {:method => /method/}) {|jp, obj, *args|}
|
305
305
|
@aspects[0].join_points_matched.size.should == 0
|
306
306
|
end
|
307
307
|
end
|
@@ -320,7 +320,7 @@ describe "DSL method #advise, when parsing the parameter list," do
|
|
320
320
|
end
|
321
321
|
|
322
322
|
it "should infer the first symbol parameter after the advice kind parameter to be the method name to advise if no other :method => ... parameter is used." do
|
323
|
-
@aspects << Watchful3.after(:public_watchful_method) {|jp
|
323
|
+
@aspects << Watchful3.after(:public_watchful_method) {|jp, obj, *args|}
|
324
324
|
@aspects.each do |aspect|
|
325
325
|
aspect.join_points_matched.size.should == 1
|
326
326
|
aspect.specification[:methods].should == Set.new([:public_watchful_method])
|
@@ -342,7 +342,7 @@ describe "DSL method #advise, when determining instance or class methods to advi
|
|
342
342
|
def public_watchful_method *args; end
|
343
343
|
end
|
344
344
|
advice_called = 0
|
345
|
-
WatchfulExampleWithSeparateAdviseCall.advise :before, :public_watchful_method do |jp, *args|
|
345
|
+
WatchfulExampleWithSeparateAdviseCall.advise :before, :public_watchful_method do |jp, obj, *args|
|
346
346
|
advice_called += 1
|
347
347
|
end
|
348
348
|
WatchfulExampleWithSeparateAdviseCall.new.public_watchful_method :a1, :a2
|
@@ -357,7 +357,7 @@ describe "DSL method #advise, when determining instance or class methods to advi
|
|
357
357
|
def public_watchful_method *args; end
|
358
358
|
end
|
359
359
|
advice_called = 0
|
360
|
-
WatchfulExampleWithSeparateAdviseCall2.advise :before, :type => WatchfulExampleWithSeparateAdviseCall2, :methods => /public_watchful_method/, :method_options =>[:instance] do |jp, *args|
|
360
|
+
WatchfulExampleWithSeparateAdviseCall2.advise :before, :type => WatchfulExampleWithSeparateAdviseCall2, :methods => /public_watchful_method/, :method_options =>[:instance] do |jp, obj, *args|
|
361
361
|
advice_called += 1
|
362
362
|
end
|
363
363
|
WatchfulExampleWithSeparateAdviseCall2.class_public_watchful_method :a1, :a2
|
@@ -375,7 +375,7 @@ describe "DSL method #advise, when determining instance or class methods to advi
|
|
375
375
|
def public_watchful_method *args; end
|
376
376
|
end
|
377
377
|
advice_called = 0
|
378
|
-
WatchfulExampleWithSeparateAdviseCall3.advise :before, :methods => /public_watchful_method/, :method_options =>[:class] do |jp, *args|
|
378
|
+
WatchfulExampleWithSeparateAdviseCall3.advise :before, :methods => /public_watchful_method/, :method_options =>[:class] do |jp, obj, *args|
|
379
379
|
advice_called += 1
|
380
380
|
end
|
381
381
|
WatchfulExampleWithSeparateAdviseCall3.class_public_watchful_method :a1, :a2
|
@@ -391,7 +391,7 @@ describe "DSL method #advise, when determining instance or class methods to advi
|
|
391
391
|
include Aquarium::Aspects::DSL::AspectDSL
|
392
392
|
@@advice_called = 0
|
393
393
|
def public_watchful_method *args; end
|
394
|
-
before :public_watchful_method do |jp, *args|
|
394
|
+
before :public_watchful_method do |jp, obj, *args|
|
395
395
|
@@advice_called += 1
|
396
396
|
end
|
397
397
|
def self.advice_called; @@advice_called; end
|
@@ -409,7 +409,7 @@ describe "DSL methods for the advice kind, when determining instance or class me
|
|
409
409
|
end
|
410
410
|
|
411
411
|
before :each do
|
412
|
-
@advice = proc {|jp
|
412
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
413
413
|
@aspects = []
|
414
414
|
end
|
415
415
|
after :each do
|
@@ -429,7 +429,7 @@ end
|
|
429
429
|
|
430
430
|
describe "Synonyms for :types" do
|
431
431
|
before :each do
|
432
|
-
@advice = proc {|jp
|
432
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
433
433
|
@aspects = [DSLClass.after(:noop, :types => Watchful, :methods => :public_watchful_method, &@advice)]
|
434
434
|
end
|
435
435
|
after :each do
|
@@ -454,7 +454,7 @@ end
|
|
454
454
|
|
455
455
|
describe "Synonyms for :objects" do
|
456
456
|
before :each do
|
457
|
-
@advice = proc {|jp
|
457
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
458
458
|
@aspects = [DSLClass.after(:noop, :objects => @watchful, :methods => :public_watchful_method, &@advice)]
|
459
459
|
end
|
460
460
|
after :each do
|
@@ -479,7 +479,7 @@ end
|
|
479
479
|
|
480
480
|
describe "Synonyms for :methods" do
|
481
481
|
before :each do
|
482
|
-
@advice = proc {|jp
|
482
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
483
483
|
@aspects = [DSLClass.after(:noop, :objects => @watchful, :methods => :public_watchful_method, &@advice)]
|
484
484
|
end
|
485
485
|
after :each do
|
@@ -504,7 +504,7 @@ end
|
|
504
504
|
|
505
505
|
describe "Synonyms for :pointcut" do
|
506
506
|
before :each do
|
507
|
-
@advice = proc {|jp
|
507
|
+
@advice = proc {|jp, obj, *args| "advice"}
|
508
508
|
@aspects = [DSLClass.after(:noop, :pointcut => {:objects => @watchful, :methods => :public_watchful_method}, &@advice)]
|
509
509
|
end
|
510
510
|
after :each do
|
@@ -533,7 +533,7 @@ describe "DSL method #advise (or synonyms) called within a type body" do
|
|
533
533
|
include Aquarium::Aspects::DSL::AspectDSL
|
534
534
|
@@advice_called = 0
|
535
535
|
def public_watchful_method *args; end
|
536
|
-
before :public_watchful_method do |jp, *args|
|
536
|
+
before :public_watchful_method do |jp, obj, *args|
|
537
537
|
@@advice_called += 1
|
538
538
|
end
|
539
539
|
def self.advice_called; @@advice_called; end
|
@@ -544,7 +544,7 @@ describe "DSL method #advise (or synonyms) called within a type body" do
|
|
544
544
|
class WatchfulWithMethodNotYetDefined
|
545
545
|
include Aquarium::Aspects::DSL::AspectDSL
|
546
546
|
@@advice_called = 0
|
547
|
-
before(:public_watchful_method) {|jp, *args| @@advice_called += 1}
|
547
|
+
before(:public_watchful_method) {|jp, obj, *args| @@advice_called += 1}
|
548
548
|
def public_watchful_method *args; end
|
549
549
|
def self.advice_called; @@advice_called; end
|
550
550
|
end
|
@@ -181,6 +181,85 @@ describe Aquarium::Aspects::JoinPoint, "#target_object" do
|
|
181
181
|
jp.target_object.should be_eql(example)
|
182
182
|
end
|
183
183
|
end
|
184
|
+
|
185
|
+
class InvokeOriginalClass
|
186
|
+
def invoke; @called = true; end
|
187
|
+
def called; @called; end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe Aquarium::Aspects::JoinPoint, "#proceed" do
|
191
|
+
it "should raise when the join point doesn't have a context" do
|
192
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
|
193
|
+
lambda { jp.proceed }.should raise_error(Aquarium::Aspects::JoinPoint::ContextNotDefined)
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should raise when the the context object doesn't have a 'proceed proc'" do
|
197
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
|
198
|
+
ioc = InvokeOriginalClass.new
|
199
|
+
context_opts = {
|
200
|
+
:advice_kind => :around,
|
201
|
+
:advised_object => ioc,
|
202
|
+
:parameters => [],
|
203
|
+
:proceed_proc => nil
|
204
|
+
}
|
205
|
+
jp2 = jp.make_current_context_join_point context_opts
|
206
|
+
lambda { jp2.proceed }.should raise_error(Aquarium::Aspects::JoinPoint::ProceedMethodNotAvailable)
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should not raise when the advice is :around advice" do
|
210
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
|
211
|
+
ioc = InvokeOriginalClass.new
|
212
|
+
context_opts = {
|
213
|
+
:advice_kind => :around,
|
214
|
+
:advised_object => ioc,
|
215
|
+
:parameters => [],
|
216
|
+
:proceed_proc => Aquarium::Aspects::NoAdviceChainNode.new({:alias_method_name => :invoke})
|
217
|
+
}
|
218
|
+
jp2 = jp.make_current_context_join_point context_opts
|
219
|
+
lambda { jp2.proceed }.should_not raise_error(Aquarium::Aspects::JoinPoint::ProceedMethodNotAvailable)
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should invoke the actual join point" do
|
223
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
|
224
|
+
ioc = InvokeOriginalClass.new
|
225
|
+
context_opts = {
|
226
|
+
:advice_kind => :around,
|
227
|
+
:advised_object => ioc,
|
228
|
+
:parameters => [],
|
229
|
+
:proceed_proc => Aquarium::Aspects::NoAdviceChainNode.new({:alias_method_name => :invoke})
|
230
|
+
}
|
231
|
+
jp2 = jp.make_current_context_join_point context_opts
|
232
|
+
jp2.proceed
|
233
|
+
ioc.called.should be_true
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
class InvokeOriginalClass
|
238
|
+
def invoke; @called = true; end
|
239
|
+
def called; @called; end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe Aquarium::Aspects::JoinPoint, "#invoke_original_join_point" do
|
243
|
+
it "should raise when the join point doesn't have a context" do
|
244
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
|
245
|
+
lambda { jp.invoke_original_join_point }.should raise_error(Aquarium::Aspects::JoinPoint::ContextNotDefined)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should invoke the original join point" do
|
249
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
|
250
|
+
ioc = InvokeOriginalClass.new
|
251
|
+
context_opts = {
|
252
|
+
:advice_kind => :around,
|
253
|
+
:advised_object => ioc,
|
254
|
+
:parameters => [],
|
255
|
+
:proceed_proc => Aquarium::Aspects::NoAdviceChainNode.new({:alias_method_name => :invoke})
|
256
|
+
}
|
257
|
+
jp2 = jp.make_current_context_join_point context_opts
|
258
|
+
jp2.invoke_original_join_point
|
259
|
+
ioc.called.should be_true
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
184
263
|
|
185
264
|
describe Aquarium::Aspects::JoinPoint, "#dup" do
|
186
265
|
it "should duplicate the fields in the join point." do
|
@@ -9,7 +9,15 @@ describe "Union of Pointcuts", :shared => true do
|
|
9
9
|
include Aquarium::Utils::HashUtils
|
10
10
|
|
11
11
|
before(:each) do
|
12
|
-
classes = [
|
12
|
+
classes = [
|
13
|
+
ClassWithProtectedInstanceMethod,
|
14
|
+
ClassWithPrivateInstanceMethod,
|
15
|
+
ClassWithPublicClassMethod,
|
16
|
+
ClassWithPrivateClassMethod,
|
17
|
+
ClassIncludingModuleWithPrivateClassMethod,
|
18
|
+
ClassIncludingModuleWithPublicClassMethod,
|
19
|
+
ClassIncludingModuleWithProtectedInstanceMethod,
|
20
|
+
ClassIncludingModuleWithPrivateInstanceMethod]
|
13
21
|
jps_array = classes.map {|c| Aquarium::Aspects::JoinPoint.new :type => c, :method => :all}
|
14
22
|
@not_matched_jps = Set.new(jps_array)
|
15
23
|
end
|
@@ -32,14 +40,16 @@ describe "Union of Pointcuts", :shared => true do
|
|
32
40
|
|
33
41
|
it "should return a new Aquarium::Aspects::Pointcut whose join points are the union of the left- and right-hand side Aquarium::Aspects::Pointcuts for type-based Aquarium::Aspects::Pointcuts." do
|
34
42
|
pc1 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
|
35
|
-
# "[^F]" excludes the ClassWithFunkyMethodNames...
|
43
|
+
# "[^F]" excludes the ClassWithFunkyMethodNames ...
|
36
44
|
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class[^F]+Method/, :method_options => :exclude_ancestor_methods
|
37
45
|
pc = pc1.or pc2
|
38
46
|
jp1 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs=
|
39
47
|
jp2 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrW_ClassWithAttribs=
|
40
48
|
jp3 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod, :method => :public_instance_test_method
|
41
49
|
jp4 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod2, :method => :public_instance_test_method2
|
42
|
-
|
50
|
+
jp5 = Aquarium::Aspects::JoinPoint.new :type => ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod, :method => :public_instance_class_derived_from_class_including_module_test_method
|
51
|
+
jp6 = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPublicInstanceMethod, :method => :public_instance_class_including_module_test_method
|
52
|
+
pc.join_points_matched.should == Set.new([jp1, jp2, jp3, jp4, jp5, jp6])
|
43
53
|
pc.join_points_not_matched.should == @not_matched_jps
|
44
54
|
end
|
45
55
|
|
@@ -33,10 +33,10 @@ def before_exclude_spec
|
|
33
33
|
@all_jps = @all_type_jps + @all_object_jps
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
@
|
36
|
+
def before_pointcut_class_spec
|
37
|
+
@example_classes_without_public_instance_method =
|
38
38
|
[ClassWithProtectedInstanceMethod, ClassWithPrivateInstanceMethod, ClassWithPublicClassMethod, ClassWithPrivateClassMethod]
|
39
|
-
@
|
39
|
+
@example_classes = ([ClassWithPublicInstanceMethod] + @example_classes_without_public_instance_method)
|
40
40
|
@pub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod, :method_name => :public_instance_test_method
|
41
41
|
@pro_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithProtectedInstanceMethod, :method_name => :protected_instance_test_method
|
42
42
|
@pri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPrivateInstanceMethod, :method_name => :private_instance_test_method
|
@@ -46,17 +46,64 @@ def before_pointcut_spec
|
|
46
46
|
@apri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPrivateInstanceMethod, :method_name => :all
|
47
47
|
@acpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicClassMethod, :method_name => :all
|
48
48
|
@acpri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPrivateClassMethod, :method_name => :all
|
49
|
-
@
|
50
|
-
@
|
49
|
+
@cdcimpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod, :method_name => :public_instance_class_derived_from_class_including_module_test_method
|
50
|
+
@expected_classes_matched_jps = Set.new [@pub_jp]
|
51
|
+
@expected_classes_not_matched_jps = Set.new [@apro_jp, @apri_jp, @acpub_jp, @acpri_jp]
|
51
52
|
end
|
52
53
|
|
53
|
-
|
54
|
+
def before_pointcut_module_spec
|
55
|
+
@example_modules_with_public_instance_method = [
|
56
|
+
ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod,
|
57
|
+
ClassIncludingModuleWithPublicInstanceMethod,
|
58
|
+
ModuleIncludingModuleWithPublicInstanceMethod,
|
59
|
+
ModuleWithPublicInstanceMethod]
|
60
|
+
@example_modules_without_public_instance_method = [
|
61
|
+
ClassIncludingModuleWithProtectedInstanceMethod,
|
62
|
+
ClassIncludingModuleWithPrivateInstanceMethod,
|
63
|
+
ClassIncludingModuleWithPublicClassMethod,
|
64
|
+
ClassIncludingModuleWithPrivateClassMethod,
|
65
|
+
ModuleWithProtectedInstanceMethod,
|
66
|
+
ModuleWithPrivateInstanceMethod,
|
67
|
+
ModuleWithPublicClassMethod,
|
68
|
+
ModuleWithPrivateClassMethod]
|
69
|
+
@example_modules = (@example_modules_with_public_instance_method + @example_modules_without_public_instance_method)
|
70
|
+
@mimpub_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleIncludingModuleWithPublicInstanceMethod, :method_name => :public_instance_module_including_module_test_method
|
71
|
+
@mpub_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithPublicInstanceMethod, :method_name => :public_instance_module_test_method
|
72
|
+
@mpro_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithProtectedInstanceMethod, :method_name => :protected_instance_module_test_method
|
73
|
+
@mpri_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithPrivateInstanceMethod, :method_name => :private_instance_module_test_method
|
74
|
+
@cmpub_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithPublicClassMethod, :method_name => :public_class_module_test_method, :class_method => true
|
75
|
+
@cmpri_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithPrivateClassMethod, :method_name => :private_class_module_test_method, :class_method => true
|
76
|
+
@ampro_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithProtectedInstanceMethod, :method_name => :all
|
77
|
+
@ampri_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithPrivateInstanceMethod, :method_name => :all
|
78
|
+
@acmpub_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithPublicClassMethod, :method_name => :all
|
79
|
+
@acmpri_jp = Aquarium::Aspects::JoinPoint.new :type => ModuleWithPrivateClassMethod, :method_name => :all
|
80
|
+
@cdcimpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod, :method_name => :public_instance_class_derived_from_class_including_module_test_method
|
81
|
+
@cimpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPublicInstanceMethod, :method_name => :public_instance_class_including_module_test_method
|
82
|
+
@cimpro_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithProtectedInstanceMethod, :method_name => :protected_instance_class_including_module_test_method
|
83
|
+
@cimpri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPrivateInstanceMethod, :method_name => :private_instance_class_including_module_test_method
|
84
|
+
@ccimpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPublicClassMethod, :method_name => :public_class_class_including_module_test_method, :class_method => true
|
85
|
+
@ccimpri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPrivateClassMethod, :method_name => :private_class_class_including_module_test_method, :class_method => true
|
86
|
+
@acimpro_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithProtectedInstanceMethod, :method_name => :all
|
87
|
+
@acimpri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPrivateInstanceMethod, :method_name => :all
|
88
|
+
@accimpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPublicClassMethod, :method_name => :all
|
89
|
+
@accimpri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPrivateClassMethod, :method_name => :all
|
90
|
+
@expected_modules_matched_jps = Set.new [@mimpub_jp, @mpub_jp, @cdcimpub_jp, @cimpub_jp]
|
91
|
+
@expected_modules_not_matched_jps = Set.new [@ampro_jp, @ampri_jp, @acmpub_jp, @acmpri_jp, @acimpro_jp, @acimpri_jp, @accimpub_jp, @accimpri_jp]
|
92
|
+
end
|
93
|
+
|
94
|
+
def ignored_join_point jp
|
95
|
+
# Ignore any types introduced by RSpec, other Aquarium types, and the "pretty printer" module (which Rake uses?)
|
96
|
+
jp.target_type.name =~ /^Spec/ or jp.target_type.name =~ /^Aquarium::(Aspects|Extras|Utils)/ or jp.target_type.name =~ /^PP/
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
describe Aquarium::Aspects::Pointcut, ".new (invalid arguments)" do
|
54
101
|
it "should raise if an unknown argument is specified" do
|
55
102
|
lambda { Aquarium::Aspects::Pointcut.new :foo => :bar }.should raise_error(Aquarium::Utils::InvalidOptions)
|
56
103
|
end
|
57
104
|
end
|
58
105
|
|
59
|
-
describe Aquarium::Aspects::Pointcut, "
|
106
|
+
describe Aquarium::Aspects::Pointcut, ".new (empty)" do
|
60
107
|
it "should match no join points by default." do
|
61
108
|
pc = Aquarium::Aspects::Pointcut.new
|
62
109
|
pc.should be_empty
|
@@ -121,57 +168,134 @@ describe Aquarium::Aspects::Pointcut, "#empty?" do
|
|
121
168
|
end
|
122
169
|
end
|
123
170
|
|
124
|
-
describe Aquarium::Aspects::Pointcut, " (
|
171
|
+
describe Aquarium::Aspects::Pointcut, " (classes specified using regular expressions)" do
|
125
172
|
before(:each) do
|
126
|
-
|
173
|
+
before_pointcut_class_spec
|
127
174
|
end
|
128
175
|
|
129
|
-
it "should match multiple
|
130
|
-
pc = Aquarium::Aspects::Pointcut.new :types =>
|
131
|
-
pc.join_points_matched.should == @
|
132
|
-
pc.join_points_not_matched.should == @
|
176
|
+
it "should match multiple classes using regular expressions that cover the full class names." do
|
177
|
+
pc = Aquarium::Aspects::Pointcut.new :types => /\AClass(?!IncludingModule).*Method\Z/, :method_options => :exclude_ancestor_methods
|
178
|
+
pc.join_points_matched.should == (@expected_classes_matched_jps + [@cdcimpub_jp])
|
179
|
+
pc.join_points_not_matched.should == @expected_classes_not_matched_jps
|
133
180
|
end
|
134
181
|
|
135
|
-
it "should match
|
136
|
-
pc = Aquarium::Aspects::Pointcut.new :types => /lass.*Pro.*Inst.*Met/, :method_options => [:public, :protected, :exclude_ancestor_methods]
|
182
|
+
it "should match clases using regular expressions that only cover partial class names." do
|
183
|
+
pc = Aquarium::Aspects::Pointcut.new :types => /lass(?!IncludingModule).*Pro.*Inst.*Met/, :method_options => [:public, :protected, :exclude_ancestor_methods]
|
137
184
|
pc.join_points_matched.should == Set.new([@pro_jp])
|
138
185
|
pc.join_points_not_matched.size.should == 0
|
139
186
|
end
|
140
187
|
end
|
141
188
|
|
142
|
-
describe Aquarium::Aspects::Pointcut, " (
|
189
|
+
describe Aquarium::Aspects::Pointcut, " (classes specified using names)" do
|
143
190
|
before(:each) do
|
144
|
-
|
191
|
+
before_pointcut_class_spec
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should match multiple classes using names." do
|
195
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes.map {|t| t.to_s}, :method_options => :exclude_ancestor_methods
|
196
|
+
pc.join_points_matched.should == @expected_classes_matched_jps
|
197
|
+
pc.join_points_not_matched.should == @expected_classes_not_matched_jps
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should match multiple classes using classes themselves." do
|
201
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :method_options => :exclude_ancestor_methods
|
202
|
+
pc.join_points_matched.should == @expected_classes_matched_jps
|
203
|
+
pc.join_points_not_matched.should == @expected_classes_not_matched_jps
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should match :all public instance methods for classes by default." do
|
207
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :method_options => :exclude_ancestor_methods
|
208
|
+
pc.join_points_matched.should == @expected_classes_matched_jps
|
209
|
+
pc.join_points_not_matched.should == @expected_classes_not_matched_jps
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should support MethodFinder's :exclude_ancestor_methods option when using classes." do
|
213
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :method_options => :exclude_ancestor_methods
|
214
|
+
pc.join_points_matched.should == @expected_classes_matched_jps
|
215
|
+
pc.join_points_not_matched.should == @expected_classes_not_matched_jps
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe Aquarium::Aspects::Pointcut, " (modules specified using regular expressions)" do
|
220
|
+
it "should match multiple types using regular expressions that cover the full module names." do
|
221
|
+
pc = Aquarium::Aspects::Pointcut.new :types => /\AModule.*Method\Z/, :method_options => :exclude_ancestor_methods
|
222
|
+
pc.join_points_matched.size.should == 2
|
223
|
+
pc.join_points_matched.each do |jp|
|
224
|
+
[ModuleIncludingModuleWithPublicInstanceMethod, ModuleWithPublicInstanceMethod].should include(jp.target_type)
|
225
|
+
end
|
226
|
+
pc.join_points_not_matched.size.should == 4
|
227
|
+
pc.join_points_not_matched.each do |jp|
|
228
|
+
[ModuleWithPrivateInstanceMethod, ModuleWithProtectedInstanceMethod,
|
229
|
+
ModuleWithPublicClassMethod, ModuleWithPrivateClassMethod].should include(jp.target_type)
|
230
|
+
end
|
145
231
|
end
|
232
|
+
end
|
146
233
|
|
147
|
-
|
148
|
-
|
149
|
-
pc.
|
150
|
-
pc.
|
234
|
+
describe Aquarium::Aspects::Pointcut, " (modules specified using names)" do
|
235
|
+
def do_module type_spec
|
236
|
+
pc = Aquarium::Aspects::Pointcut.new :types => type_spec, :method_options => :exclude_ancestor_methods
|
237
|
+
pc.join_points_matched.size.should == 1
|
238
|
+
pc.join_points_matched.each do |jp|
|
239
|
+
jp.target_type.should == ModuleWithPublicInstanceMethod
|
240
|
+
jp.method_name.should == :public_instance_module_test_method
|
241
|
+
end
|
242
|
+
pc.join_points_not_matched.size.should == 1
|
243
|
+
pc.join_points_not_matched.each do |jp|
|
244
|
+
jp.target_type.should == ModuleWithPublicClassMethod
|
245
|
+
jp.method_name.should == :all
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should match multiple types using module names." do
|
250
|
+
do_module ["ModuleWithPublicInstanceMethod", "ModuleWithPublicClassMethod"]
|
151
251
|
end
|
152
252
|
|
153
|
-
it "should match multiple types using
|
154
|
-
|
155
|
-
pc.join_points_matched.should == @expected_matched_jps
|
156
|
-
pc.join_points_not_matched.should == @expected_not_matched_jps
|
253
|
+
it "should match multiple types using module-name regular expressions." do
|
254
|
+
do_module /^ModuleWithPublic.*Method/
|
157
255
|
end
|
158
256
|
|
159
|
-
it "should match
|
160
|
-
|
161
|
-
|
162
|
-
|
257
|
+
it "should match multiple types using modules themselves." do
|
258
|
+
do_module [ModuleWithPublicInstanceMethod, ModuleWithPublicClassMethod]
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should match :all public instance methods for modules by default." do
|
262
|
+
do_module [ModuleWithPublicInstanceMethod, ModuleWithPublicClassMethod]
|
163
263
|
end
|
164
264
|
|
165
|
-
it "should support MethodFinder's :exclude_ancestor_methods option when using
|
166
|
-
|
167
|
-
pc.join_points_matched.should == @expected_matched_jps
|
168
|
-
pc.join_points_not_matched.should == @expected_not_matched_jps
|
265
|
+
it "should support MethodFinder's :exclude_ancestor_methods option when using modules." do
|
266
|
+
do_module [ModuleWithPublicInstanceMethod, ModuleWithPublicClassMethod]
|
169
267
|
end
|
170
268
|
end
|
171
269
|
|
270
|
+
describe Aquarium::Aspects::Pointcut, " (types and their descendents and ancestors)" do
|
271
|
+
before(:each) do
|
272
|
+
before_pointcut_module_spec
|
273
|
+
end
|
274
|
+
|
275
|
+
it "should match classes specified and their ancestor and descendent modules and classes." do
|
276
|
+
pc = Aquarium::Aspects::Pointcut.new :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/, :types_and_descendents => /^Class(Including|DerivedFrom).*Method/, :methods => :all, :method_options => :exclude_ancestor_methods
|
277
|
+
expected_types = @example_modules_with_public_instance_method + [Kernel, Module, Object]
|
278
|
+
pc.join_points_matched.each do |jp|
|
279
|
+
next if ignored_join_point(jp)
|
280
|
+
expected_types.should include(jp.target_type)
|
281
|
+
end
|
282
|
+
not_expected_types = @expected_modules_not_matched_jps.map {|jp| jp.target_type}
|
283
|
+
pc.join_points_not_matched.each do |jp|
|
284
|
+
next if ignored_join_point(jp)
|
285
|
+
not_expected_types.should include(jp.target_type)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should match modules specified, their ancestor and descendent modules, and including classes." do
|
290
|
+
pc = Aquarium::Aspects::Pointcut.new :types_and_ancestors => /^Module.*Method/, :types_and_descendents => /^Module.*Method/, :methods => :all, :method_options => :exclude_ancestor_methods
|
291
|
+
pc.join_points_matched.should == (@expected_modules_matched_jps + [@mimpub_jp])
|
292
|
+
pc.join_points_not_matched.should == @expected_modules_not_matched_jps
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
172
296
|
describe Aquarium::Aspects::Pointcut, " (objects specified)" do
|
173
297
|
before(:each) do
|
174
|
-
|
298
|
+
before_pointcut_class_spec
|
175
299
|
end
|
176
300
|
|
177
301
|
it "should match :all public instance methods for objects by default." do
|
@@ -301,6 +425,124 @@ describe Aquarium::Aspects::Pointcut, " (:exclude_types => types specified)" do
|
|
301
425
|
end
|
302
426
|
end
|
303
427
|
|
428
|
+
describe Aquarium::Aspects::Pointcut, " (exclude types and their descendents and ancestors)" do
|
429
|
+
before(:each) do
|
430
|
+
before_pointcut_module_spec
|
431
|
+
end
|
432
|
+
|
433
|
+
def check_module_ancestors pc
|
434
|
+
expected_types = [
|
435
|
+
ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod,
|
436
|
+
ClassIncludingModuleWithPublicInstanceMethod,
|
437
|
+
Kernel,
|
438
|
+
Object]
|
439
|
+
found_types = {}
|
440
|
+
pc.join_points_matched.each do |jp|
|
441
|
+
next if ignored_join_point(jp)
|
442
|
+
expected_types.should include(jp.target_type)
|
443
|
+
found_types[jp.target_type] = true
|
444
|
+
end
|
445
|
+
found_types.size.should == 4
|
446
|
+
not_expected_types = @expected_modules_not_matched_jps.map {|jp| jp.target_type}
|
447
|
+
pc.join_points_not_matched.each do |jp|
|
448
|
+
next if ignored_join_point(jp)
|
449
|
+
not_expected_types.should include(jp.target_type)
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
it "should exclude modules specified and their included modules when excluding ancestors." do
|
454
|
+
pc = Aquarium::Aspects::Pointcut.new :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
455
|
+
:exclude_types_and_ancestors => ModuleIncludingModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
456
|
+
check_module_ancestors pc
|
457
|
+
end
|
458
|
+
it "should exclude join_points whose types match an excluded ancestor modules." do
|
459
|
+
pc = Aquarium::Aspects::Pointcut.new :join_point => @mimpub_jp, :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
460
|
+
:exclude_types_and_ancestors => ModuleIncludingModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
461
|
+
check_module_ancestors pc
|
462
|
+
end
|
463
|
+
|
464
|
+
def check_module_descendents pc
|
465
|
+
expected_types = [Kernel, Object]
|
466
|
+
found_types = {}
|
467
|
+
pc.join_points_matched.each do |jp|
|
468
|
+
next if ignored_join_point(jp)
|
469
|
+
expected_types.should include(jp.target_type)
|
470
|
+
found_types[jp.target_type] = true
|
471
|
+
end
|
472
|
+
found_types.size.should == 2
|
473
|
+
not_expected_types = @expected_modules_not_matched_jps.map {|jp| jp.target_type}
|
474
|
+
pc.join_points_not_matched.each do |jp|
|
475
|
+
next if ignored_join_point(jp)
|
476
|
+
not_expected_types.should include(jp.target_type)
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
it "should exclude modules specified and their including modules and classes when excluding descendents." do
|
481
|
+
pc = Aquarium::Aspects::Pointcut.new :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
482
|
+
:exclude_types_and_descendents => ModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
483
|
+
check_module_descendents pc
|
484
|
+
end
|
485
|
+
it "should exclude join_points whose types match an excluded descendent modules." do
|
486
|
+
pc = Aquarium::Aspects::Pointcut.new :join_point => @mpub_jp, :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
487
|
+
:exclude_types_and_descendents => ModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
488
|
+
check_module_descendents pc
|
489
|
+
end
|
490
|
+
|
491
|
+
def check_class_ancestors pc
|
492
|
+
expected_types = [ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod, ModuleIncludingModuleWithPublicInstanceMethod]
|
493
|
+
found_types = {}
|
494
|
+
pc.join_points_matched.each do |jp|
|
495
|
+
next if ignored_join_point(jp)
|
496
|
+
expected_types.should include(jp.target_type)
|
497
|
+
found_types[jp.target_type] = true
|
498
|
+
end
|
499
|
+
found_types.size.should == 2
|
500
|
+
not_expected_types = @expected_modules_not_matched_jps.map {|jp| jp.target_type}
|
501
|
+
pc.join_points_not_matched.each do |jp|
|
502
|
+
next if ignored_join_point(jp)
|
503
|
+
not_expected_types.should include(jp.target_type)
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
it "should exclude classes specified and their included modules and ancestor classes when excluding ancestors." do
|
508
|
+
pc = Aquarium::Aspects::Pointcut.new :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
509
|
+
:exclude_types_and_ancestors => ClassIncludingModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
510
|
+
check_class_ancestors pc
|
511
|
+
end
|
512
|
+
it "should exclude join_points whose types match an excluded ancestor classes." do
|
513
|
+
pc = Aquarium::Aspects::Pointcut.new :join_point => @cimpub_jp, :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
514
|
+
:exclude_types_and_ancestors => ClassIncludingModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
515
|
+
check_class_ancestors pc
|
516
|
+
end
|
517
|
+
|
518
|
+
def check_class_descendents pc
|
519
|
+
expected_types = [Kernel, ModuleIncludingModuleWithPublicInstanceMethod, ModuleWithPublicInstanceMethod, Object]
|
520
|
+
found_types = {}
|
521
|
+
pc.join_points_matched.each do |jp|
|
522
|
+
next if ignored_join_point(jp)
|
523
|
+
expected_types.should include(jp.target_type)
|
524
|
+
found_types[jp.target_type] = true
|
525
|
+
end
|
526
|
+
found_types.size.should == 4
|
527
|
+
not_expected_types = @expected_modules_not_matched_jps.map {|jp| jp.target_type}
|
528
|
+
pc.join_points_not_matched.each do |jp|
|
529
|
+
next if ignored_join_point(jp)
|
530
|
+
not_expected_types.should include(jp.target_type)
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
it "should exclude classes specified and their including modules and descendent classes when excluding descendents." do
|
535
|
+
pc = Aquarium::Aspects::Pointcut.new :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
536
|
+
:exclude_types_and_descendents => ClassIncludingModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
537
|
+
check_class_descendents pc
|
538
|
+
end
|
539
|
+
it "should exclude join_points whose types match an excluded descendent types." do
|
540
|
+
pc = Aquarium::Aspects::Pointcut.new :join_point => @cimpub_jp, :types_and_ancestors => /^Class(Including|DerivedFrom).*Method/,
|
541
|
+
:exclude_types_and_descendents => ClassIncludingModuleWithPublicInstanceMethod, :methods => :all, :method_options => :exclude_ancestor_methods
|
542
|
+
check_class_descendents pc
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
304
546
|
describe Aquarium::Aspects::Pointcut, " (:exclude_objects => objects specified)" do
|
305
547
|
before(:each) do
|
306
548
|
@e11 = ExcludeTestOne.new
|
@@ -451,7 +693,7 @@ end
|
|
451
693
|
|
452
694
|
describe Aquarium::Aspects::Pointcut, " (types or objects specified with public instance methods)" do
|
453
695
|
before(:each) do
|
454
|
-
|
696
|
+
before_pointcut_class_spec
|
455
697
|
end
|
456
698
|
|
457
699
|
it "should support MethodFinder's :public and :instance options for the specified types." do
|
@@ -470,7 +712,7 @@ end
|
|
470
712
|
|
471
713
|
describe Aquarium::Aspects::Pointcut, " (types or objects specified with protected instance methods)" do
|
472
714
|
before(:each) do
|
473
|
-
|
715
|
+
before_pointcut_class_spec
|
474
716
|
end
|
475
717
|
|
476
718
|
it "should support MethodFinder's :protected and :instance options for the specified types." do
|
@@ -489,7 +731,7 @@ end
|
|
489
731
|
|
490
732
|
describe Aquarium::Aspects::Pointcut, " (types or objects specified with private instance methods)" do
|
491
733
|
before(:each) do
|
492
|
-
|
734
|
+
before_pointcut_class_spec
|
493
735
|
end
|
494
736
|
|
495
737
|
it "should support MethodFinder's :private and :instance options for the specified types." do
|
@@ -508,7 +750,7 @@ end
|
|
508
750
|
|
509
751
|
describe Aquarium::Aspects::Pointcut, " (types or objects specified with public class methods)" do
|
510
752
|
before(:each) do
|
511
|
-
|
753
|
+
before_pointcut_class_spec
|
512
754
|
end
|
513
755
|
|
514
756
|
it "should support MethodFinder's :public and :class options for the specified types." do
|
@@ -528,7 +770,7 @@ end
|
|
528
770
|
|
529
771
|
describe Aquarium::Aspects::Pointcut, " (types or objects specified with private class methods)" do
|
530
772
|
before(:each) do
|
531
|
-
|
773
|
+
before_pointcut_class_spec
|
532
774
|
end
|
533
775
|
|
534
776
|
it "should support MethodFinder's :private and :class options for the specified types." do
|
@@ -547,7 +789,7 @@ end
|
|
547
789
|
|
548
790
|
describe Aquarium::Aspects::Pointcut, " (types or objects specified with method regular expressions)" do
|
549
791
|
before(:each) do
|
550
|
-
|
792
|
+
before_pointcut_class_spec
|
551
793
|
@jp_rwe = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs=
|
552
794
|
@jp_rw = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs
|
553
795
|
@jp_we = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrW_ClassWithAttribs=
|
@@ -627,7 +869,7 @@ end
|
|
627
869
|
|
628
870
|
describe Aquarium::Aspects::Pointcut, " (types or objects specified with attribute regular expressions)" do
|
629
871
|
before(:each) do
|
630
|
-
|
872
|
+
before_pointcut_class_spec
|
631
873
|
@jp_rwe = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs=
|
632
874
|
@jp_rw = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs
|
633
875
|
@jp_we = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrW_ClassWithAttribs=
|
@@ -780,7 +1022,7 @@ end
|
|
780
1022
|
|
781
1023
|
describe Aquarium::Aspects::Pointcut, " (join points specified)" do
|
782
1024
|
before(:each) do
|
783
|
-
|
1025
|
+
before_pointcut_class_spec
|
784
1026
|
@anClassWithPublicInstanceMethod = ClassWithPublicInstanceMethod.new
|
785
1027
|
@expected_matched = [@pub_jp, @pro_jp, @pri_jp, @cpub_jp, @cpri_jp,
|
786
1028
|
Aquarium::Aspects::JoinPoint.new(:object => @anClassWithPublicInstanceMethod, :method => :public_instance_test_method)]
|
@@ -1057,18 +1299,18 @@ end
|
|
1057
1299
|
|
1058
1300
|
describe Aquarium::Aspects::Pointcut, "#candidate_types" do
|
1059
1301
|
before(:each) do
|
1060
|
-
|
1302
|
+
before_pointcut_class_spec
|
1061
1303
|
end
|
1062
1304
|
|
1063
1305
|
it "should return only candidate matching types when the input types exist." do
|
1064
|
-
pc = Aquarium::Aspects::Pointcut.new :types => @
|
1065
|
-
pc.candidate_types.matched_keys.sort {|x,y| x.to_s <=> y.to_s}.should == @
|
1306
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes
|
1307
|
+
pc.candidate_types.matched_keys.sort {|x,y| x.to_s <=> y.to_s}.should == @example_classes.sort {|x,y| x.to_s <=> y.to_s}
|
1066
1308
|
pc.candidate_types.not_matched_keys.should == []
|
1067
1309
|
end
|
1068
1310
|
|
1069
1311
|
it "should return only candidate matching types when the input type names correspond to existing types." do
|
1070
|
-
pc = Aquarium::Aspects::Pointcut.new :types => @
|
1071
|
-
pc.candidate_types.matched_keys.sort {|x,y| x.to_s <=> y.to_s}.should == @
|
1312
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes.map {|t| t.to_s}
|
1313
|
+
pc.candidate_types.matched_keys.sort {|x,y| x.to_s <=> y.to_s}.should == @example_classes.sort {|x,y| x.to_s <=> y.to_s}
|
1072
1314
|
pc.candidate_types.not_matched_keys.should == []
|
1073
1315
|
end
|
1074
1316
|
|
@@ -1079,7 +1321,7 @@ describe Aquarium::Aspects::Pointcut, "#candidate_types" do
|
|
1079
1321
|
end
|
1080
1322
|
|
1081
1323
|
it "should return no candidate matching or non-matching types when only objects are input." do
|
1082
|
-
pc = Aquarium::Aspects::Pointcut.new :objects => @
|
1324
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => @example_classes.map {|t| t.new}
|
1083
1325
|
pc.candidate_types.matched_keys.should == []
|
1084
1326
|
pc.candidate_types.not_matched_keys.should == []
|
1085
1327
|
end
|
@@ -1087,11 +1329,11 @@ end
|
|
1087
1329
|
|
1088
1330
|
describe Aquarium::Aspects::Pointcut, "#candidate_objects" do
|
1089
1331
|
before(:each) do
|
1090
|
-
|
1332
|
+
before_pointcut_class_spec
|
1091
1333
|
end
|
1092
1334
|
|
1093
1335
|
it "should return only candidate matching objects when the input are objects." do
|
1094
|
-
example_objs = @
|
1336
|
+
example_objs = @example_classes.map {|t| t.new}
|
1095
1337
|
pc = Aquarium::Aspects::Pointcut.new :objects => example_objs
|
1096
1338
|
example_objs.each do |obj|
|
1097
1339
|
pc.candidate_objects.matched[obj].should_not be(nil?)
|
@@ -1102,7 +1344,7 @@ end
|
|
1102
1344
|
|
1103
1345
|
describe Aquarium::Aspects::Pointcut, "#candidate_join_points" do
|
1104
1346
|
before(:each) do
|
1105
|
-
|
1347
|
+
before_pointcut_class_spec
|
1106
1348
|
end
|
1107
1349
|
|
1108
1350
|
it "should return only candidate non-matching join points for the input join points that do not exist." do
|
@@ -1131,13 +1373,18 @@ end
|
|
1131
1373
|
|
1132
1374
|
describe Aquarium::Aspects::Pointcut, "#specification" do
|
1133
1375
|
before(:each) do
|
1134
|
-
|
1376
|
+
before_pointcut_class_spec
|
1135
1377
|
@empty_set = Set.new
|
1136
1378
|
@default_specification = {
|
1137
1379
|
:types => @empty_set, :objects => @empty_set, :join_points => @empty_set,
|
1380
|
+
:types_and_ancestors => @empty_set,
|
1381
|
+
:types_and_descendents => @empty_set,
|
1138
1382
|
:methods => @empty_set, :method_options => @empty_set,
|
1139
1383
|
:attributes => @empty_set, :attribute_options => @empty_set,
|
1140
1384
|
:exclude_types => @empty_set,
|
1385
|
+
:exclude_types_calculated => @empty_set,
|
1386
|
+
:exclude_types_and_ancestors => @empty_set,
|
1387
|
+
:exclude_types_and_descendents => @empty_set,
|
1141
1388
|
:exclude_objects => @empty_set,
|
1142
1389
|
:exclude_join_points => @empty_set,
|
1143
1390
|
:exclude_pointcuts => @empty_set,
|
@@ -1152,38 +1399,38 @@ describe Aquarium::Aspects::Pointcut, "#specification" do
|
|
1152
1399
|
end
|
1153
1400
|
|
1154
1401
|
it "should return the input :types and :type arguments combined into an array keyed by :types." do
|
1155
|
-
pc = Aquarium::Aspects::Pointcut.new :types => @
|
1156
|
-
pc.specification.should == { :types => Set.new(@
|
1402
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :type => String
|
1403
|
+
pc.specification.should == { :types => Set.new(@example_classes + [String]) } | @default_specification_all_methods
|
1157
1404
|
end
|
1158
1405
|
|
1159
1406
|
it "should return the input :objects and :object arguments combined into an array keyed by :objects." do
|
1160
|
-
example_objs = @
|
1407
|
+
example_objs = @example_classes.map {|t| t.new}
|
1161
1408
|
s1234 = "1234"
|
1162
1409
|
pc = Aquarium::Aspects::Pointcut.new :objects => example_objs, :object => s1234
|
1163
1410
|
pc.specification.should == { :objects => Set.new(example_objs + [s1234]) } | @default_specification_all_methods
|
1164
1411
|
end
|
1165
1412
|
|
1166
1413
|
it "should return the input :methods and :method arguments combined into an array keyed by :methods." do
|
1167
|
-
pc = Aquarium::Aspects::Pointcut.new :types => @
|
1168
|
-
pc.specification.should == { :types => Set.new(@
|
1414
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :methods => /^get/, :method => "dup"
|
1415
|
+
pc.specification.should == { :types => Set.new(@example_classes), :methods => Set.new([/^get/, "dup"]) } | @default_specification
|
1169
1416
|
end
|
1170
1417
|
|
1171
1418
|
it "should return the input :method_options verbatim." do
|
1172
|
-
pc = Aquarium::Aspects::Pointcut.new :types => @
|
1173
|
-
pc.specification.should == { :types => Set.new(@
|
1419
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :methods => /^get/, :method => "dup", :method_options => [:instance, :public]
|
1420
|
+
pc.specification.should == { :types => Set.new(@example_classes), :methods => Set.new([/^get/, "dup"]),
|
1174
1421
|
:method_options => Set.new([:instance, :public]), :default_objects => @empty_set } | @default_specification
|
1175
1422
|
end
|
1176
1423
|
|
1177
1424
|
it "should return the input :methods and :method arguments combined into an array keyed by :methods." do
|
1178
|
-
pc = Aquarium::Aspects::Pointcut.new :types => @
|
1179
|
-
pc.specification.should == { :types => Set.new(@
|
1425
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :attributes => /^state/, :attribute => "name"
|
1426
|
+
pc.specification.should == { :types => Set.new(@example_classes), :objects => @empty_set, :join_points => @empty_set,
|
1180
1427
|
:methods => @empty_set, :method_options => Set.new([]), :default_objects => @empty_set,
|
1181
1428
|
:attributes => Set.new([/^state/, "name"]), :attribute_options => @empty_set } | @default_specification
|
1182
1429
|
end
|
1183
1430
|
|
1184
1431
|
it "should return the input :attributes, :attribute and :attribute_options arguments, verbatim." do
|
1185
|
-
pc = Aquarium::Aspects::Pointcut.new :types => @
|
1186
|
-
pc.specification.should == { :types => Set.new(@
|
1432
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_classes, :attributes => /^state/, :attribute => "name", :attribute_options => :reader
|
1433
|
+
pc.specification.should == { :types => Set.new(@example_classes), :attributes => Set.new([/^state/, "name"]),
|
1187
1434
|
:attribute_options => Set.new([:reader]) } | @default_specification
|
1188
1435
|
end
|
1189
1436
|
end
|