aquarium 0.1.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 +4 -0
- data/EXAMPLES.rd +4 -0
- data/MIT-LICENSE +20 -0
- data/README +250 -0
- data/RELEASE-PLAN +1 -0
- data/Rakefile +236 -0
- data/UPGRADE +3 -0
- data/examples/aspect_design_example.rb +36 -0
- data/examples/design_by_contract_example.rb +88 -0
- data/examples/method_missing_example.rb +44 -0
- data/examples/method_tracing_example.rb +64 -0
- data/lib/aquarium.rb +7 -0
- data/lib/aquarium/aspects.rb +6 -0
- data/lib/aquarium/aspects/advice.rb +189 -0
- data/lib/aquarium/aspects/aspect.rb +577 -0
- data/lib/aquarium/aspects/default_object_handler.rb +27 -0
- data/lib/aquarium/aspects/dsl.rb +1 -0
- data/lib/aquarium/aspects/dsl/aspect_dsl.rb +61 -0
- data/lib/aquarium/aspects/join_point.rb +158 -0
- data/lib/aquarium/aspects/pointcut.rb +254 -0
- data/lib/aquarium/aspects/pointcut_composition.rb +36 -0
- data/lib/aquarium/extensions.rb +5 -0
- data/lib/aquarium/extensions/hash.rb +85 -0
- data/lib/aquarium/extensions/regexp.rb +20 -0
- data/lib/aquarium/extensions/set.rb +49 -0
- data/lib/aquarium/extensions/string.rb +13 -0
- data/lib/aquarium/extensions/symbol.rb +22 -0
- data/lib/aquarium/extras.rb +4 -0
- data/lib/aquarium/extras/design_by_contract.rb +64 -0
- data/lib/aquarium/finders.rb +4 -0
- data/lib/aquarium/finders/finder_result.rb +121 -0
- data/lib/aquarium/finders/method_finder.rb +228 -0
- data/lib/aquarium/finders/object_finder.rb +74 -0
- data/lib/aquarium/finders/type_finder.rb +127 -0
- data/lib/aquarium/utils.rb +9 -0
- data/lib/aquarium/utils/array_utils.rb +29 -0
- data/lib/aquarium/utils/hash_utils.rb +28 -0
- data/lib/aquarium/utils/html_escaper.rb +17 -0
- data/lib/aquarium/utils/invalid_options.rb +9 -0
- data/lib/aquarium/utils/method_utils.rb +18 -0
- data/lib/aquarium/utils/nil_object.rb +13 -0
- data/lib/aquarium/utils/set_utils.rb +32 -0
- data/lib/aquarium/version.rb +30 -0
- data/rake_tasks/examples.rake +7 -0
- data/rake_tasks/examples_specdoc.rake +8 -0
- data/rake_tasks/examples_with_rcov.rake +8 -0
- data/rake_tasks/verify_rcov.rake +7 -0
- data/spec/aquarium/aspects/advice_chain_node_spec.rb +34 -0
- data/spec/aquarium/aspects/advice_spec.rb +103 -0
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +111 -0
- data/spec/aquarium/aspects/aspect_spec.rb +978 -0
- data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +129 -0
- data/spec/aquarium/aspects/concurrent_aspects_spec.rb +423 -0
- data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +103 -0
- data/spec/aquarium/aspects/concurrently_accessed.rb +21 -0
- data/spec/aquarium/aspects/dsl/aspect_dsl_spec.rb +514 -0
- data/spec/aquarium/aspects/join_point_spec.rb +302 -0
- data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +131 -0
- data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +111 -0
- data/spec/aquarium/aspects/pointcut_spec.rb +800 -0
- data/spec/aquarium/extensions/hash_spec.rb +187 -0
- data/spec/aquarium/extensions/regex_spec.rb +40 -0
- data/spec/aquarium/extensions/set_spec.rb +105 -0
- data/spec/aquarium/extensions/string_spec.rb +25 -0
- data/spec/aquarium/extensions/symbol_spec.rb +37 -0
- data/spec/aquarium/extras/design_by_contract_spec.rb +68 -0
- data/spec/aquarium/finders/finder_result_spec.rb +359 -0
- data/spec/aquarium/finders/method_finder_spec.rb +878 -0
- data/spec/aquarium/finders/method_sorting_spec.rb +16 -0
- data/spec/aquarium/finders/object_finder_spec.rb +230 -0
- data/spec/aquarium/finders/type_finder_spec.rb +210 -0
- data/spec/aquarium/spec_example_classes.rb +117 -0
- data/spec/aquarium/spec_helper.rb +3 -0
- data/spec/aquarium/utils/array_utils_spec.rb +47 -0
- data/spec/aquarium/utils/hash_utils_spec.rb +48 -0
- data/spec/aquarium/utils/html_escaper_spec.rb +18 -0
- data/spec/aquarium/utils/method_utils_spec.rb +50 -0
- data/spec/aquarium/utils/nil_object_spec.rb +19 -0
- data/spec/aquarium/utils/set_utils_spec.rb +60 -0
- metadata +132 -0
@@ -0,0 +1,800 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../spec_example_classes'
|
3
|
+
require 'aquarium/extensions/hash'
|
4
|
+
require 'aquarium/aspects/pointcut'
|
5
|
+
require 'aquarium/utils'
|
6
|
+
|
7
|
+
def common_setup
|
8
|
+
@example_types_without_public_instance_method =
|
9
|
+
[ClassWithProtectedInstanceMethod, ClassWithPrivateInstanceMethod, ClassWithPublicClassMethod, ClassWithPrivateClassMethod]
|
10
|
+
@example_types = ([ClassWithPublicInstanceMethod] + @example_types_without_public_instance_method)
|
11
|
+
@pub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod, :method_name => :public_instance_test_method
|
12
|
+
@pro_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithProtectedInstanceMethod, :method_name => :protected_instance_test_method
|
13
|
+
@pri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPrivateInstanceMethod, :method_name => :private_instance_test_method
|
14
|
+
@cpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicClassMethod, :method_name => :public_class_test_method, :is_class_method => true
|
15
|
+
@cpri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPrivateClassMethod, :method_name => :private_class_test_method, :is_class_method => true
|
16
|
+
@apro_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithProtectedInstanceMethod, :method_name => :all
|
17
|
+
@apri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPrivateInstanceMethod, :method_name => :all
|
18
|
+
@acpub_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicClassMethod, :method_name => :all
|
19
|
+
@acpri_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithPrivateClassMethod, :method_name => :all
|
20
|
+
@expected_matched_jps = Set.new [@pub_jp]
|
21
|
+
@expected_not_matched_jps = Set.new [@apro_jp, @apri_jp, @acpub_jp, @acpri_jp]
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Aquarium::Aspects::Pointcut, " (empty)" do
|
25
|
+
it "should match no join points by default." do
|
26
|
+
pc = Aquarium::Aspects::Pointcut.new
|
27
|
+
pc.should be_empty
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should match no join points if nil is the only argument specified." do
|
31
|
+
pc = Aquarium::Aspects::Pointcut.new nil
|
32
|
+
pc.should be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should match no join points if types = [] specified." do
|
36
|
+
pc = Aquarium::Aspects::Pointcut.new :types => []
|
37
|
+
pc.should be_empty
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should match no join points if types = nil specified." do
|
41
|
+
pc = Aquarium::Aspects::Pointcut.new :types => nil
|
42
|
+
pc.should be_empty
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should match no join points if objects = [] specified." do
|
46
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => []
|
47
|
+
pc.should be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should match no join points if objects = nil specified." do
|
51
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => nil
|
52
|
+
pc.should be_empty
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe Aquarium::Aspects::Pointcut, "#empty?" do
|
57
|
+
it "should be true if there are no matched and no unmatched join points." do
|
58
|
+
pc = Aquarium::Aspects::Pointcut.new
|
59
|
+
pc.join_points_matched.size.should == 0
|
60
|
+
pc.join_points_not_matched.size.should == 0
|
61
|
+
pc.should be_empty
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be false if there are matched join points." do
|
65
|
+
pc = Aquarium::Aspects::Pointcut.new :types => [ClassWithAttribs], :methods => [/^attr/]
|
66
|
+
pc.join_points_matched.size.should > 0
|
67
|
+
pc.join_points_not_matched.size.should == 0
|
68
|
+
pc.should_not be_empty
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should be false if there are unmatched join points." do
|
72
|
+
pc = Aquarium::Aspects::Pointcut.new :types => [String], :methods => [/^attr/]
|
73
|
+
pc.join_points_matched.size.should == 0
|
74
|
+
pc.join_points_not_matched.size.should > 0
|
75
|
+
pc.should_not be_empty
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe Aquarium::Aspects::Pointcut, " (types specified using regular expressions)" do
|
80
|
+
setup do
|
81
|
+
common_setup
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should match multiple classes using regular expressions." do
|
85
|
+
pc = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :method_options => :suppress_ancestor_methods
|
86
|
+
pc.join_points_matched.should == @expected_matched_jps
|
87
|
+
pc.join_points_not_matched.should == @expected_not_matched_jps
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe Aquarium::Aspects::Pointcut, " (types specified using names)" do
|
92
|
+
setup do
|
93
|
+
common_setup
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should match multiple classes using names." do
|
97
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types.map {|t| t.to_s}, :method_options => :suppress_ancestor_methods
|
98
|
+
pc.join_points_matched.should == @expected_matched_jps
|
99
|
+
pc.join_points_not_matched.should == @expected_not_matched_jps
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should match multiple classes using types themselves." do
|
103
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :method_options => :suppress_ancestor_methods
|
104
|
+
pc.join_points_matched.should == @expected_matched_jps
|
105
|
+
pc.join_points_not_matched.should == @expected_not_matched_jps
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should match :all public instance methods for types by default." do
|
109
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :method_options => :suppress_ancestor_methods
|
110
|
+
pc.join_points_matched.should == @expected_matched_jps
|
111
|
+
pc.join_points_not_matched.should == @expected_not_matched_jps
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should support MethodFinder's :suppress_ancestor_methods option when using types." do
|
115
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :method_options => :suppress_ancestor_methods
|
116
|
+
pc.join_points_matched.should == @expected_matched_jps
|
117
|
+
pc.join_points_not_matched.should == @expected_not_matched_jps
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe Aquarium::Aspects::Pointcut, " (objects specified)" do
|
122
|
+
setup do
|
123
|
+
common_setup
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should match :all public instance methods for objects by default." do
|
127
|
+
pub, pro = ClassWithPublicInstanceMethod.new, ClassWithProtectedInstanceMethod.new
|
128
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => [pub, pro], :method_options => :suppress_ancestor_methods
|
129
|
+
pc.join_points_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:object => pub, :method_name => :public_instance_test_method)])
|
130
|
+
pc.join_points_not_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:object => pro, :method_name => :all)])
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should support MethodFinder's :suppress_ancestor_methods option when using objects." do
|
134
|
+
pub, pro = ClassWithPublicInstanceMethod.new, ClassWithProtectedInstanceMethod.new
|
135
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => [pub, pro], :method_options => :suppress_ancestor_methods
|
136
|
+
pc.join_points_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:object => pub, :method_name => :public_instance_test_method)])
|
137
|
+
pc.join_points_not_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:object => pro, :method_name => :all)])
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should match all possible methods on the specified objects." do
|
141
|
+
pub, pro = ClassWithPublicInstanceMethod.new, ClassWithProtectedInstanceMethod.new
|
142
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => [pub, pro], :methods => :all, :method_options => [:public, :protected, :suppress_ancestor_methods]
|
143
|
+
pc.join_points_matched.size.should == 2
|
144
|
+
pc.join_points_not_matched.size.should == 0
|
145
|
+
pc.join_points_matched.should == Set.new([
|
146
|
+
Aquarium::Aspects::JoinPoint.new(:object => pro, :method_name => :protected_instance_test_method),
|
147
|
+
Aquarium::Aspects::JoinPoint.new(:object => pub, :method_name => :public_instance_test_method)])
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe Aquarium::Aspects::Pointcut, " (types or objects specified with public instance methods)" do
|
152
|
+
setup do
|
153
|
+
common_setup
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should support MethodFinder's :public and :instance options for the specified types." do
|
157
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithPublicInstanceMethod, :method_options => [:public, :instance, :suppress_ancestor_methods]
|
158
|
+
pc.join_points_matched.should eql(Set.new([@pub_jp]))
|
159
|
+
pc.join_points_not_matched.size.should == 0
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should support MethodFinder's :public and :instance options for the specified objects." do
|
163
|
+
pub = ClassWithPublicInstanceMethod.new
|
164
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => pub, :method_options => [:public, :instance, :suppress_ancestor_methods]
|
165
|
+
pc.join_points_matched.should eql(Set.new([Aquarium::Aspects::JoinPoint.new(:object => pub, :method_name => :public_instance_test_method)]))
|
166
|
+
pc.join_points_not_matched.size.should == 0
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe Aquarium::Aspects::Pointcut, " (types or objects specified with protected instance methods)" do
|
171
|
+
setup do
|
172
|
+
common_setup
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should support MethodFinder's :protected and :instance options for the specified types." do
|
176
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithProtectedInstanceMethod, :method_options => [:protected, :instance, :suppress_ancestor_methods]
|
177
|
+
pc.join_points_matched.should eql(Set.new([@pro_jp]))
|
178
|
+
pc.join_points_not_matched.size.should == 0
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should support MethodFinder's :protected and :instance options for the specified objects." do
|
182
|
+
pro = ClassWithProtectedInstanceMethod.new
|
183
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => pro, :method_options => [:protected, :instance, :suppress_ancestor_methods]
|
184
|
+
pc.join_points_matched.should eql(Set.new([Aquarium::Aspects::JoinPoint.new(:object => pro, :method_name => :protected_instance_test_method)]))
|
185
|
+
pc.join_points_not_matched.size.should == 0
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe Aquarium::Aspects::Pointcut, " (types or objects specified with private instance methods)" do
|
190
|
+
setup do
|
191
|
+
common_setup
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should support MethodFinder's :private and :instance options for the specified types." do
|
195
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithPrivateInstanceMethod, :method_options => [:private, :instance, :suppress_ancestor_methods]
|
196
|
+
pc.join_points_matched.should eql(Set.new([@pri_jp]))
|
197
|
+
pc.join_points_not_matched.size.should == 0
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should support MethodFinder's :private and :instance options for the specified objects." do
|
201
|
+
pro = ClassWithPrivateInstanceMethod.new
|
202
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => pro, :method_options => [:private, :instance, :suppress_ancestor_methods]
|
203
|
+
pc.join_points_matched.should eql(Set.new([Aquarium::Aspects::JoinPoint.new(:object => pro, :method_name => :private_instance_test_method)]))
|
204
|
+
pc.join_points_not_matched.size.should == 0
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe Aquarium::Aspects::Pointcut, " (types or objects specified with public class methods)" do
|
209
|
+
setup do
|
210
|
+
common_setup
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should support MethodFinder's :public and :class options for the specified types." do
|
214
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithPublicClassMethod, :method_options => [:public, :class, :suppress_ancestor_methods]
|
215
|
+
pc.join_points_matched.should eql(Set.new([@cpub_jp]))
|
216
|
+
pc.join_points_not_matched.size.should == 0
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should support MethodFinder's :public and :class options for the specified objects, which will return no methods." do
|
220
|
+
pub = ClassWithPublicInstanceMethod.new
|
221
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => pub, :method_options => [:public, :class, :suppress_ancestor_methods]
|
222
|
+
pc.join_points_matched.size.should == 0
|
223
|
+
pc.join_points_not_matched.size.should == 1
|
224
|
+
pc.join_points_not_matched.should eql(Set.new([Aquarium::Aspects::JoinPoint.new(:object => pub, :method_name => :all, :is_class_method => true)]))
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe Aquarium::Aspects::Pointcut, " (types or objects specified with private class methods)" do
|
229
|
+
setup do
|
230
|
+
common_setup
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should support MethodFinder's :private and :class options for the specified types." do
|
234
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithPrivateClassMethod, :method_options => [:private, :class, :suppress_ancestor_methods]
|
235
|
+
pc.join_points_matched.should eql(Set.new([@cpri_jp]))
|
236
|
+
pc.join_points_not_matched.size.should == 0
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should support MethodFinder's :private and :class options for the specified objects, which will return no methods." do
|
240
|
+
pri = ClassWithPrivateInstanceMethod.new
|
241
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => pri, :method_options => [:private, :class, :suppress_ancestor_methods]
|
242
|
+
pc.join_points_not_matched.should eql(Set.new([Aquarium::Aspects::JoinPoint.new(:object => pri, :method_name => :all, :is_class_method => true)]))
|
243
|
+
pc.join_points_not_matched.size.should == 1
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe Aquarium::Aspects::Pointcut, " (types or objects specified with method regular expressions)" do
|
248
|
+
setup do
|
249
|
+
common_setup
|
250
|
+
@jp_rwe = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs=
|
251
|
+
@jp_rw = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs
|
252
|
+
@jp_we = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrW_ClassWithAttribs=
|
253
|
+
@jp_r = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrR_ClassWithAttribs
|
254
|
+
@expected_for_types = Set.new([@jp_rw, @jp_rwe, @jp_r, @jp_we])
|
255
|
+
@object_of_ClassWithAttribs = ClassWithAttribs.new
|
256
|
+
@jp_rwe_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs=
|
257
|
+
@jp_rw_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs
|
258
|
+
@jp_we_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrW_ClassWithAttribs=
|
259
|
+
@jp_r_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrR_ClassWithAttribs
|
260
|
+
@expected_for_objects = Set.new([@jp_rw_o, @jp_rwe_o, @jp_r_o, @jp_we_o])
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should match on public method readers and writers for type names by default." do
|
264
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :methods => [/^attr/]
|
265
|
+
pc.join_points_matched.should == @expected_for_types
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should match on public method readers and writers for types by default." do
|
269
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :methods => [/^attr/]
|
270
|
+
pc.join_points_matched.should == @expected_for_types
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should match on public method readers and writers for objects by default." do
|
274
|
+
pc = Aquarium::Aspects::Pointcut.new :object => @object_of_ClassWithAttribs, :methods => [/^attr/]
|
275
|
+
pc.join_points_matched.should == @expected_for_objects
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe Aquarium::Aspects::Pointcut, " (types or objects specified with attribute regular expressions)" do
|
280
|
+
setup do
|
281
|
+
common_setup
|
282
|
+
@jp_rwe = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs=
|
283
|
+
@jp_rw = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs
|
284
|
+
@jp_we = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrW_ClassWithAttribs=
|
285
|
+
@jp_r = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method_name => :attrR_ClassWithAttribs
|
286
|
+
@expected_for_types = Set.new([@jp_rw, @jp_rwe, @jp_r, @jp_we])
|
287
|
+
@object_of_ClassWithAttribs = ClassWithAttribs.new
|
288
|
+
@jp_rwe_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs=
|
289
|
+
@jp_rw_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrRW_ClassWithAttribs
|
290
|
+
@jp_we_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrW_ClassWithAttribs=
|
291
|
+
@jp_r_o = Aquarium::Aspects::JoinPoint.new :object => @object_of_ClassWithAttribs, :method_name => :attrR_ClassWithAttribs
|
292
|
+
@expected_for_objects = Set.new([@jp_rw_o, @jp_rwe_o, @jp_r_o, @jp_we_o])
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should match on public attribute readers and writers for type names by default." do
|
296
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/]
|
297
|
+
pc.join_points_matched.should == @expected_for_types
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should match on public attribute readers and writers for types by default." do
|
301
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/]
|
302
|
+
pc.join_points_matched.should == @expected_for_types
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should match on public attribute readers and writers for objects by default." do
|
306
|
+
pc = Aquarium::Aspects::Pointcut.new :object => @object_of_ClassWithAttribs, :attributes => [/^attr/]
|
307
|
+
pc.join_points_matched.should == @expected_for_objects
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should match attribute specifications for types that are prefixed with @." do
|
311
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^@attr/]
|
312
|
+
pc.join_points_matched.should == @expected_for_types
|
313
|
+
end
|
314
|
+
|
315
|
+
it "should match attribute specifications for objects that are prefixed with @." do
|
316
|
+
pc = Aquarium::Aspects::Pointcut.new :object => @object_of_ClassWithAttribs, :attributes => [/^@attr/]
|
317
|
+
pc.join_points_matched.should == @expected_for_objects
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should match attribute specifications that are regular expressions of symbols." do
|
321
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^:attr/]
|
322
|
+
pc.join_points_matched.should == @expected_for_types
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should match attribute specifications for objects that are regular expressions of symbols." do
|
326
|
+
object = ClassWithAttribs.new
|
327
|
+
pc = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^:attr/]
|
328
|
+
pc.join_points_matched.should == Set.new([
|
329
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs),
|
330
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs=),
|
331
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrR_ClassWithAttribs),
|
332
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrW_ClassWithAttribs=)])
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should match public attribute readers and writers for types when both the :readers and :writers options are specified." do
|
336
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers, :writers]
|
337
|
+
pc.join_points_matched.should == @expected_for_types
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should match public attribute readers and writers for objects when both the :readers and :writers options are specified." do
|
341
|
+
object = ClassWithAttribs.new
|
342
|
+
pc = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^:attr/], :attribute_options => [:readers, :writers]
|
343
|
+
pc.join_points_matched.should == Set.new([
|
344
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs),
|
345
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs=),
|
346
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrR_ClassWithAttribs),
|
347
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrW_ClassWithAttribs=)])
|
348
|
+
end
|
349
|
+
|
350
|
+
it "should match public attribute readers for types only when the :readers option is specified." do
|
351
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers]
|
352
|
+
pc.join_points_matched.should == Set.new([
|
353
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrRW_ClassWithAttribs),
|
354
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrR_ClassWithAttribs)])
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should match public attribute readers for objects only when the :readers option is specified." do
|
358
|
+
object = ClassWithAttribs.new
|
359
|
+
pc = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^:attr/], :attribute_options => [:readers]
|
360
|
+
pc.join_points_matched.should == Set.new([
|
361
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs),
|
362
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrR_ClassWithAttribs)])
|
363
|
+
end
|
364
|
+
|
365
|
+
it "should match public attribute writers for types only when the :writers option is specified." do
|
366
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
|
367
|
+
pc.join_points_matched.should == Set.new([
|
368
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrRW_ClassWithAttribs=),
|
369
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrW_ClassWithAttribs=)])
|
370
|
+
end
|
371
|
+
|
372
|
+
it "should match public attribute writers for objects only when the :writers option is specified." do
|
373
|
+
object = ClassWithAttribs.new
|
374
|
+
pc = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^:attr/], :attribute_options => [:writers]
|
375
|
+
pc.join_points_matched.should == Set.new([
|
376
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs=),
|
377
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrW_ClassWithAttribs=)])
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should match attribute writers for types whether or not the attributes specification ends with an equal sign." do
|
381
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs",
|
382
|
+
:attributes => [/^attr[RW]+_ClassWithAttribs=/], :attribute_options => [:writers]
|
383
|
+
pc.join_points_matched.should == Set.new([
|
384
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrRW_ClassWithAttribs=),
|
385
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrW_ClassWithAttribs=)])
|
386
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs",
|
387
|
+
:attributes => [/^attr[RW]+_ClassWithAttribs/], :attribute_options => [:writers]
|
388
|
+
pc2.join_points_matched.should == Set.new([
|
389
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrRW_ClassWithAttribs=),
|
390
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrW_ClassWithAttribs=)])
|
391
|
+
end
|
392
|
+
|
393
|
+
it "should match attribute writers for objects whether or not the attributes specification ends with an equal sign." do
|
394
|
+
object = ClassWithAttribs.new
|
395
|
+
pc = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^attr[RW]+_ClassWithAttribs=/], :attribute_options => [:writers]
|
396
|
+
pc.join_points_matched.should == Set.new([
|
397
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs=),
|
398
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrW_ClassWithAttribs=)])
|
399
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^attr[RW]+_ClassWithAttribs/], :attribute_options => [:writers]
|
400
|
+
pc2.join_points_matched.should == Set.new([
|
401
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs=),
|
402
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrW_ClassWithAttribs=)])
|
403
|
+
end
|
404
|
+
|
405
|
+
it "should match attribute readers for types when the :readers option is specified even if the attributes specification ends with an equal sign!" do
|
406
|
+
pc = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs",
|
407
|
+
:attributes => [/^attr[RW]+_ClassWithAttribs=/], :attribute_options => [:readers]
|
408
|
+
pc.join_points_matched.should == Set.new([
|
409
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrRW_ClassWithAttribs),
|
410
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrR_ClassWithAttribs)])
|
411
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs",
|
412
|
+
:attributes => [/^attr[RW]+_ClassWithAttribs=/], :attribute_options => [:readers]
|
413
|
+
pc2.join_points_matched.should == Set.new([
|
414
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrRW_ClassWithAttribs),
|
415
|
+
Aquarium::Aspects::JoinPoint.new(:type => "ClassWithAttribs", :method_name => :attrR_ClassWithAttribs)])
|
416
|
+
end
|
417
|
+
|
418
|
+
it "should match attribute readers for objects when the :readers option is specified even if the attributes specification ends with an equal sign!" do
|
419
|
+
object = ClassWithAttribs.new
|
420
|
+
pc = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^attr[RW]+_ClassWithAttribs=/], :attribute_options => [:readers]
|
421
|
+
pc.join_points_matched.should == Set.new([
|
422
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs),
|
423
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrR_ClassWithAttribs)])
|
424
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => object, :attributes => [/^attr[RW]+_ClassWithAttribs/], :attribute_options => [:readers]
|
425
|
+
pc2.join_points_matched.should == Set.new([
|
426
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrRW_ClassWithAttribs),
|
427
|
+
Aquarium::Aspects::JoinPoint.new(:object => object, :method_name => :attrR_ClassWithAttribs)])
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
describe Aquarium::Aspects::Pointcut, " (methods that end in non-alphanumeric characters)" do
|
432
|
+
class ClassWithFunkyMethodNames
|
433
|
+
def huh?; true; end
|
434
|
+
def yes!; true; end
|
435
|
+
def x= other; false; end
|
436
|
+
def == other; false; end
|
437
|
+
def =~ other; false; end
|
438
|
+
end
|
439
|
+
|
440
|
+
before(:each) do
|
441
|
+
@funky = ClassWithFunkyMethodNames.new
|
442
|
+
end
|
443
|
+
|
444
|
+
{'?' => :huh?, '!' => :yes!, '=' => :x=}.each do |char, method|
|
445
|
+
it "should match instance methods for types when searching for names that end with a '#{char}' character." do
|
446
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithFunkyMethodNames, :method => method, :method_options => [:suppress_ancestor_methods]
|
447
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithFunkyMethodNames, :method_name => method
|
448
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
449
|
+
end
|
450
|
+
|
451
|
+
it "should match instance methods for objects when searching for names that end with a '#{char}' character." do
|
452
|
+
pc = Aquarium::Aspects::Pointcut.new :object => @funky, :method => method, :method_options => [:suppress_ancestor_methods]
|
453
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :object => @funky, :method_name => method
|
454
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
455
|
+
end
|
456
|
+
|
457
|
+
it "should match instance methods for types when searching for names that end with a '#{char}' character, using a regular expressions." do
|
458
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithFunkyMethodNames, :methods => /#{Regexp.escape(char)}$/, :method_options => [:suppress_ancestor_methods]
|
459
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithFunkyMethodNames, :method_name => method
|
460
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
461
|
+
end
|
462
|
+
|
463
|
+
it "should match instance methods for object when searching for names that end with a '#{char}' character, using a regular expressions." do
|
464
|
+
pc = Aquarium::Aspects::Pointcut.new :object => @funky, :methods => /#{Regexp.escape(char)}$/, :method_options => [:suppress_ancestor_methods]
|
465
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :object => @funky, :method_name => method
|
466
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
{'=' => :==, '~' => :=~}.each do |char, method|
|
471
|
+
it "should match the #{method} instance method for types, if you don't suppress ancestor methods, even if the method is defined in the class!" do
|
472
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithFunkyMethodNames, :method => method, :method_options => [:instance]
|
473
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithFunkyMethodNames, :method_name => method
|
474
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
475
|
+
end
|
476
|
+
|
477
|
+
it "should match the #{method} instance method for objects, if you don't suppress ancestor methods, even if the method is defined in the class!" do
|
478
|
+
pc = Aquarium::Aspects::Pointcut.new :object => @funky, :method => method, :method_options => [:instance]
|
479
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :object => @funky, :method_name => method
|
480
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
481
|
+
end
|
482
|
+
|
483
|
+
it "should match the #{method} instance method for types when using a regular expressions, if you don't suppress ancestor methods, even if the method is defined in the class!" do
|
484
|
+
pc = Aquarium::Aspects::Pointcut.new :types => ClassWithFunkyMethodNames, :methods => /#{Regexp.escape(char)}$/, :method_options => [:instance]
|
485
|
+
pc.join_points_matched.any? {|jp| jp.method_name == method}.should be_true
|
486
|
+
end
|
487
|
+
|
488
|
+
it "should match the #{method} instance method for objects when using a regular expressions, if you don't suppress ancestor methods, even if the method is defined in the class!" do
|
489
|
+
pc = Aquarium::Aspects::Pointcut.new :object => @funky, :methods => /#{Regexp.escape(char)}$/, :method_options => [:instance]
|
490
|
+
pc.join_points_matched.any? {|jp| jp.method_name == method}.should be_true
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
describe Aquarium::Aspects::Pointcut, " (:attributes => :all option not yet supported)" do
|
496
|
+
|
497
|
+
it "should raise if :all is used for attributes for types (not yet supported)." do
|
498
|
+
lambda { Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => :all }.should raise_error(Aquarium::Utils::InvalidOptions)
|
499
|
+
end
|
500
|
+
|
501
|
+
it "should raise if :all is used for attributes for objects (not yet supported)." do
|
502
|
+
lambda { Aquarium::Aspects::Pointcut.new :object => ClassWithAttribs.new, :attributes => :all }.should raise_error(Aquarium::Utils::InvalidOptions)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
describe "Aquarium::Aspects::Pointcut" do
|
507
|
+
|
508
|
+
setup do
|
509
|
+
class Empty; end
|
510
|
+
|
511
|
+
@objectWithSingletonMethod = Empty.new
|
512
|
+
class << @objectWithSingletonMethod
|
513
|
+
def a_singleton_method
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
class NotQuiteEmpty
|
518
|
+
end
|
519
|
+
class << NotQuiteEmpty
|
520
|
+
def a_class_singleton_method
|
521
|
+
end
|
522
|
+
end
|
523
|
+
@notQuiteEmpty = NotQuiteEmpty.new
|
524
|
+
end
|
525
|
+
|
526
|
+
it "should find instance-level singleton method joinpoints for objects when :singleton is specified." do
|
527
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => [@notQuiteEmpty, @objectWithSingletonMethod], :methods => :all, :method_options => [:singleton]
|
528
|
+
pc.join_points_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:object => @objectWithSingletonMethod, :method_name => :a_singleton_method)])
|
529
|
+
pc.join_points_not_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:object => @notQuiteEmpty, :method_name => :all)])
|
530
|
+
end
|
531
|
+
|
532
|
+
it "should find type-level singleton methods for types when :singleton is specified." do
|
533
|
+
pc = Aquarium::Aspects::Pointcut.new :types => [NotQuiteEmpty, Empty], :methods => :all, :method_options => [:singleton, :suppress_ancestor_methods]
|
534
|
+
pc.join_points_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:type => NotQuiteEmpty, :method_name => :a_class_singleton_method)])
|
535
|
+
pc.join_points_not_matched.should == Set.new([Aquarium::Aspects::JoinPoint.new(:type => Empty, :method_name => :all)])
|
536
|
+
end
|
537
|
+
|
538
|
+
it "should raise when specifying method options :singleton with :class, :public, :protected, or :private." do
|
539
|
+
lambda { Aquarium::Aspects::Pointcut.new :types => [NotQuiteEmpty, Empty], :methods => :all, :method_options => [:singleton, :class]}.should raise_error(Aquarium::Utils::InvalidOptions)
|
540
|
+
lambda { Aquarium::Aspects::Pointcut.new :types => [NotQuiteEmpty, Empty], :methods => :all, :method_options => [:singleton, :public]}.should raise_error(Aquarium::Utils::InvalidOptions)
|
541
|
+
lambda { Aquarium::Aspects::Pointcut.new :types => [NotQuiteEmpty, Empty], :methods => :all, :method_options => [:singleton, :protected]}.should raise_error(Aquarium::Utils::InvalidOptions)
|
542
|
+
lambda { Aquarium::Aspects::Pointcut.new :types => [NotQuiteEmpty, Empty], :methods => :all, :method_options => [:singleton, :private]}.should raise_error(Aquarium::Utils::InvalidOptions)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
546
|
+
|
547
|
+
describe Aquarium::Aspects::Pointcut, "#eql?" do
|
548
|
+
it "should return true for the same Aquarium::Aspects::Pointcut object." do
|
549
|
+
pc = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /_test_method$/
|
550
|
+
pc.should eql(pc)
|
551
|
+
pc1 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicClassMethod.new, :methods => /_test_method$/
|
552
|
+
pc1.should eql(pc1)
|
553
|
+
end
|
554
|
+
|
555
|
+
it "should return true for Aquarium::Aspects::Pointcuts that specify the same types and methods." do
|
556
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /_test_method$/
|
557
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /_test_method$/
|
558
|
+
pc1.should eql(pc2)
|
559
|
+
end
|
560
|
+
|
561
|
+
it "should return false for Aquarium::Aspects::Pointcuts that specify different types." do
|
562
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /ClassWithPublicMethod/
|
563
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
564
|
+
pc1.should_not eql(pc2)
|
565
|
+
end
|
566
|
+
|
567
|
+
it "should return false for Aquarium::Aspects::Pointcuts that specify different types, even if no methods match." do
|
568
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /ClassWithPublicMethod/, :methods => /foobar/
|
569
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/ , :methods => /foobar/
|
570
|
+
pc1.should_not eql(pc2)
|
571
|
+
end
|
572
|
+
|
573
|
+
it "should return false for Aquarium::Aspects::Pointcuts that specify different methods." do
|
574
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /ClassWithPublicMethod/, :methods =>/^private/
|
575
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /ClassWithPublicMethod/, :methods =>/^public/
|
576
|
+
pc1.should_not eql(pc2)
|
577
|
+
end
|
578
|
+
|
579
|
+
it "should return false for Aquarium::Aspects::Pointcuts that specify equivalent objects that are not the same object." do
|
580
|
+
pc1 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicClassMethod.new, :methods => /_test_method$/
|
581
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicClassMethod.new, :methods => /_test_method$/
|
582
|
+
pc1.should_not eql(pc2)
|
583
|
+
end
|
584
|
+
|
585
|
+
it "should return false for Aquarium::Aspects::Pointcuts that specify equivalent objects that are not the same object, even if no methods match." do
|
586
|
+
pc1 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicClassMethod.new, :methods => /foobar/
|
587
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicClassMethod.new, :methods => /foobar/
|
588
|
+
pc1.should_not eql(pc2)
|
589
|
+
end
|
590
|
+
|
591
|
+
it "should return false if the matched types are different." do
|
592
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /ClassWithPublicMethod/
|
593
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
594
|
+
pc1.should_not eql(pc2)
|
595
|
+
end
|
596
|
+
|
597
|
+
it "should return false if the matched objects are different." do
|
598
|
+
pc1 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicClassMethod.new, :methods => /_test_method$/
|
599
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => ClassWithPrivateClassMethod.new, :methods => /_test_method$/
|
600
|
+
pc1.should_not eql(pc2)
|
601
|
+
end
|
602
|
+
|
603
|
+
it "should return false if the not_matched types are different." do
|
604
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Foo/
|
605
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Bar/
|
606
|
+
pc1.should_not eql(pc2)
|
607
|
+
end
|
608
|
+
|
609
|
+
it "should return false if the matched methods for the same types are different." do
|
610
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /public.*_test_method$/
|
611
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /_test_method$/
|
612
|
+
pc1.should_not == pc2
|
613
|
+
end
|
614
|
+
|
615
|
+
it "should return false if the matched methods for the same objects are different." do
|
616
|
+
pub = ClassWithPublicInstanceMethod.new
|
617
|
+
pri = ClassWithPrivateInstanceMethod.new
|
618
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :methods => /public.*_test_method$/
|
619
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :methods => /_test_method$/
|
620
|
+
pc1.should_not == pc2
|
621
|
+
end
|
622
|
+
|
623
|
+
it "should return false if the not_matched methods for the same types are different." do
|
624
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /foo/
|
625
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /bar/
|
626
|
+
pc1.should_not == pc2
|
627
|
+
end
|
628
|
+
|
629
|
+
it "should return false if the not_matched methods for the same objects are different." do
|
630
|
+
pub = ClassWithPublicInstanceMethod.new
|
631
|
+
pri = ClassWithPrivateInstanceMethod.new
|
632
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :methods => /foo/
|
633
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :methods => /bar/
|
634
|
+
pc1.should_not == pc2
|
635
|
+
end
|
636
|
+
|
637
|
+
it "should return false if the matched attributes for the same types are different." do
|
638
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :attributes => /attrRW/
|
639
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :attributes => /attrR/
|
640
|
+
pc1.should_not == pc2
|
641
|
+
end
|
642
|
+
|
643
|
+
it "should return false if the matched attributes for the same objects are different." do
|
644
|
+
pub = ClassWithPublicInstanceMethod.new
|
645
|
+
pri = ClassWithPrivateInstanceMethod.new
|
646
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :attributes => /attrRW/
|
647
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :attributes => /attrR/
|
648
|
+
pc1.should_not == pc2
|
649
|
+
end
|
650
|
+
|
651
|
+
it "should return false if the not_matched attributes for the same types are different." do
|
652
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :attributes => /foo/
|
653
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :attributes => /bar/
|
654
|
+
pc1.should_not == pc2
|
655
|
+
end
|
656
|
+
|
657
|
+
it "should return false if the not_matched attributes for the same objects are different." do
|
658
|
+
pub = ClassWithPublicInstanceMethod.new
|
659
|
+
pri = ClassWithPrivateInstanceMethod.new
|
660
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :attributes => /foo/
|
661
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => [pub, pri], :attributes => /bar/
|
662
|
+
pc1.should_not == pc2
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
describe "Aquarium::Aspects::Pointcut#eql?" do
|
667
|
+
it "should be an alias for #==" do
|
668
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /_test_method$/
|
669
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :methods => /_test_method$/
|
670
|
+
pc3 = Aquarium::Aspects::Pointcut.new :objects => [ClassWithPublicInstanceMethod.new, ClassWithPublicInstanceMethod.new]
|
671
|
+
pc1.should eql(pc1)
|
672
|
+
pc1.should eql(pc2)
|
673
|
+
pc1.should_not eql(pc3)
|
674
|
+
pc2.should_not eql(pc3)
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
describe "Aquarium::Aspects::Pointcut#candidate_types" do
|
679
|
+
setup do
|
680
|
+
common_setup
|
681
|
+
end
|
682
|
+
|
683
|
+
it "should return only candidate matching types when the input types exist." do
|
684
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types
|
685
|
+
pc.candidate_types.matched_keys.sort {|x,y| x.to_s <=> y.to_s}.should == @example_types.sort {|x,y| x.to_s <=> y.to_s}
|
686
|
+
pc.candidate_types.not_matched_keys.should == []
|
687
|
+
end
|
688
|
+
|
689
|
+
it "should return only candidate matching types when the input type names correspond to existing types." do
|
690
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types.map {|t| t.to_s}
|
691
|
+
pc.candidate_types.matched_keys.sort {|x,y| x.to_s <=> y.to_s}.should == @example_types.sort {|x,y| x.to_s <=> y.to_s}
|
692
|
+
pc.candidate_types.not_matched_keys.should == []
|
693
|
+
end
|
694
|
+
|
695
|
+
it "should return only candidate non-matching types when the input types do not exist." do
|
696
|
+
pc = Aquarium::Aspects::Pointcut.new :types => 'NonExistentClass'
|
697
|
+
pc.candidate_types.matched_keys.should == []
|
698
|
+
pc.candidate_types.not_matched_keys.should == ['NonExistentClass']
|
699
|
+
end
|
700
|
+
|
701
|
+
it "should return no candidate matching or non-matching types when only objects are input." do
|
702
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => @example_types.map {|t| t.new}
|
703
|
+
pc.candidate_types.matched_keys.should == []
|
704
|
+
pc.candidate_types.not_matched_keys.should == []
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
708
|
+
describe "Aquarium::Aspects::Pointcut#candidate_objects" do
|
709
|
+
setup do
|
710
|
+
common_setup
|
711
|
+
end
|
712
|
+
|
713
|
+
it "should return only candidate matching objects when the input are objects." do
|
714
|
+
example_objs = @example_types.map {|t| t.new}
|
715
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => example_objs
|
716
|
+
example_objs.each do |obj|
|
717
|
+
pc.candidate_objects.matched[obj].should_not be(nil?)
|
718
|
+
end
|
719
|
+
pc.candidate_objects.not_matched_keys.should == []
|
720
|
+
end
|
721
|
+
end
|
722
|
+
|
723
|
+
describe "Aquarium::Aspects::Pointcut#specification" do
|
724
|
+
setup do
|
725
|
+
common_setup
|
726
|
+
@expected_specification_subset = {
|
727
|
+
:methods => [:all], :method_options => [:suppress_ancestor_methods],
|
728
|
+
:attributes => [], :attribute_options => []}
|
729
|
+
@empty_set = Set.new
|
730
|
+
end
|
731
|
+
|
732
|
+
it "should return ':attribute_options => []', by default, if no arguments are given." do
|
733
|
+
pc = Aquarium::Aspects::Pointcut.new
|
734
|
+
pc.specification.should == { :types => @empty_set, :objects => @empty_set, :default_object => @empty_set,
|
735
|
+
:methods => Set.new([:all]), :method_options => Set.new([]),
|
736
|
+
:attributes => @empty_set, :attribute_options => @empty_set }
|
737
|
+
end
|
738
|
+
|
739
|
+
it "should return the input :types and :type arguments combined into an array keyed by :types." do
|
740
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :type => String
|
741
|
+
pc.specification.should == { :types => Set.new(@example_types + [String]), :objects => @empty_set, :default_object => @empty_set,
|
742
|
+
:methods => Set.new([:all]), :method_options => Set.new([]),
|
743
|
+
:attributes => @empty_set, :attribute_options => @empty_set }
|
744
|
+
end
|
745
|
+
|
746
|
+
it "should return the input :objects and :object arguments combined into an array keyed by :objects." do
|
747
|
+
example_objs = @example_types.map {|t| t.new}
|
748
|
+
s1234 = "1234"
|
749
|
+
pc = Aquarium::Aspects::Pointcut.new :objects => example_objs, :object => s1234
|
750
|
+
pc.specification.should == { :types => @empty_set, :objects => Set.new(example_objs + [s1234]), :default_object => @empty_set,
|
751
|
+
:methods => Set.new([:all]), :method_options => Set.new([]),
|
752
|
+
:attributes => @empty_set, :attribute_options => @empty_set }
|
753
|
+
end
|
754
|
+
|
755
|
+
it "should return the input :methods and :method arguments combined into an array keyed by :methods." do
|
756
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :methods => /^get/, :method => "dup"
|
757
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :default_object => @empty_set,
|
758
|
+
:methods => Set.new([/^get/, "dup"]), :method_options => Set.new([]),
|
759
|
+
:attributes => @empty_set, :attribute_options => @empty_set }
|
760
|
+
end
|
761
|
+
|
762
|
+
it "should return the input :method_options verbatim." do
|
763
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :methods => /^get/, :method => "dup", :method_options => [:instance, :public]
|
764
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :default_object => @empty_set,
|
765
|
+
:methods => Set.new([/^get/, "dup"]), :method_options => Set.new([:instance, :public]),
|
766
|
+
:attributes => @empty_set, :attribute_options => @empty_set }
|
767
|
+
end
|
768
|
+
|
769
|
+
it "should return the input :methods and :method arguments combined into an array keyed by :methods." do
|
770
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :attributes => /^state/, :attribute => "name"
|
771
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :default_object => @empty_set,
|
772
|
+
:methods => @empty_set, :method_options => Set.new([]),
|
773
|
+
:attributes => Set.new([/^state/, "name"]), :attribute_options => @empty_set }
|
774
|
+
end
|
775
|
+
|
776
|
+
it "should return the input :attributes, :attribute and :attribute_options arguments, verbatim." do
|
777
|
+
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :attributes => /^state/, :attribute => "name", :attribute_options => :reader
|
778
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :default_object => @empty_set,
|
779
|
+
:methods => @empty_set, :method_options => Set.new([]),
|
780
|
+
:attributes => Set.new([/^state/, "name"]), :attribute_options => Set.new([:reader]) }
|
781
|
+
end
|
782
|
+
end
|
783
|
+
|
784
|
+
describe "Aquarium::Aspects::Pointcut.make_attribute_method_names" do
|
785
|
+
before do
|
786
|
+
@expected_attribs = Set.new(%w[a a= b b= c c= d d=])
|
787
|
+
end
|
788
|
+
|
789
|
+
it "should generate attribute reader and writer method names when the attribute name is prefixed with @." do
|
790
|
+
Aquarium::Aspects::Pointcut.make_attribute_method_names(%w[@a @b @c @d]).should == @expected_attribs
|
791
|
+
end
|
792
|
+
|
793
|
+
it "should generate attribute reader and writer method names when the attribute name is not prefixed with @." do
|
794
|
+
Aquarium::Aspects::Pointcut.make_attribute_method_names(%w[a b c d]).should == @expected_attribs
|
795
|
+
end
|
796
|
+
|
797
|
+
it "should generate attribute reader and writer method names when the attribute name is a symbol." do
|
798
|
+
Aquarium::Aspects::Pointcut.make_attribute_method_names([:a, :b, :c, :d]).should == @expected_attribs
|
799
|
+
end
|
800
|
+
end
|