aquarium 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/Aquarium-IDEA.ipr +252 -0
  2. data/Aquarium-IDEA.iws +493 -0
  3. data/Aquarium.ipr +1 -1
  4. data/Aquarium.iws +133 -138
  5. data/CHANGES +63 -0
  6. data/ParseTreePlay.rb +25 -0
  7. data/README +55 -3
  8. data/RELEASE-PLAN +9 -1
  9. data/TODO.rb +175 -15
  10. data/examples/aspect_design_example.rb +13 -1
  11. data/examples/aspect_design_example_spec.rb +20 -2
  12. data/examples/introductions_example.rb +35 -0
  13. data/examples/introductions_example_spec.rb +37 -0
  14. data/examples/method_missing_example.rb +2 -1
  15. data/lib/aquarium/aspects/advice.rb +127 -74
  16. data/lib/aquarium/aspects/aspect.rb +139 -72
  17. data/lib/aquarium/aspects/default_objects_handler.rb +6 -4
  18. data/lib/aquarium/aspects/exclusion_handler.rb +15 -3
  19. data/lib/aquarium/aspects/join_point.rb +60 -55
  20. data/lib/aquarium/aspects/pointcut.rb +153 -124
  21. data/lib/aquarium/aspects/pointcut_composition.rb +1 -1
  22. data/lib/aquarium/dsl/aspect_dsl.rb +13 -5
  23. data/lib/aquarium/dsl/object_dsl.rb +4 -2
  24. data/lib/aquarium/extras/design_by_contract.rb +9 -5
  25. data/lib/aquarium/finders.rb +1 -0
  26. data/lib/aquarium/finders/finder_result.rb +13 -5
  27. data/lib/aquarium/finders/method_finder.rb +75 -70
  28. data/lib/aquarium/finders/pointcut_finder.rb +166 -0
  29. data/lib/aquarium/finders/type_finder.rb +104 -62
  30. data/lib/aquarium/utils/array_utils.rb +1 -1
  31. data/lib/aquarium/utils/invalid_options.rb +2 -0
  32. data/lib/aquarium/utils/name_utils.rb +3 -2
  33. data/lib/aquarium/utils/nil_object.rb +7 -3
  34. data/lib/aquarium/utils/options_utils.rb +38 -27
  35. data/lib/aquarium/utils/set_utils.rb +2 -2
  36. data/lib/aquarium/utils/type_utils.rb +11 -0
  37. data/lib/aquarium/version.rb +1 -1
  38. data/spec/aquarium/aspects/advice_spec.rb +147 -32
  39. data/spec/aquarium/aspects/aspect_invocation_spec.rb +252 -43
  40. data/spec/aquarium/aspects/aspect_spec.rb +148 -88
  41. data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +40 -34
  42. data/spec/aquarium/aspects/aspect_with_subtypes_spec.rb +39 -3
  43. data/spec/aquarium/aspects/join_point_spec.rb +190 -227
  44. data/spec/aquarium/aspects/pointcut_spec.rb +24 -1
  45. data/spec/aquarium/dsl/aspect_dsl_spec.rb +17 -17
  46. data/spec/aquarium/finders/method_finder_spec.rb +8 -2
  47. data/spec/aquarium/finders/pointcut_finder_spec.rb +193 -0
  48. data/spec/aquarium/finders/pointcut_finder_spec_test_classes.rb +90 -0
  49. data/spec/aquarium/finders/type_finder_spec.rb +17 -0
  50. data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +4 -4
  51. data/spec/aquarium/finders/type_finder_with_nested_types.rb +47 -0
  52. data/spec/aquarium/utils/nil_object_spec.rb +21 -0
  53. data/spec/aquarium/utils/type_utils_sample_nested_types.rb +51 -0
  54. data/spec/aquarium/utils/type_utils_spec.rb +18 -1
  55. metadata +13 -3
@@ -6,15 +6,15 @@ include Aquarium::Aspects
6
6
 
7
7
  describe Advice, "#sort_by_priority_order" do
8
8
  it "should return an empty array for empty input" do
9
- Aquarium::Aspects::Advice.sort_by_priority_order([]).should == []
9
+ Advice.sort_by_priority_order([]).should == []
10
10
  end
11
11
 
12
12
  it "should return a properly-sorted array for arbitrary input of valid advice kind symbols" do
13
- Aquarium::Aspects::Advice.sort_by_priority_order([:after_raising, :after_returning, :before, :after, :around]).should == [:around, :before, :after, :after_returning, :after_raising]
13
+ Advice.sort_by_priority_order([:after_raising, :after_returning, :before, :after, :around]).should == [:around, :before, :after, :after_returning, :after_raising]
14
14
  end
15
15
 
16
16
  it "should accept strings for the advice kinds, but return sorted symbols" do
17
- Aquarium::Aspects::Advice.sort_by_priority_order(["after_raising", "after_returning", "before", "after", "around"]).should == [:around, :before, :after, :after_returning, :after_raising]
17
+ Advice.sort_by_priority_order(["after_raising", "after_returning", "before", "after", "around"]).should == [:around, :before, :after, :after_returning, :after_raising]
18
18
  end
19
19
  end
20
20
 
@@ -53,16 +53,20 @@ describe Advice, "#invoke_original_join_point" do
53
53
  end
54
54
  end
55
55
 
56
+ def should_raise_expected_exception_with_message message
57
+ begin
58
+ yield ; fail
59
+ rescue => e
60
+ e.message.should include(message)
61
+ end
62
+ end
63
+
56
64
  describe Advice, "that raises an exception" do
57
65
  it "should add the kind of advice to the exception message." do
58
66
  aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_watchful_method} do |jp, obj, *args|
59
67
  raise SpecExceptionForTesting.new("advice called with args: #{args.inspect}")
60
68
  end
61
- begin
62
- Watchful.new.public_watchful_method(:a1, :a2) || fail
63
- rescue => e
64
- e.message.should include("\"before\" advice")
65
- end
69
+ should_raise_expected_exception_with_message("\"before\" advice") {Watchful.new.public_watchful_method(:a1, :a2)}
66
70
  aspect.unadvise
67
71
  end
68
72
 
@@ -70,11 +74,7 @@ describe Advice, "that raises an exception" do
70
74
  aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_watchful_method} do |jp, obj, *args|
71
75
  raise "advice called with args: #{args.inspect}"
72
76
  end
73
- begin
74
- Watchful.new.public_watchful_method(:a1, :a2) || fail
75
- rescue => e
76
- e.message.should include("Watchful#public_watchful_method")
77
- end
77
+ should_raise_expected_exception_with_message("Watchful#public_watchful_method") {Watchful.new.public_watchful_method(:a1, :a2)}
78
78
  aspect.unadvise
79
79
  end
80
80
 
@@ -82,29 +82,25 @@ describe Advice, "that raises an exception" do
82
82
  aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_class_watchful_method, :method_options => [:class]} do |jp, obj, *args|
83
83
  raise "advice called with args: #{args.inspect}"
84
84
  end
85
- begin
86
- Watchful.public_class_watchful_method(:a1, :a2) || fail
87
- rescue => e
88
- e.message.should include("Watchful.public_class_watchful_method")
89
- end
85
+ should_raise_expected_exception_with_message("Watchful.public_class_watchful_method") {Watchful.public_class_watchful_method(:a1, :a2)}
90
86
  aspect.unadvise
91
87
  end
92
88
 
93
89
  it "should rethrow an exception of the same type as the original exception." do
94
- class MyException < Exception; end
90
+ class MyException1 < Exception; end
95
91
  aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_class_watchful_method, :method_options => [:class]} do |jp, obj, *args|
96
- raise MyException.new("advice called with args: #{args.inspect}")
92
+ raise MyException1.new("advice called with args: #{args.inspect}")
97
93
  end
98
- lambda { Watchful.public_class_watchful_method :a1, :a2 }.should raise_error(MyException)
94
+ lambda { Watchful.public_class_watchful_method :a1, :a2 }.should raise_error(MyException1)
99
95
  aspect.unadvise
100
96
  end
101
97
 
102
98
  it "should rethrow an exception with the same backtrace as the original exception." do
103
- class MyException < Exception; end
99
+ class MyException2 < Exception; end
104
100
  @backtrace = nil
105
101
  aspect = Aspect.new :before, :pointcut => {:type => Watchful, :methods => :public_class_watchful_method, :method_options => [:class]} do |jp, obj, *args|
106
102
  begin
107
- exception = MyException.new("advice called with args: #{args.inspect}")
103
+ exception = MyException2.new("advice called with args: #{args.inspect}")
108
104
  raise exception
109
105
  rescue Exception => e
110
106
  @backtrace = e.backtrace
@@ -112,7 +108,89 @@ describe Advice, "that raises an exception" do
112
108
  end
113
109
  end
114
110
  begin
115
- Watchful.public_class_watchful_method(:a1, :a2) || fail
111
+ Watchful.public_class_watchful_method(:a1, :a2) ; fail
112
+ rescue Exception => e
113
+ e.backtrace.should == @backtrace
114
+ end
115
+ aspect.unadvise
116
+ end
117
+ end
118
+
119
+ describe Advice, "#invoke_original_join_point that raises an exception" do
120
+ class InvokeOriginalJoinPointRaisingException
121
+ class IOJPRException < Exception; end
122
+ def raise_exception *args
123
+ raise IOJPRException.new(":raise_exception called with args: #{args.inspect}")
124
+ end
125
+ def self.class_raise_exception *args
126
+ raise IOJPRException.new(":class_raise_exception called with args: #{args.inspect}")
127
+ end
128
+ end
129
+
130
+ it "should add the kind of advice to the exception message." do
131
+ aspect = Aspect.new :before,
132
+ :pointcut => {:type => InvokeOriginalJoinPointRaisingException, :methods => :raise_exception} do |jp, obj, *args|
133
+ jp.invoke_original_join_point
134
+ end
135
+ begin
136
+ InvokeOriginalJoinPointRaisingException.new.raise_exception(:a1, :a2) ; fail
137
+ rescue InvokeOriginalJoinPointRaisingException::IOJPRException => e
138
+ e.message.should include("\"before\" advice")
139
+ end
140
+ aspect.unadvise
141
+ end
142
+
143
+ it "should add the \"Class#method\" of the advised object's type and method to the exception message." do
144
+ aspect = Aspect.new :before,
145
+ :pointcut => {:type => InvokeOriginalJoinPointRaisingException, :methods => :raise_exception} do |jp, obj, *args|
146
+ jp.invoke_original_join_point
147
+ end
148
+ begin
149
+ InvokeOriginalJoinPointRaisingException.new.raise_exception(:a1, :a2) ; fail
150
+ rescue InvokeOriginalJoinPointRaisingException::IOJPRException => e
151
+ e.message.should include("InvokeOriginalJoinPointRaisingException#raise_exception")
152
+ end
153
+ aspect.unadvise
154
+ end
155
+
156
+ it "should add the \"Class.method\" of the advised type's class method to the exception message." do
157
+ aspect = Aspect.new :before,
158
+ :pointcut => {:type => InvokeOriginalJoinPointRaisingException, :methods => :class_raise_exception,
159
+ :method_options => [:class]} do |jp, obj, *args|
160
+ jp.invoke_original_join_point
161
+ end
162
+ begin
163
+ InvokeOriginalJoinPointRaisingException.class_raise_exception(:a1, :a2) ; fail
164
+ rescue InvokeOriginalJoinPointRaisingException::IOJPRException => e
165
+ e.message.should include("InvokeOriginalJoinPointRaisingException.class_raise_exception")
166
+ end
167
+ aspect.unadvise
168
+ end
169
+
170
+ it "should rethrow an exception of the same type as the original exception." do
171
+ aspect = Aspect.new :before,
172
+ :pointcut => {:type => InvokeOriginalJoinPointRaisingException, :methods => :class_raise_exception,
173
+ :method_options => [:class]} do |jp, obj, *args|
174
+ jp.invoke_original_join_point
175
+ end
176
+ lambda { InvokeOriginalJoinPointRaisingException.class_raise_exception :a1, :a2 }.should raise_error(InvokeOriginalJoinPointRaisingException::IOJPRException)
177
+ aspect.unadvise
178
+ end
179
+
180
+ it "should rethrow an exception with the same backtrace as the original exception." do
181
+ @backtrace = nil
182
+ aspect = Aspect.new :before,
183
+ :pointcut => {:type => InvokeOriginalJoinPointRaisingException, :methods => :class_raise_exception,
184
+ :method_options => [:class]} do |jp, obj, *args|
185
+ begin
186
+ jp.invoke_original_join_point
187
+ rescue Exception => e
188
+ @backtrace = e.backtrace
189
+ raise e
190
+ end
191
+ end
192
+ begin
193
+ InvokeOriginalJoinPointRaisingException.class_raise_exception(:a1, :a2) ; fail
116
194
  rescue Exception => e
117
195
  e.backtrace.should == @backtrace
118
196
  end
@@ -120,19 +198,56 @@ describe Advice, "that raises an exception" do
120
198
  end
121
199
  end
122
200
 
201
+ describe Advice, ".compare_advice_kinds with nil or UNKNOWN_ADVICE_KIND" do
202
+ it "should return 0 when comparing nil to nil" do
203
+ Advice.compare_advice_kinds(nil, nil).should == 0
204
+ end
205
+ it "should return 0 when comparing UNKNOWN_ADVICE_KIND to UNKNOWN_ADVICE_KIND" do
206
+ Advice.compare_advice_kinds(Advice::UNKNOWN_ADVICE_KIND, Advice::UNKNOWN_ADVICE_KIND).should == 0
207
+ end
208
+ it "should return 1 when comparing UNKNOWN_ADVICE_KIND to nil" do
209
+ Advice.compare_advice_kinds(Advice::UNKNOWN_ADVICE_KIND, nil).should == 1
210
+ end
211
+ it "should return -1 when comparing nil to UNKNOWN_ADVICE_KIND" do
212
+ Advice.compare_advice_kinds(nil, Advice::UNKNOWN_ADVICE_KIND).should == -1
213
+ end
214
+
215
+ Advice::KINDS_IN_PRIORITY_ORDER.each do |kind|
216
+ it "should return 1 when comparing :#{kind} to UNKNOWN_ADVICE_KIND" do
217
+ Advice.compare_advice_kinds(kind, Advice::UNKNOWN_ADVICE_KIND).should == 1
218
+ end
219
+ end
220
+ Advice::KINDS_IN_PRIORITY_ORDER.each do |kind|
221
+ it "should return -1 when comparing UNKNOWN_ADVICE_KIND to :#{kind}" do
222
+ Advice.compare_advice_kinds(Advice::UNKNOWN_ADVICE_KIND, kind).should == -1
223
+ end
224
+ end
225
+ end
226
+
227
+ describe Advice, ".compare_advice_kinds between 'real' advice kinds" do
228
+ Advice::KINDS_IN_PRIORITY_ORDER.each do |kind1|
229
+ Advice::KINDS_IN_PRIORITY_ORDER.each do |kind2|
230
+ expected = Advice::KINDS_IN_PRIORITY_ORDER.index(kind1) <=> Advice::KINDS_IN_PRIORITY_ORDER.index(kind2)
231
+ it "should return #{expected} when comparing :#{kind1} to :#{kind2} (using priority order)" do
232
+ Advice.compare_advice_kinds(kind1, kind2).should == expected
233
+ end
234
+ end
235
+ end
236
+ end
237
+
123
238
  describe AdviceChainNodeFactory, "#make_node" do
124
239
  it "should raise if an unknown advice kind is specified" do
125
- lambda {Aquarium::Aspects::AdviceChainNodeFactory.make_node :advice_kind => :foo}.should raise_error(Aquarium::Utils::InvalidOptions)
240
+ lambda {AdviceChainNodeFactory.make_node :advice_kind => :foo}.should raise_error(Aquarium::Utils::InvalidOptions)
126
241
  end
127
242
 
128
243
  it "should return a node of the type corresponding to the input advice kind" do
129
- Aquarium::Aspects::AdviceChainNodeFactory.make_node(:advice_kind => :no).kind_of?(Aquarium::Aspects::NoAdviceChainNode).should be_true
130
- Aquarium::Aspects::AdviceChainNodeFactory.make_node(:advice_kind => :none).kind_of?(Aquarium::Aspects::NoAdviceChainNode).should be_true
131
- Aquarium::Aspects::AdviceChainNodeFactory.make_node(:advice_kind => :before).kind_of?(Aquarium::Aspects::BeforeAdviceChainNode).should be_true
132
- Aquarium::Aspects::AdviceChainNodeFactory.make_node(:advice_kind => :after).kind_of?(Aquarium::Aspects::AfterAdviceChainNode).should be_true
133
- Aquarium::Aspects::AdviceChainNodeFactory.make_node(:advice_kind => :after_raising).kind_of?(Aquarium::Aspects::AfterRaisingAdviceChainNode).should be_true
134
- Aquarium::Aspects::AdviceChainNodeFactory.make_node(:advice_kind => :after_returning).kind_of?(Aquarium::Aspects::AfterReturningAdviceChainNode).should be_true
135
- Aquarium::Aspects::AdviceChainNodeFactory.make_node(:advice_kind => :around).kind_of?(Aquarium::Aspects::AroundAdviceChainNode).should be_true
244
+ AdviceChainNodeFactory.make_node(:advice_kind => :no).kind_of?(NoAdviceChainNode).should be_true
245
+ AdviceChainNodeFactory.make_node(:advice_kind => :none).kind_of?(NoAdviceChainNode).should be_true
246
+ AdviceChainNodeFactory.make_node(:advice_kind => :before).kind_of?(BeforeAdviceChainNode).should be_true
247
+ AdviceChainNodeFactory.make_node(:advice_kind => :after).kind_of?(AfterAdviceChainNode).should be_true
248
+ AdviceChainNodeFactory.make_node(:advice_kind => :after_raising).kind_of?(AfterRaisingAdviceChainNode).should be_true
249
+ AdviceChainNodeFactory.make_node(:advice_kind => :after_returning).kind_of?(AfterReturningAdviceChainNode).should be_true
250
+ AdviceChainNodeFactory.make_node(:advice_kind => :around).kind_of?(AroundAdviceChainNode).should be_true
136
251
  end
137
252
  end
138
253
 
@@ -1,13 +1,16 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
  require File.dirname(__FILE__) + '/../spec_example_types'
3
+ require File.dirname(__FILE__) + '/../utils/type_utils_sample_nested_types'
3
4
  require 'aquarium/aspects/aspect'
4
- require 'aquarium/aspects/dsl'
5
+ require 'aquarium/dsl'
5
6
  require 'aquarium/utils/array_utils'
7
+ require File.dirname(__FILE__) + '/../finders/pointcut_finder_spec_test_classes'
6
8
 
7
9
  require 'profiler'
8
10
 
9
11
  include Aquarium::Aspects
10
12
  include Aquarium::Utils::ArrayUtils
13
+ include Aquarium::PointcutFinderTestClasses
11
14
 
12
15
 
13
16
  def aspects_should_be_equal num_jps, aspect1, aspect2
@@ -132,18 +135,18 @@ describe Aspect, "methods" do
132
135
  it "should reject the :exceptions argument unless specified with :after_raising." do
133
136
  lambda { Aspect.new :before, :after, :exceptions => [Exception, String], :pointcut => @pointcut_opts, :noop => true }.should raise_error(Aquarium::Utils::InvalidOptions)
134
137
  end
135
- end
138
+ end
136
139
 
137
140
  describe Aspect, ".new (parameters that specify pointcuts)" do
138
141
  before :all do
139
142
  @pointcut_opts = {:type => Aquarium::AspectInvocationTestClass}
140
143
  end
141
144
 
142
- it "should contain at least one of :method(s), :pointcut(s), :type(s), or :object(s)." do
145
+ it "should contain at least one of :method(s), :pointcut(s), :named_pointcut(s), :type(s), or :object(s)." do
143
146
  lambda {Aspect.new(:after, :ignore_no_matching_join_points => true) {true}}.should raise_error(Aquarium::Utils::InvalidOptions)
144
147
  end
145
148
 
146
- it "should contain at least one of :pointcut(s), :type(s), or :object(s) unless :default_objects => object is given." do
149
+ it "should contain at least one of :pointcut(s), :named_pointcut(s), :type(s), or :object(s) unless :default_objects => object is given." do
147
150
  aspect = Aspect.new(:after, :default_objects => Aquarium::AspectInvocationTestClass.new, :method => :public_test_method, :noop => true) {true}
148
151
  end
149
152
 
@@ -163,7 +166,7 @@ end
163
166
  aspect.join_points_matched.each {|jp| jp.type_or_object.should_not == Aquarium::AspectInvocationTestClass}
164
167
  end
165
168
 
166
- it "should ignore the :default_objects if at least one :pointcut is given and the :default_objects are objects." do
169
+ it "should ignore the :default_objects if at least one :pointcut is given even if the :default_objects => object are given." do
167
170
  object = Aquarium::AspectInvocationTestClass.new
168
171
  aspect = Aspect.new(:after, :default_objects => object,
169
172
  :pointcut => {:type => Aquarium::AspectInvocationTestClass2, :method => :public_test_method}, :method => :public_test_method) {true}
@@ -171,7 +174,7 @@ end
171
174
  aspect.join_points_matched.each {|jp| jp.type_or_object.should_not == object}
172
175
  end
173
176
 
174
- it "should ignore the :default_objects if at least one :pointcut is given and the :default_objects are types." do
177
+ it "should ignore the :default_objects if at least one :pointcut is given even if the :default_objects => type are given." do
175
178
  aspect = Aspect.new(:after, :default_objects => Aquarium::AspectInvocationTestClass,
176
179
  :pointcut => {:type => Aquarium::AspectInvocationTestClass2, :method => :public_test_method}, :method => :public_test_method) {true}
177
180
  aspect.join_points_matched.size.should == 1
@@ -193,7 +196,7 @@ end
193
196
  aspect.join_points_matched.each {|jp| jp.type_or_object.should_not == Aquarium::AspectInvocationTestClass}
194
197
  end
195
198
 
196
- [:type, :type_and_descendents, :type_and_ancestors].each do |type_key|
199
+ [:type, :type_and_descendents, :type_and_ancestors, :type_and_nested_types].each do |type_key|
197
200
  it "should ignore the :default_objects if at least one :#{type_key} is given and the :default_objects are objects." do
198
201
  object = Aquarium::AspectInvocationTestClass.new
199
202
  aspect = Aspect.new(:after, :default_objects => object, type_key => Aquarium::AspectInvocationTestClass2, :method => :public_test_method, :method => :public_test_method) {true}
@@ -220,7 +223,37 @@ end
220
223
  end
221
224
  end
222
225
 
226
+ describe Aspect, ".new (parameters that specify named constant and/or class variable pointcuts)" do
227
+ it "should contain at least one :types or TypeFinder synonym for :types." do
228
+ lambda {Aspect.new(:after, :named_pointcuts => {}, :noop => true) {true}}.should raise_error(Aquarium::Utils::InvalidOptions)
229
+ lambda {Aspect.new(:after, :named_pointcuts => {:types => all_pointcut_classes}, :noop => true) {true}}.should_not raise_error(Aquarium::Utils::InvalidOptions)
230
+ end
231
+
232
+ it "should ignore the :default_objects if at least one :named_pointcut is given even if the :default_objects => object are given." do
233
+ object = Aquarium::AspectInvocationTestClass.new
234
+ aspect = Aspect.new(:after, :default_objects => object, :named_pointcut => {:types => Aquarium::PointcutFinderTestClasses::PointcutClassVariableHolder1}) {true}
235
+ aspect.join_points_matched.size.should == 1
236
+ aspect.join_points_matched.each {|jp| jp.type_or_object.should_not == object}
237
+ end
238
+
239
+ it "should ignore the :default_objects if at least one :named_pointcut is given even if the :default_objects => type are given." do
240
+ aspect = Aspect.new(:after, :default_objects => Aquarium::AspectInvocationTestClass, :named_pointcut => {:types => Aquarium::PointcutFinderTestClasses::PointcutClassVariableHolder1}) {true}
241
+ aspect.join_points_matched.size.should == 1
242
+ aspect.join_points_matched.each {|jp| jp.type_or_object.should_not == Aquarium::AspectInvocationTestClass}
243
+ end
244
+
245
+ Aspect::CANONICAL_OPTIONS["named_pointcuts"].each do |key|
246
+ it "should accept :#{key} as a synonym for :named_pointcuts." do
247
+ lambda { Aspect.new :before, key.intern => {:types => Aquarium::PointcutFinderTestClasses.all_pointcut_classes}, :noop => true do; end }.should_not raise_error
248
+ end
249
+ end
223
250
 
251
+ it "should not contain :named_pointcut(s) and either :type(s) or :object(s)." do
252
+ lambda {Aspect.new(:after, :named_pointcuts => {:types => Aquarium::PointcutFinderTestClasses::PointcutClassVariableHolder1}, :type => Aquarium::AspectInvocationTestClass, :method => :public_test_method) {true}}.should raise_error(Aquarium::Utils::InvalidOptions)
253
+ lambda {Aspect.new(:after, :named_pointcuts => {:types => Aquarium::PointcutFinderTestClasses::PointcutClassVariableHolder1}, :object => Aquarium::AspectInvocationTestClass.new, :method => :public_test_method) {true}}.should raise_error(Aquarium::Utils::InvalidOptions)
254
+ end
255
+ end
256
+
224
257
  describe Aspect, ".new with :types parameter" do
225
258
  it "should advise the specified types." do
226
259
  @advice_called = false
@@ -462,6 +495,27 @@ end
462
495
  do_type_spec
463
496
  end
464
497
 
498
+ it "should accept :type(s)_and_nested_types => T1, :methods => [m, ...]" do
499
+ @types_option = :types_and_nested_types
500
+ @type_spec = Aquarium::AspectInvocationTestClass
501
+ @method_spec = [:public_test_method]
502
+ do_type_spec
503
+ end
504
+
505
+ it "should accept :type(s)_and_nested_types => [T1, ...], :methods => [m, ...]" do
506
+ @types_option = :types_and_nested_types
507
+ @type_spec = [Aquarium::AspectInvocationTestClass]
508
+ @method_spec = [:public_test_method]
509
+ do_type_spec
510
+ end
511
+
512
+ it "should accept :type(s)_and_nested_types => /T1/, :methods => [m, ...]" do
513
+ @types_option = :types_and_nested_types
514
+ @type_spec = /Aquarium::AspectInvocationTestClass/
515
+ @method_spec = [:public_test_method]
516
+ do_type_spec
517
+ end
518
+
465
519
  it "should accept :type(s) => ..., :methods => ..., :method_options => [:exclude_ancestor_methods] to exclude methods defined in ancestors" do
466
520
  @type_spec = /Aquarium::AspectInvocationTestClass/
467
521
  @method_spec = /test_method/
@@ -885,6 +939,11 @@ end
885
939
  do_type_pointcut_spec
886
940
  end
887
941
 
942
+ it "should accept {:type(s)_and_nested_types => [T1, ...], :methods => /m/} " do
943
+ @pointcut_hash = {:type_and_nested_types => [Aquarium::AspectInvocationTestClass], :methods => /test_method/}
944
+ do_type_pointcut_spec
945
+ end
946
+
888
947
  it "should accept {:type(s) => T1, :methods => [m, ...]} " do
889
948
  @pointcut_hash = {:type => Aquarium::AspectInvocationTestClass, :methods => [:public_test_method]}
890
949
  do_type_pointcut_spec
@@ -910,6 +969,11 @@ end
910
969
  do_type_pointcut_spec
911
970
  end
912
971
 
972
+ it "should accept {:type(s)_and_nested_types => T1, :methods => /m/} " do
973
+ @pointcut_hash = {:type_and_nested_types => Aquarium::AspectInvocationTestClass, :methods => /test_method/}
974
+ do_type_pointcut_spec
975
+ end
976
+
913
977
  it "should accept {:type(s) => /T1/, :methods => [m, ...]} " do
914
978
  @pointcut_hash = {:type => /Aquarium::AspectInvocationTestClass/, :methods => [:public_test_method]}
915
979
  do_type_pointcut_spec
@@ -935,6 +999,11 @@ end
935
999
  do_type_pointcut_spec
936
1000
  end
937
1001
 
1002
+ it "should accept {:type(s)_and_nested_types => /T1/, :methods => /m/} " do
1003
+ @pointcut_hash = {:type_and_nested_types => /Aquarium::AspectInvocationTestClass/, :methods => /test_method/}
1004
+ do_type_pointcut_spec
1005
+ end
1006
+
938
1007
  %w[public protected private].each do |protection|
939
1008
  it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:instance, #{protection}]} " do
940
1009
  @protection = protection
@@ -1153,6 +1222,26 @@ end
1153
1222
  aspects_should_be_equal 1, @aspect1, @aspect2
1154
1223
  end
1155
1224
 
1225
+ it "should advise equivalent join points when :type_and_nested_types => T and :method => m is used or :pointcut =>{:type_and_nested_types => T, :method => m} is used." do
1226
+ @aspect1 = Aspect.new :after, :type_and_nested_types => Aquarium::AspectInvocationTestClass, :method => :public_test_method, &@advice
1227
+ @aspect2 = Aspect.new :after, :pointcut => {:type_and_nested_types => Aquarium::AspectInvocationTestClass, :method => :public_test_method}, &@advice
1228
+ aspects_should_be_equal 1, @aspect1, @aspect2
1229
+ end
1230
+
1231
+ it "should advise equivalent join points when :type_and_nested_types => T and :method => m is used or :pointcut => pointcut is used, where pointcut matches :type_and_nested_types => T and :method => m." do
1232
+ @aspect1 = Aspect.new :after, :type_and_nested_types => Aquarium::AspectInvocationTestClass, :method => :public_test_method, &@advice
1233
+ pointcut = Aquarium::Aspects::Pointcut.new :type_and_nested_types => Aquarium::AspectInvocationTestClass, :method => :public_test_method
1234
+ @aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
1235
+ aspects_should_be_equal 1, @aspect1, @aspect2
1236
+ end
1237
+
1238
+ it "should advise equivalent join points when :pointcut =>{:type_and_nested_types => T, :method => m} is used or :pointcut => pointcut is used, where pointcut matches :type_and_nested_types => T and :method => m." do
1239
+ @aspect1 = Aspect.new :after, :pointcut => {:type_and_nested_types => Aquarium::AspectInvocationTestClass, :method => :public_test_method}, &@advice
1240
+ pointcut = Aquarium::Aspects::Pointcut.new :type_and_nested_types => Aquarium::AspectInvocationTestClass, :method => :public_test_method
1241
+ @aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
1242
+ aspects_should_be_equal 1, @aspect1, @aspect2
1243
+ end
1244
+
1156
1245
  end
1157
1246
 
1158
1247
  describe Aspect, ".new (with a :type(s) parameter and an :attributes(s) parameter or one of several equivalent :pointcut parameters)" do
@@ -1407,7 +1496,7 @@ end
1407
1496
  end
1408
1497
 
1409
1498
  describe Aspect, ".new (advice block to around advice with just the join_point parameter - Bug #19262)" do
1410
- it "should work not raise an error" do
1499
+ it "should not raise an error" do
1411
1500
  aspect = Aspect.new :around, :type => Aquarium::AspectInvocationTestClass, :methods => :public_test_method do |jp|; jp.proceed; end
1412
1501
  Aquarium::AspectInvocationTestClass.new.public_test_method
1413
1502
  aspect.unadvise
@@ -1439,7 +1528,7 @@ end
1439
1528
  def doit3; end
1440
1529
  end
1441
1530
 
1442
- describe Aspect, ".new (with a :type(s) parameter and an :exclude_type(s), and :exclude_type(s)_and_ancestors, or an :exclude_type(s)_and_descendents parameter)" do
1531
+ describe Aspect, ".new (with a :type(s) parameter and an :exclude_type(s), and :exclude_type(s)_and_ancestors, an :exclude_type(s)_and_descendents, or an :exclude_type(s)_and_nested_types parameter)" do
1443
1532
  before :all do
1444
1533
  @included_types = [DontExclude1, DontExclude2]
1445
1534
  @excluded_types = [Exclude1, Exclude2]
@@ -1496,6 +1585,16 @@ end
1496
1585
  end
1497
1586
  end
1498
1587
 
1588
+ it "should accept :type(s) => [T1, ...], :exclude_types_and_nested_types => [T2, ...] and exclude join points in the excluded types" do
1589
+ do_exclude_types :exclude_types_and_nested_types
1590
+ end
1591
+
1592
+ Aspect::CANONICAL_OPTIONS["exclude_types_and_nested_types"].each do |key|
1593
+ it "should accept :#{key} as a synonym for :exclude_types_and_nested_types." do
1594
+ lambda { Aspect.new :before, :types => @all_types, key.intern => @excluded_types, :methods => :doit, :noop => true do; end }.should_not raise_error
1595
+ end
1596
+ end
1597
+
1499
1598
  end
1500
1599
 
1501
1600
 
@@ -1650,6 +1749,27 @@ end
1650
1749
  end
1651
1750
  end
1652
1751
 
1752
+ describe Aspect, ".new (with a :type(s)_and_nested_types parameter and an :exclude_join_point(s) parameter)" do
1753
+ it "should accept :type(s)_and_nested_types => [T1, ...], :exclude_join_point(s) => [jps], where [jps] are the list of join points for the types and methods to exclude" do
1754
+ included_types = [ClassWithPublicInstanceMethod, ModuleWithPublicInstanceMethod]
1755
+ excluded_join_point1 = JoinPoint.new :type => ClassWithPublicInstanceMethod, :method => :public_instance_test_method
1756
+ excluded_join_point2 = JoinPoint.new :type => ModuleWithPublicInstanceMethod, :method => :public_instance_module_test_method
1757
+ excluded_join_points = [excluded_join_point1, excluded_join_point2]
1758
+ aspect = nil
1759
+ advice_called = false
1760
+ aspect = Aspect.new :before, :types_and_nested_types => included_types, :methods => :doit,
1761
+ :exclude_join_points => excluded_join_points, :ignore_no_matching_join_points => true do |jp, obj, *args|; advice_called = true; end
1762
+
1763
+ advice_called = false
1764
+ ClassWithPublicInstanceMethod.new.public_instance_test_method
1765
+ advice_called.should be_false
1766
+ advice_called = false
1767
+ ClassIncludingModuleWithPublicInstanceMethod.new.public_instance_module_test_method
1768
+ advice_called.should be_false
1769
+ aspect.unadvise
1770
+ end
1771
+ end
1772
+
1653
1773
  describe Aspect, ".new (with a :pointcut(s) parameter and an :exclude_join_point(s) parameter)" do
1654
1774
  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
1655
1775
  included_types = [DontExclude1, DontExclude2]
@@ -1716,7 +1836,7 @@ end
1716
1836
 
1717
1837
  Aspect::CANONICAL_OPTIONS["exclude_pointcuts"].each do |key|
1718
1838
  it "should accept :#{key} as a synonym for :exclude_pointcuts." do
1719
- lambda {aspect = Aspect.new :before, :objects => @all_objects, :exclude_pointcuts => @excluded_pointcuts, :methods => :doit, :noop => true do; end}.should_not raise_error
1839
+ lambda {aspect = Aspect.new :before, :objects => @all_objects, key.intern => @excluded_pointcuts, :methods => :doit, :noop => true do; end}.should_not raise_error
1720
1840
  end
1721
1841
  end
1722
1842
  end
@@ -1787,40 +1907,82 @@ end
1787
1907
  end
1788
1908
  end
1789
1909
 
1790
- describe Aspect, ".new (with type-based :pointcut(s) and :exclude_type(s) parameter)" do
1791
- it "should accept :pointcut(s) => [P1, ...], :exclude_type(s) => [types], where join points with [types] are excluded" do
1792
- included_types = [DontExclude1, DontExclude2]
1793
- excluded_types = [Exclude1, Exclude2]
1794
- pointcut1 = Pointcut.new :types => included_types, :method => :doit
1795
- pointcut2 = Pointcut.new :types => excluded_types, :method => :doit
1910
+ describe Aspect, ".new (with a :pointcut(s) and an :exclude_named_pointcut(s) parameter)" do
1911
+ it "should accept :pointcut(s) => [P1, ...], :exclude_named_pointcut(s) => {...}, where any pointcuts matching the latter are excluded" do
1796
1912
  aspect = nil
1797
1913
  advice_called = false
1798
- aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_types => excluded_types do |jp, obj, *args|
1914
+ aspect = Aspect.new :before, :pointcuts => Aquarium::PointcutFinderTestClasses.all_pointcuts,
1915
+ :exclude_named_pointcuts => {:matching => /POINTCUT/, :in_types => Aquarium::PointcutFinderTestClasses.all_pointcut_classes} do |jp, obj, *args|
1799
1916
  advice_called = true
1800
- excluded_types.should_not include(jp.target_type)
1917
+ Aquarium::PointcutFinderTestClasses.all_constants_pointcut_classes.should_not include(jp.target_type)
1801
1918
  end
1919
+ Aquarium::PointcutFinderTestClasses.all_class_variables_pointcut_classes.each do |type|
1920
+ advice_called = false
1921
+ type.new.doit
1922
+ advice_called.should be_true
1923
+ end
1924
+ Aquarium::PointcutFinderTestClasses.all_constants_pointcut_classes.each do |type|
1925
+ advice_called = false
1926
+ type.new.doit
1927
+ advice_called.should_not be_true
1928
+ end
1929
+ aspect.unadvise
1930
+ end
1802
1931
 
1803
- included_types.each do |type|
1932
+ Aspect::CANONICAL_OPTIONS["exclude_named_pointcuts"].each do |key|
1933
+ it "should accept :#{key} as a synonym for :exclude_named_pointcuts." do
1934
+ lambda {aspect = Aspect.new :before, :pointcuts => Aquarium::PointcutFinderTestClasses.all_pointcuts,
1935
+ key.intern => {:matching => /POINTCUT/, :in_types => Aquarium::PointcutFinderTestClasses.all_pointcut_classes},
1936
+ :noop => true do; end}.should_not raise_error
1937
+ end
1938
+ end
1939
+ end
1940
+
1941
+ describe Aspect, ".new (with type-based :pointcut(s) and :exclude_type(s) parameter)" do
1942
+ before :all do
1943
+ @included_types = [DontExclude1, DontExclude2]
1944
+ @excluded_types = [Exclude1, Exclude2]
1945
+ @pointcut1 = Pointcut.new :types => @included_types, :method => :doit
1946
+ @pointcut2 = Pointcut.new :types => @excluded_types, :method => :doit
1947
+ end
1948
+
1949
+ it "should accept :pointcut(s) => [P1, ...], :exclude_type(s) => [types], where join points with [types] are excluded" do
1950
+ advice_called = false
1951
+ aspect = Aspect.new :before, :pointcuts => [@pointcut1, @pointcut2], :exclude_types => @excluded_types do |jp, obj, *args|
1952
+ advice_called = true
1953
+ @excluded_types.should_not include(jp.target_type)
1954
+ end
1955
+
1956
+ @included_types.each do |type|
1804
1957
  advice_called = false
1805
1958
  type.new(1).doit
1806
1959
  advice_called.should be_true
1807
1960
  end
1808
- excluded_types.each do |type|
1961
+ @excluded_types.each do |type|
1809
1962
  advice_called = false
1810
1963
  type.new(1).doit
1811
1964
  advice_called.should_not be_true
1812
1965
  end
1813
1966
  aspect.unadvise
1814
1967
  end
1968
+
1969
+ Aspect::CANONICAL_OPTIONS["exclude_types"].each do |key|
1970
+ it "should accept :#{key} as a synonym for :exclude_types." do
1971
+ lambda {aspect = Aspect.new :before, :pointcuts => [@pointcut1, @pointcut2], key.intern => @excluded_types,
1972
+ :noop => true do; end}.should_not raise_error
1973
+ end
1974
+ end
1815
1975
  end
1816
1976
 
1817
1977
  describe Aspect, ".new (with type-based :pointcut(s) and :exclude_type(s)_and_ancestors parameter)" do
1978
+ before :all do
1979
+ @excluded_types = [ClassWithPublicInstanceMethod, ModuleWithPublicInstanceMethod]
1980
+ @types = @excluded_types + [ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod]
1981
+ @pointcut1 = Pointcut.new :types => @types, :method => :all, :method_options => [:exclude_ancestor_methods]
1982
+ end
1983
+
1818
1984
  it "should accept :pointcut(s) => [P1, ...], :exclude_type(s)_and_ancestors => [types], where join points with [types] are excluded" do
1819
- excluded_types = [ClassWithPublicInstanceMethod, ModuleWithPublicInstanceMethod]
1820
- types = excluded_types + [ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod]
1821
- pointcut1 = Pointcut.new :types => types, :method => :all, :method_options => [:exclude_ancestor_methods]
1822
- advice_called = false
1823
- aspect = Aspect.new :before, :pointcuts => pointcut1, :exclude_types_and_ancestors => excluded_types do |jp, obj, *args|; end
1985
+ aspect = Aspect.new :before, :pointcuts => @pointcut1, :exclude_types_and_ancestors => @excluded_types do |jp, obj, *args|; end
1824
1986
  aspect.pointcuts.each do |pc|
1825
1987
  pc.join_points_matched.each do |jp|
1826
1988
  jp.target_type.should == ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod
@@ -1828,48 +1990,95 @@ end
1828
1990
  end
1829
1991
  aspect.unadvise
1830
1992
  end
1993
+
1994
+ Aspect::CANONICAL_OPTIONS["exclude_types_and_ancestors"].each do |key|
1995
+ it "should accept :#{key} as a synonym for :exclude_types_and_ancestors." do
1996
+ lambda {aspect = Aspect.new :before, :pointcuts => @pointcut1, key.intern => @excluded_types,
1997
+ :noop => true do; end}.should_not raise_error
1998
+ end
1999
+ end
1831
2000
  end
1832
2001
 
1833
2002
  describe Aspect, ".new (with type-based :pointcut(s) and :exclude_type(s)_and_descendents parameter)" do
2003
+ before :all do
2004
+ @excluded_types = [ClassWithPublicInstanceMethod, ModuleWithPublicInstanceMethod]
2005
+ @types = @excluded_types + [ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod]
2006
+ @pointcut1 = Pointcut.new :types => @types, :method => :all, :method_options => [:exclude_ancestor_methods]
2007
+ end
1834
2008
  it "should accept :pointcut(s) => [P1, ...], :exclude_type(s)_and_descendents => [types], where join points with [types] are excluded" do
1835
- excluded_types = [ClassWithPublicInstanceMethod, ModuleWithPublicInstanceMethod]
1836
- types = excluded_types + [ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod]
1837
- pointcut1 = Pointcut.new :types => types, :method => :all, :method_options => [:exclude_ancestor_methods]
1838
- advice_called = false
1839
- aspect = Aspect.new :before, :pointcuts => pointcut1, :exclude_types_and_descendents => excluded_types, :ignore_no_matching_join_points => true do |jp, obj, *args|; end
2009
+ aspect = Aspect.new :before, :pointcuts => @pointcut1, :exclude_types_and_descendents => @excluded_types,
2010
+ :ignore_no_matching_join_points => true do |jp, obj, *args|; end
1840
2011
  aspect.pointcuts.size.should == 0
1841
2012
  aspect.unadvise
1842
2013
  end
2014
+
2015
+ Aspect::CANONICAL_OPTIONS["exclude_types_and_descendents"].each do |key|
2016
+ it "should accept :#{key} as a synonym for :exclude_types_and_descendents." do
2017
+ lambda {aspect = Aspect.new :before, :pointcuts => @pointcut1, key.intern => @excluded_types,
2018
+ :ignore_no_matching_join_points => true, :noop => true do; end}.should_not raise_error
2019
+ end
2020
+ end
2021
+ end
2022
+
2023
+ describe Aspect, ".new (with type-based :pointcut(s) and :exclude_type(s)_and_nested_types parameter)" do
2024
+ before :all do
2025
+ @excluded_types = [ClassWithPublicInstanceMethod, ModuleWithPublicInstanceMethod]
2026
+ @types = @excluded_types + [ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod]
2027
+ @pointcut1 = Pointcut.new :types => @types, :method => :all, :method_options => [:exclude_ancestor_methods]
2028
+ end
2029
+ it "should accept :pointcut(s) => [P1, ...], :exclude_type(s)_and_nested_types => [types], where join points with [types] are excluded" do
2030
+ aspect = Aspect.new :before, :pointcuts => @pointcut1, :exclude_types_and_nested_types => @excluded_types,
2031
+ :ignore_no_matching_join_points => true do |jp, obj, *args|; end
2032
+ aspect.pointcuts.size.should == 1
2033
+ aspect.unadvise
2034
+ end
2035
+
2036
+ Aspect::CANONICAL_OPTIONS["exclude_types_and_nested_types"].each do |key|
2037
+ it "should accept :#{key} as a synonym for :exclude_types_and_nested_types." do
2038
+ lambda {aspect = Aspect.new :before, :pointcuts => @pointcut1, key.intern => @excluded_types,
2039
+ :ignore_no_matching_join_points => true, :noop => true do; end}.should_not raise_error
2040
+ end
2041
+ end
1843
2042
  end
1844
2043
 
1845
- describe Aspect, ".new (with object-based :pointcut(s) and :exclude_object(s) or :exclude_method(s) parameter)" do
2044
+ describe Aspect, ".new (with object-based :pointcut(s) and :exclude_object(s) parameter)" do
2045
+ before :all do
2046
+ @dontExclude1 = DontExclude1.new(1)
2047
+ @dontExclude2 = DontExclude1.new(2)
2048
+ @exclude1 = DontExclude1.new(3)
2049
+ @exclude2 = DontExclude1.new(4)
2050
+ @included_objects = [@dontExclude1, @dontExclude2]
2051
+ @excluded_objects = [@exclude1, @exclude2]
2052
+ @pointcut1 = Pointcut.new :objects => @included_objects, :method => :doit
2053
+ @pointcut2 = Pointcut.new :objects => @excluded_objects, :method => :doit
2054
+ end
2055
+
1846
2056
  it "should accept :pointcut(s) => [P1, ...], :exclude_object(s) => [objects], where join points with [objects] are excluded" do
1847
- dontExclude1 = DontExclude1.new(1)
1848
- dontExclude2 = DontExclude1.new(2)
1849
- exclude1 = DontExclude1.new(3)
1850
- exclude2 = DontExclude1.new(4)
1851
- included_objects = [dontExclude1, dontExclude2]
1852
- excluded_objects = [exclude1, exclude2]
1853
- pointcut1 = Pointcut.new :objects => included_objects, :method => :doit
1854
- pointcut2 = Pointcut.new :objects => excluded_objects, :method => :doit
1855
2057
  aspect = nil
1856
2058
  advice_called = false
1857
- aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_objects => excluded_objects do |jp, obj, *args|
2059
+ aspect = Aspect.new :before, :pointcuts => [@pointcut1, @pointcut2], :exclude_objects => @excluded_objects do |jp, obj, *args|
1858
2060
  advice_called = true
1859
- excluded_objects.should_not include(obj)
2061
+ @excluded_objects.should_not include(obj)
1860
2062
  end
1861
- included_objects.each do |object|
2063
+ @included_objects.each do |object|
1862
2064
  advice_called = false
1863
2065
  object.doit
1864
2066
  advice_called.should be_true
1865
2067
  end
1866
- excluded_objects.each do |object|
2068
+ @excluded_objects.each do |object|
1867
2069
  advice_called = false
1868
2070
  object.doit
1869
2071
  advice_called.should_not be_true
1870
2072
  end
1871
2073
  aspect.unadvise
1872
2074
  end
2075
+
2076
+ Aspect::CANONICAL_OPTIONS["exclude_objects"].each do |key|
2077
+ it "should accept :#{key} as a synonym for :exclude_objects." do
2078
+ lambda {aspect = Aspect.new :before, :pointcuts => [@pointcut1, @pointcut2], key.intern => @excluded_objects,
2079
+ :noop => true do; end}.should_not raise_error
2080
+ end
2081
+ end
1873
2082
  end
1874
2083
 
1875
2084
  describe Aspect, ".new (with :method(s) and :exclude_method(s) parameter)" do