aquarium 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,302 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../spec_example_classes'
|
3
|
+
|
4
|
+
require 'aquarium/extensions/hash'
|
5
|
+
require 'aquarium/aspects/join_point'
|
6
|
+
|
7
|
+
class Dummy
|
8
|
+
def eql?; false; end
|
9
|
+
def count; 0; end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Aquarium::Aspects::JoinPoint, "#initialize with invalid parameters" do
|
13
|
+
|
14
|
+
it "should require either a :type or an :object parameter when creating." do
|
15
|
+
lambda { Aquarium::Aspects::JoinPoint.new :method_name => :count }.should raise_error(Aquarium::Utils::InvalidOptions)
|
16
|
+
lambda { Aquarium::Aspects::JoinPoint.new :type => String, :object => "", :method_name => :count }.should raise_error(Aquarium::Utils::InvalidOptions)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should require a :method_name parameter when creating." do
|
20
|
+
lambda { Aquarium::Aspects::JoinPoint.new :type => String }.should raise_error(Aquarium::Utils::InvalidOptions)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should except :method as a synonym for the :method_name parameter." do
|
24
|
+
lambda { Aquarium::Aspects::JoinPoint.new :type => String, :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Aquarium::Aspects::JoinPoint, "#initialize with invalid parameters" do
|
29
|
+
it "should assume the :method_name refers to an instance method, by default." do
|
30
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split
|
31
|
+
jp.is_instance_method?.should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should treat the :method_name as refering to an instance method if :is_instance_method is specified as true." do
|
35
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :is_instance_method => true
|
36
|
+
jp.is_instance_method?.should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should treat the :method_name as refering to a class method if :is_instance_method is specified as false." do
|
40
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :is_instance_method => false
|
41
|
+
jp.is_instance_method?.should be_false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should treat the :method_name as refering to an instance method if :is_class_method is specified as false." do
|
45
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :is_class_method => false
|
46
|
+
jp.is_instance_method?.should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should treat the :method_name as refering to a class method if :is_class_method is specified as true." do
|
50
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :is_class_method => true
|
51
|
+
jp.is_instance_method?.should be_false
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should treat give precedence to :is_instance_method if appears with :is_class_method." do
|
55
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :is_instance_method => false, :is_class_method => true
|
56
|
+
jp.is_instance_method?.should be_false
|
57
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :is_instance_method => true, :is_class_method => false
|
58
|
+
jp.is_instance_method?.should be_true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe Aquarium::Aspects::JoinPoint, "#dup" do
|
63
|
+
it "should duplicate the fields in the join point." do
|
64
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :count
|
65
|
+
jp2 = jp.dup
|
66
|
+
jp2.should eql(jp)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe Aquarium::Aspects::JoinPoint, "#eql?" do
|
71
|
+
setup do
|
72
|
+
@jp1 = Aquarium::Aspects::JoinPoint.new :type => Dummy, :method_name => :count
|
73
|
+
@jp2 = Aquarium::Aspects::JoinPoint.new :type => Dummy, :method_name => :count
|
74
|
+
@jp3 = Aquarium::Aspects::JoinPoint.new :type => Array, :method_name => :size
|
75
|
+
@jp4 = Aquarium::Aspects::JoinPoint.new :object => [], :method_name => :size
|
76
|
+
@jp5 = Aquarium::Aspects::JoinPoint.new :object => [], :method_name => :size
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should return true for the same join point." do
|
80
|
+
@jp1.should eql(@jp1)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return true for an identical join point." do
|
84
|
+
@jp1.should eql(@jp2)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should return false for a non-identical join point." do
|
88
|
+
@jp1.should_not eql(@jp3)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return false when one join point matches a method for a class and the other matches the same method in an instance of the class." do
|
92
|
+
@jp3.should_not eql(@jp4)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should return false for a non-join point object." do
|
96
|
+
@jp1.should_not eql("foo")
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should return false for two join points that are equal except for the ids of the object they reference." do
|
100
|
+
@jp4.should_not eql(@jp5)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe Aquarium::Aspects::JoinPoint, "#==" do
|
105
|
+
setup do
|
106
|
+
@jp1 = Aquarium::Aspects::JoinPoint.new :type => Dummy, :method_name => :count
|
107
|
+
@jp2 = Aquarium::Aspects::JoinPoint.new :type => Dummy, :method_name => :count
|
108
|
+
@jp3 = Aquarium::Aspects::JoinPoint.new :type => Array, :method_name => :size
|
109
|
+
@jp4 = Aquarium::Aspects::JoinPoint.new :object => [], :method_name => :size
|
110
|
+
@jp5 = Aquarium::Aspects::JoinPoint.new :object => [], :method_name => :size
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should return true for the same join point." do
|
114
|
+
@jp1.should == @jp1
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return true for an identical join point." do
|
118
|
+
@jp1.should == @jp2
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should return false for a non-identical join point." do
|
122
|
+
@jp1.should_not == @jp3
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return false when one join point matches a method for a class and the other matches the same method in an instance of the class." do
|
126
|
+
@jp3.should_not == @jp4
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should return false for a non-join point object." do
|
130
|
+
@jp1.should_not == "foo"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should return false for two join points that are equal except for the ids of the object they reference." do
|
134
|
+
@jp4.should_not == @jp5
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe Aquarium::Aspects::JoinPoint, "#<=>" do
|
139
|
+
setup do
|
140
|
+
@jp1 = Aquarium::Aspects::JoinPoint.new :type => Dummy, :method_name => :count
|
141
|
+
@jp2 = Aquarium::Aspects::JoinPoint.new :type => Dummy, :method_name => :count
|
142
|
+
@jp3 = Aquarium::Aspects::JoinPoint.new :type => Array, :method_name => :size
|
143
|
+
@jp4 = Aquarium::Aspects::JoinPoint.new :object => [], :method_name => :size
|
144
|
+
@jp5 = Aquarium::Aspects::JoinPoint.new :object => [], :method_name => :size
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should sort return 0 for the same join points" do
|
148
|
+
(@jp1.<=>@jp1).should == 0
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should sort return 0 for equivalent join points" do
|
152
|
+
(@jp1.<=>@jp2).should == 0
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should sort by type name first" do
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe Aquarium::Aspects::JoinPoint, "#make_current_context_join_point when the Aquarium::Aspects::JoinPoint::Context object is nil" do
|
160
|
+
it "should return a new join_point that contains the non-context information of the advised_object plus a new Aquarium::Aspects::JoinPoint::Context with the specified context information." do
|
161
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
162
|
+
jp.context.should be_nil
|
163
|
+
object = "12,34"
|
164
|
+
jp_with_context = jp.make_current_context_join_point :advice_kind => :before, :advised_object => object, :parameters => [","], :returned_value => ["12", "34"]
|
165
|
+
jp_with_context.object_id.should_not == jp.object_id
|
166
|
+
jp.context.should be_nil
|
167
|
+
jp_with_context.context.should_not be_nil
|
168
|
+
jp_with_context.context.advice_kind.should == :before
|
169
|
+
jp_with_context.context.advised_object.should == object
|
170
|
+
jp_with_context.context.parameters.should == [","]
|
171
|
+
jp_with_context.context.returned_value.should == ["12", "34"]
|
172
|
+
jp_with_context.context.raised_exception.should be_nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe Aquarium::Aspects::JoinPoint, "#make_current_context_join_point when the Aquarium::Aspects::JoinPoint::Context object is not nil" do
|
177
|
+
it "should return a new join_point that contains the non-context information of the advised_object plus an updated Aquarium::Aspects::JoinPoint::Context with the specified context information." do
|
178
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
179
|
+
object = "12,34"
|
180
|
+
jp.context = Aquarium::Aspects::JoinPoint::Context.new :advice_kind => :before, :advised_object => object, :parameters => [","], :returned_value => ["12", "34"]
|
181
|
+
exception = RuntimeError.new
|
182
|
+
jp_after = jp.make_current_context_join_point :advice_kind => :after, :returned_value => ["12", "34", "56"], :raised_exception => exception
|
183
|
+
jp_after.object_id.should_not == jp.object_id
|
184
|
+
jp_after.context.should_not eql(jp.context)
|
185
|
+
jp.context.advice_kind.should == :before
|
186
|
+
jp.context.advised_object.should == object
|
187
|
+
jp.context.parameters.should == [","]
|
188
|
+
jp.context.returned_value.should == ["12", "34"]
|
189
|
+
jp.context.raised_exception.should be_nil
|
190
|
+
jp_after.context.advice_kind.should == :after
|
191
|
+
jp_after.context.advised_object.should == object
|
192
|
+
jp_after.context.parameters.should == [","]
|
193
|
+
jp_after.context.returned_value.should == ["12", "34", "56"]
|
194
|
+
jp_after.context.raised_exception.should == exception
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe Aquarium::Aspects::JoinPoint, "#type_or_object" do
|
199
|
+
it "should return the type if the object is nil" do
|
200
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
201
|
+
jp.type_or_object.should eql(String)
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should return the object if the type is nil" do
|
205
|
+
jp = Aquarium::Aspects::JoinPoint.new :object => String.new, :method_name => :split
|
206
|
+
jp.type_or_object.should eql("")
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe Aquarium::Aspects::JoinPoint::Context, "#initialize" do
|
211
|
+
it "should require :advice_kind, :advised_object and :parameters arguments." do
|
212
|
+
lambda { Aquarium::Aspects::JoinPoint::Context.new :advised_object => "object", :parameters => [","]}.should raise_error(Aquarium::Utils::InvalidOptions)
|
213
|
+
lambda { Aquarium::Aspects::JoinPoint::Context.new :advice_kind => :before, :parameters => [","]}.should raise_error(Aquarium::Utils::InvalidOptions)
|
214
|
+
lambda { Aquarium::Aspects::JoinPoint::Context.new :advice_kind => :before, :advised_object => "object"}.should raise_error(Aquarium::Utils::InvalidOptions)
|
215
|
+
lambda { Aquarium::Aspects::JoinPoint::Context.new :advice_kind => :before, :advised_object => "object", :parameters => [","]}.should_not raise_error(Aquarium::Utils::InvalidOptions)
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should accept a :returned_value argument." do
|
219
|
+
lambda { Aquarium::Aspects::JoinPoint::Context.new :advice_kind => :before, :advised_object => "object", :parameters => [","], :returned_value => ["12", "34"]}.should_not raise_error(Aquarium::Utils::InvalidOptions)
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should accept a :raised_exception argument." do
|
223
|
+
lambda { Aquarium::Aspects::JoinPoint::Context.new :advice_kind => :before, :advised_object => "object", :parameters => [","], :raised_exception => NameError.new}.should_not raise_error(Aquarium::Utils::InvalidOptions)
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
describe Aquarium::Aspects::JoinPoint::Context, "#target_object" do
|
229
|
+
it "should be a synonym for #advised_object." do
|
230
|
+
@object = "12,34"
|
231
|
+
@jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
232
|
+
@jp_with_context = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object, :parameters => [","], :returned_value => ["12", "34"]
|
233
|
+
@jp_with_context.context.target_object.should == @jp_with_context.context.advised_object
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe Aquarium::Aspects::JoinPoint::Context, "#target_object=" do
|
238
|
+
it "should be a synonym for #advised_object=." do
|
239
|
+
@object = "12,34"
|
240
|
+
@object2 = "12,34,56"
|
241
|
+
@jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
242
|
+
@jp_with_context = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object, :parameters => [","], :returned_value => ["12", "34"]
|
243
|
+
@jp_with_context.context.target_object = @object2
|
244
|
+
@jp_with_context.context.target_object.should == @object2
|
245
|
+
@jp_with_context.context.advised_object.should == @object2
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def do_common_eql_setup
|
250
|
+
@object = "12,34"
|
251
|
+
@object2 = "12,34,56"
|
252
|
+
@jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
253
|
+
@jp_with_context1 = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object, :parameters => [","], :returned_value => ["12", "34"]
|
254
|
+
@jp_with_context2 = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object, :parameters => [","], :returned_value => ["12", "34"]
|
255
|
+
@jp_with_context2b = @jp.make_current_context_join_point :advice_kind => :after, :advised_object => @object, :parameters => [","], :returned_value => ["12", "34"]
|
256
|
+
@jp_with_context2c = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object2, :parameters => [","], :returned_value => ["12", "34"]
|
257
|
+
@jp_with_context2d = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object, :parameters => ["2"], :returned_value => ["1", ",34"]
|
258
|
+
end
|
259
|
+
|
260
|
+
describe Aquarium::Aspects::JoinPoint::Context, "#eql?" do
|
261
|
+
setup do
|
262
|
+
do_common_eql_setup
|
263
|
+
end
|
264
|
+
|
265
|
+
it "should return true for identical contexts." do
|
266
|
+
@jp_with_context1.context.should eql(@jp_with_context2.context)
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should return false for different contexts." do
|
270
|
+
@jp_with_context1.context.should_not eql(@jp_with_context2b.context)
|
271
|
+
@jp_with_context1.context.should_not eql(@jp_with_context2c.context)
|
272
|
+
@jp_with_context1.context.should_not eql(@jp_with_context2d.context)
|
273
|
+
end
|
274
|
+
|
275
|
+
it "should return false if two equal but different objects are specified." do
|
276
|
+
@jp_with_context1 = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object, :parameters => [","], :returned_value => ["12", "34"]
|
277
|
+
jp_with_diff_object = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => "12,34", :parameters => [","], :returned_value => ["12", "34"]
|
278
|
+
@jp_with_context1.context.should_not eql(jp_with_diff_object.context)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe Aquarium::Aspects::JoinPoint::Context, "#==" do
|
283
|
+
setup do
|
284
|
+
do_common_eql_setup
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should return true for identical contexts." do
|
288
|
+
@jp_with_context1.context.should == @jp_with_context2.context
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should return false for different contexts." do
|
292
|
+
@jp_with_context1.context.should_not == @jp_with_context2b.context
|
293
|
+
@jp_with_context1.context.should_not == @jp_with_context2c.context
|
294
|
+
@jp_with_context1.context.should_not == @jp_with_context2d.context
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should return false if two equal but different objects are specified." do
|
298
|
+
@jp_with_context1 = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => @object, :parameters => [","], :returned_value => ["12", "34"]
|
299
|
+
jp_with_diff_object = @jp.make_current_context_join_point :advice_kind => :before, :advised_object => "12,34", :parameters => [","], :returned_value => ["12", "34"]
|
300
|
+
@jp_with_context1.context.should_not == jp_with_diff_object.context
|
301
|
+
end
|
302
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../spec_example_classes'
|
3
|
+
require 'aquarium/utils'
|
4
|
+
require 'aquarium/extensions'
|
5
|
+
require 'aquarium/aspects/pointcut'
|
6
|
+
require 'aquarium/aspects/pointcut_composition'
|
7
|
+
|
8
|
+
describe "Aquarium::Aspects::Pointcut#and" do
|
9
|
+
include Aquarium::Utils::HashUtils
|
10
|
+
include Aquarium::Utils::HtmlEscaper
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
@example_types = {}
|
14
|
+
[ClassWithPublicInstanceMethod, ClassWithProtectedInstanceMethod, ClassWithPrivateInstanceMethod,
|
15
|
+
ClassWithPublicClassMethod, ClassWithPrivateClassMethod].each {|c| @example_types[c] = []}
|
16
|
+
@empty_set = Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return an empty Aquarium::Aspects::Pointcut if the left-hand Aquarium::Aspects::Pointcut is empty, independent of the right-hand Aquarium::Aspects::Pointcut." do
|
20
|
+
pc1 = Aquarium::Aspects::Pointcut.new
|
21
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
22
|
+
(pc1.and(pc2)).should == pc1
|
23
|
+
pc3 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicInstanceMethod.new
|
24
|
+
(pc1.and(pc3)).should == pc1
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return an empty Aquarium::Aspects::Pointcut if the second pointcut has no join points." do
|
28
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
29
|
+
pc2 = Aquarium::Aspects::Pointcut.new
|
30
|
+
(pc1.and(pc2)).should == pc2
|
31
|
+
pc3 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicInstanceMethod.new
|
32
|
+
(pc3.and(pc2)).should == pc2
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return a new Aquarium::Aspects::Pointcut whose join points are the intersection of the left- and right-hand side Aquarium::Aspects::Pointcuts, each with multiple types." do
|
36
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => [ClassWithAttribs, ClassWithPublicInstanceMethod, ClassWithPrivateInstanceMethod], :attributes => [/^attr/], :attribute_options => [:readers]
|
37
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => [ClassWithAttribs, ClassWithPublicInstanceMethod, ClassWithProtectedInstanceMethod], :attributes => :attrRW_ClassWithAttribs
|
38
|
+
pc = pc1.and pc2
|
39
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs
|
40
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
41
|
+
pc.join_points_not_matched.should == @empty_set
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return a new Aquarium::Aspects::Pointcut whose join points are the intersection of the left- and right-hand side Aquarium::Aspects::Pointcuts, each with multiple objects." do
|
45
|
+
cwa = ClassWithAttribs.new
|
46
|
+
pub = ClassWithPublicInstanceMethod.new
|
47
|
+
pri = ClassWithPrivateInstanceMethod.new
|
48
|
+
pro = ClassWithProtectedInstanceMethod.new
|
49
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => [cwa, pub, pri], :attributes => [/^attr/], :attribute_options => [:readers]
|
50
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => [cwa, pub, pro], :attributes => :attrRW_ClassWithAttribs
|
51
|
+
pc = pc1.and pc2
|
52
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs
|
53
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
54
|
+
pc.join_points_not_matched.should == @empty_set
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return a new Aquarium::Aspects::Pointcut whose join points are the intersection of the left- and right-hand side Aquarium::Aspects::Pointcuts, each with a single type." do
|
58
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers]
|
59
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => :attrRW_ClassWithAttribs
|
60
|
+
pc = pc1.and pc2
|
61
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs
|
62
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
63
|
+
pc.join_points_not_matched.should == @empty_set
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should return a new Aquarium::Aspects::Pointcut whose join points are the intersection of the left- and right-hand side Aquarium::Aspects::Pointcuts, each with a single object." do
|
67
|
+
cwa = ClassWithAttribs.new
|
68
|
+
pc1 = Aquarium::Aspects::Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:readers]
|
69
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => cwa, :attributes => :attrRW_ClassWithAttribs
|
70
|
+
pc = pc1.and pc2
|
71
|
+
expected_jp = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs
|
72
|
+
pc.join_points_matched.should == Set.new([expected_jp])
|
73
|
+
pc.join_points_not_matched.should == @empty_set
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should be unitary for type-based Aquarium::Aspects::Pointcuts." do
|
77
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
|
78
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
|
79
|
+
pc = pc1.and pc2
|
80
|
+
pc.should == pc1
|
81
|
+
pc.should == pc2
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should be unitary for object-based Aquarium::Aspects::Pointcuts." do
|
85
|
+
cwa = ClassWithAttribs.new
|
86
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
87
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
88
|
+
pc = pc1.and pc2
|
89
|
+
pc.should == pc1
|
90
|
+
pc.should == pc2
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should be commutative for type-based Aquarium::Aspects::Pointcuts." do
|
94
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
|
95
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
96
|
+
pc12 = pc1.and pc2
|
97
|
+
pc21 = pc2.and pc1
|
98
|
+
pc12.should == pc21
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be commutative for object-based Aquarium::Aspects::Pointcuts." do
|
102
|
+
cwa = ClassWithAttribs.new
|
103
|
+
pub = ClassWithPublicInstanceMethod.new
|
104
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
105
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => pub, :attributes => [/^attr/], :attribute_options => [:writers]
|
106
|
+
pc12 = pc1.and pc2
|
107
|
+
pc21 = pc2.and pc1
|
108
|
+
pc12.should == pc21
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should be associativity for type-based Aquarium::Aspects::Pointcuts." do
|
112
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
|
113
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:readers]
|
114
|
+
pc3 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
115
|
+
pc123a = (pc1.and(pc2)).and(pc3)
|
116
|
+
pc123b = pc1.and(pc2.and(pc3))
|
117
|
+
pc123a.should == pc123b
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should be associativity for object-based Aquarium::Aspects::Pointcuts." do
|
121
|
+
cwa = ClassWithAttribs.new
|
122
|
+
pub = ClassWithPublicInstanceMethod.new
|
123
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
124
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:readers]
|
125
|
+
pc3 = Aquarium::Aspects::Pointcut.new :objects => pub
|
126
|
+
pc123a = (pc1.and(pc2)).and(pc3)
|
127
|
+
pc123b = pc1.and(pc2.and(pc3))
|
128
|
+
pc123a.should == pc123b
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../spec_example_classes'
|
3
|
+
require 'aquarium/utils'
|
4
|
+
require 'aquarium/extensions'
|
5
|
+
require 'aquarium/aspects/pointcut'
|
6
|
+
require 'aquarium/aspects/pointcut_composition'
|
7
|
+
|
8
|
+
describe "Aquarium::Aspects::Pointcut#and" do
|
9
|
+
include Aquarium::Utils::HashUtils
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
classes = [ClassWithProtectedInstanceMethod, ClassWithPrivateInstanceMethod, ClassWithPublicClassMethod, ClassWithPrivateClassMethod]
|
13
|
+
jps_array = classes.map {|c| Aquarium::Aspects::JoinPoint.new :type => c, :method => :all}
|
14
|
+
@not_matched_jps = Set.new(jps_array)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return a Aquarium::Aspects::Pointcut equal to the second, appended, non-empty Aquarium::Aspects::Pointcut if self is empty (has no join points)." do
|
18
|
+
pc1 = Aquarium::Aspects::Pointcut.new
|
19
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
20
|
+
pc1.or(pc2).should eql(pc2)
|
21
|
+
pc3 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicInstanceMethod.new
|
22
|
+
pc1.or(pc3).should eql(pc3)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return a Aquarium::Aspects::Pointcut equal to self if the second pointcut is empty." do
|
26
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
27
|
+
pc2 = Aquarium::Aspects::Pointcut.new
|
28
|
+
pc1.or(pc2).should eql(pc1)
|
29
|
+
pc3 = Aquarium::Aspects::Pointcut.new :object => ClassWithPublicInstanceMethod.new
|
30
|
+
pc3.or(pc2).should eql(pc3)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return a new Aquarium::Aspects::Pointcut whose join points are the union of the left- and right-hand side Aquarium::Aspects::Pointcuts for type-based Aquarium::Aspects::Pointcuts." do
|
34
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers, :suppress_ancestor_methods]
|
35
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :method_options => :suppress_ancestor_methods
|
36
|
+
pc = pc1.or pc2
|
37
|
+
jp1 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs=
|
38
|
+
jp2 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrW_ClassWithAttribs=
|
39
|
+
jp3 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod, :method => :public_instance_test_method
|
40
|
+
pc.join_points_matched.should == Set.new([jp1, jp2, jp3])
|
41
|
+
pc.join_points_not_matched.should == @not_matched_jps
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return a new Aquarium::Aspects::Pointcut whose join points are the union of the left- and right-hand side Aquarium::Aspects::Pointcuts for object-based Aquarium::Aspects::Pointcuts." do
|
45
|
+
cwa = ClassWithAttribs.new
|
46
|
+
pub = ClassWithPublicInstanceMethod.new
|
47
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => [cwa], :attributes => [/^attr/], :attribute_options => [:writers, :suppress_ancestor_methods]
|
48
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => pub, :method_options => :suppress_ancestor_methods
|
49
|
+
pc = pc1.or pc2
|
50
|
+
jp1 = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs=
|
51
|
+
jp2 = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrW_ClassWithAttribs=
|
52
|
+
jp3 = Aquarium::Aspects::JoinPoint.new :object => pub, :method => :public_instance_test_method
|
53
|
+
pc.join_points_matched.sort.should == [jp1, jp2, jp3].sort
|
54
|
+
pc.join_points_not_matched.sort.should == []
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should be unitary for type-based Aquarium::Aspects::Pointcuts." do
|
58
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
|
59
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
|
60
|
+
pc = pc1.or pc2
|
61
|
+
pc.should eql(pc1)
|
62
|
+
pc.should eql(pc2)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should be unitary for object-based Aquarium::Aspects::Pointcuts." do
|
66
|
+
cwa = ClassWithAttribs.new
|
67
|
+
pc1 = Aquarium::Aspects::Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
68
|
+
pc2 = Aquarium::Aspects::Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
69
|
+
pc = pc1.or pc2
|
70
|
+
pc.should eql(pc1)
|
71
|
+
pc.should eql(pc2)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be commutative for type-based Aquarium::Aspects::Pointcuts." do
|
75
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
|
76
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
77
|
+
pc12 = pc1.or pc2
|
78
|
+
pc21 = pc2.or pc1
|
79
|
+
pc12.should eql(pc21)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should be commutative for object-based Aquarium::Aspects::Pointcuts." do
|
83
|
+
cwa = ClassWithAttribs.new
|
84
|
+
pub = ClassWithPublicInstanceMethod.new
|
85
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
86
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => pub, :attributes => [/^attr/], :attribute_options => [:writers]
|
87
|
+
pc12 = pc1.or pc2
|
88
|
+
pc21 = pc2.or pc1
|
89
|
+
pc12.should eql(pc21)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be associativity for type-based Aquarium::Aspects::Pointcuts." do
|
93
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
|
94
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers]
|
95
|
+
pc3 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
|
96
|
+
pc123a = (pc1.or(pc2)).or(pc3)
|
97
|
+
pc123b = pc1.or(pc2.or(pc3))
|
98
|
+
pc123a.should eql(pc123b)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be associativity for object-based Aquarium::Aspects::Pointcuts." do
|
102
|
+
cwa = ClassWithAttribs.new
|
103
|
+
pub = ClassWithPublicInstanceMethod.new
|
104
|
+
pc1 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
|
105
|
+
pc2 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:readers]
|
106
|
+
pc3 = Aquarium::Aspects::Pointcut.new :objects => pub
|
107
|
+
pc123a = (pc1.or(pc2)).or(pc3)
|
108
|
+
pc123b = pc1.or(pc2.or(pc3))
|
109
|
+
pc123a.should eql(pc123b)
|
110
|
+
end
|
111
|
+
end
|