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,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
|