aquarium 0.5.1 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES +240 -215
- data/README +61 -44
- data/RELEASE-PLAN +21 -23
- data/Rakefile +64 -94
- data/UPGRADE +45 -35
- data/aquarium.gemspec +50 -0
- data/examples/README.txt +6 -0
- data/examples/aspect_design_example_spec.rb +2 -2
- data/examples/design_by_contract_example_spec.rb +3 -3
- data/examples/exception_wrapping_example_spec.rb +2 -2
- data/examples/introductions_example_spec.rb +1 -1
- data/examples/method_tracing_example_spec.rb +17 -16
- data/examples/reusable_aspect_hack_example_spec.rb +5 -5
- data/jruby/Rakefile +61 -0
- data/jruby/java/example/Worker.java +9 -0
- data/jruby/java/example/sorter/StringListSorter.java +22 -0
- data/jruby/java/example/sorter/converter/StringListCaseConverterAndSorter.java +42 -0
- data/jruby/java/example/visibility/Visibility.java +13 -0
- data/jruby/spec/java_class_aspects_spec.rb +434 -0
- data/jruby/spec/java_visibility_spec.rb +122 -0
- data/jruby/spec/spec_helper.rb +5 -0
- data/lib/aquarium/aspects/aspect.rb +8 -4
- data/lib/aquarium/utils/type_utils.rb +4 -1
- data/lib/aquarium/version.rb +29 -28
- data/previous_failures.txt +0 -0
- data/rspec.watchr +60 -0
- data/spec/aquarium/aspects/advice_spec.rb +10 -10
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +79 -79
- data/spec/aquarium/aspects/aspect_spec.rb +73 -73
- data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +5 -5
- data/spec/aquarium/aspects/concurrent_aspects_spec.rb +1 -1
- data/spec/aquarium/aspects/default_objects_handler_spec.rb +5 -5
- data/spec/aquarium/aspects/join_point_spec.rb +40 -40
- data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +8 -8
- data/spec/aquarium/aspects/pointcut_spec.rb +25 -25
- data/spec/aquarium/extensions/regex_spec.rb +6 -6
- data/spec/aquarium/extras/design_by_contract_spec.rb +6 -6
- data/spec/aquarium/finders/finder_result_spec.rb +2 -2
- data/spec/aquarium/finders/method_finder_spec.rb +24 -24
- data/spec/aquarium/finders/pointcut_finder_spec.rb +10 -10
- data/spec/aquarium/finders/pointcut_finder_spec_test_classes.rb +4 -4
- data/spec/aquarium/finders/type_finder_spec.rb +5 -5
- data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +6 -5
- data/spec/aquarium/finders/type_finder_with_nested_types_spec.rb +2 -2
- data/spec/aquarium/utils/logic_error_spec.rb +1 -1
- data/spec/aquarium/utils/method_utils_spec.rb +38 -38
- data/spec/aquarium/utils/nil_object_spec.rb +11 -11
- data/spec/aquarium/utils/options_utils_spec.rb +8 -8
- data/spec/aquarium/utils/type_utils_spec.rb +3 -3
- metadata +238 -57
@@ -0,0 +1,13 @@
|
|
1
|
+
package example.visibility;
|
2
|
+
import java.util.ArrayList;
|
3
|
+
|
4
|
+
public class Visibility {
|
5
|
+
private ArrayList<String> messages = new ArrayList<String>();
|
6
|
+
public ArrayList<String> getMessages() { return messages; }
|
7
|
+
|
8
|
+
public void publicMethod (String s, int i) { protectedMethod("public: "+s, i); }
|
9
|
+
protected void protectedMethod(String s, int i) { privateMethod("protected: "+s, i); }
|
10
|
+
private void privateMethod (String s, int i) {
|
11
|
+
messages.add("private: "+s+", i="+i);
|
12
|
+
}
|
13
|
+
}
|
@@ -0,0 +1,434 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
include Aquarium::Aspects
|
4
|
+
|
5
|
+
# The Aquarium README summarizes the known bugs and limitations of the JRuby integration.
|
6
|
+
|
7
|
+
class StringLengthListComparator
|
8
|
+
include java.util.Comparator
|
9
|
+
def compare s1, s2
|
10
|
+
s1.length <=> s2.length
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class StringListCaseConverterAndSorterWithConvertCaseOverride < Java::example.sorter.converter.StringListCaseConverterAndSorter
|
15
|
+
def convertCase *args; super *args; end
|
16
|
+
end
|
17
|
+
|
18
|
+
java_example_types = [
|
19
|
+
Java::example.Worker,
|
20
|
+
Java::example.sorter.StringListSorter,
|
21
|
+
Java::example.sorter.converter.StringListCaseConverterAndSorter,
|
22
|
+
StringListCaseConverterAndSorterWithConvertCaseOverride]
|
23
|
+
|
24
|
+
def do_sort list_sorter, method_name = :do_work
|
25
|
+
orig_list = %w[now is the time for all good men to come to the aid of their country]
|
26
|
+
sorted_list = list_sorter.send(method_name,orig_list)
|
27
|
+
sorted_list.should_not eql(orig_list)
|
28
|
+
sorted_list.size.should == orig_list.size
|
29
|
+
expected = %w[is to to of now the for all men the aid time good come their country]
|
30
|
+
sorted_list.to_a.should eql(expected)
|
31
|
+
end
|
32
|
+
|
33
|
+
def is_java_interface? type
|
34
|
+
type.java_class.interface?
|
35
|
+
end
|
36
|
+
|
37
|
+
def log_should_contain_entries
|
38
|
+
@@aspect_log.should_not be_empty
|
39
|
+
@@aspect_log.should include("entering do_work")
|
40
|
+
@@aspect_log.should include("leaving do_work")
|
41
|
+
end
|
42
|
+
|
43
|
+
# def make_advice
|
44
|
+
# return Proc.new { |jp, object, *args|
|
45
|
+
# @@aspect_log += "entering do_work(#{args.inspect})\n"
|
46
|
+
# result = jp.proceed
|
47
|
+
# @@aspect_log += "leaving do_work(#{args.inspect})\n"
|
48
|
+
# result
|
49
|
+
# }
|
50
|
+
# end
|
51
|
+
|
52
|
+
canned_advice = Proc.new { |jp, object, *args|
|
53
|
+
@@aspect_log += "entering do_work(#{args.inspect})\n"
|
54
|
+
result = jp.proceed
|
55
|
+
@@aspect_log += "leaving do_work(#{args.inspect})\n"
|
56
|
+
result
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
describe "Java type without advice" do
|
61
|
+
it "should not be advised" do
|
62
|
+
do_sort Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
63
|
+
do_sort Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "Java instance with advice" do
|
68
|
+
before :each do
|
69
|
+
@@aspect_log = ""
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should invoke the advice when the advised methods on the same instance are called" do
|
73
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
74
|
+
aspect = Aspect.new :around, :calls_to => :do_work, :object => list_sorter, :advice => canned_advice
|
75
|
+
do_sort list_sorter
|
76
|
+
log_should_contain_entries
|
77
|
+
|
78
|
+
list_sorter2 = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
79
|
+
aspect = Aspect.new :around, :calls_to => :do_work, :object => list_sorter2, :advice => canned_advice
|
80
|
+
@@aspect_log = ""
|
81
|
+
do_sort list_sorter2
|
82
|
+
log_should_contain_entries
|
83
|
+
aspect.unadvise
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "Second Java instance of the same type" do
|
88
|
+
it "should not be advised by the advice applied to a different instance" do
|
89
|
+
aspect = Aspect.new :around, :calls_to => :do_work, :object => Java::example.sorter.StringListSorter.new(StringLengthListComparator.new), :advice => canned_advice
|
90
|
+
list_sorter2 = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
91
|
+
@@aspect_log = ""
|
92
|
+
do_sort list_sorter2
|
93
|
+
@@aspect_log.should be_empty
|
94
|
+
aspect.unadvise
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "Second Java instance of a derived type" do
|
99
|
+
it "should not be advised by the advice applied to an instance of a parent type" do
|
100
|
+
aspect = Aspect.new :around, :calls_to => :do_work, :object => Java::example.sorter.StringListSorter.new(StringLengthListComparator.new), :advice => canned_advice
|
101
|
+
list_sorter2 = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
102
|
+
@@aspect_log = ""
|
103
|
+
do_sort list_sorter2
|
104
|
+
@@aspect_log.should be_empty
|
105
|
+
aspect.unadvise
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "Java instance with advice added then removed" do
|
110
|
+
it "should not be advised after the advice is removed" do
|
111
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
112
|
+
aspect = Aspect.new :around, :calls_to => :do_work, :object => list_sorter, :advice => canned_advice
|
113
|
+
do_sort list_sorter
|
114
|
+
@@aspect_log = ""
|
115
|
+
aspect.unadvise
|
116
|
+
do_sort list_sorter
|
117
|
+
@@aspect_log.should be_empty
|
118
|
+
|
119
|
+
list_sorter2 = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
120
|
+
aspect2 = Aspect.new :around, :calls_to => :do_work, :object => list_sorter2, :advice => canned_advice
|
121
|
+
do_sort list_sorter2
|
122
|
+
@@aspect_log = ""
|
123
|
+
aspect2.unadvise
|
124
|
+
do_sort list_sorter2
|
125
|
+
@@aspect_log.should be_empty
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "Java interface used with :type => ... (or synonym)" do
|
130
|
+
it "should never match join points; you must use :type(s)_and_descendents, instead" do
|
131
|
+
aspect = Aspect.new :around, :calls_to => [:do_work, :doWork], :type => Java::example.Worker, :ignore_no_matching_join_points => true do; end
|
132
|
+
aspect.join_points_matched.should be_empty
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "Java interface used with :type_and_descendents => ... (or synonym)" do
|
137
|
+
before :each do
|
138
|
+
@aspect = Aspect.new :around, :calls_to => :do_work, :type_and_descendents => Java::example.Worker,
|
139
|
+
# :advice => canned_advice
|
140
|
+
:exclude_type => StringListCaseConverterAndSorterWithConvertCaseOverride, :advice => canned_advice
|
141
|
+
@@aspect_log = ""
|
142
|
+
end
|
143
|
+
after :each do
|
144
|
+
@aspect.unadvise unless @aspect.nil?
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should invoke the advice when the advised methods of directly-implementing subclasses are called" do
|
148
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
149
|
+
do_sort list_sorter
|
150
|
+
log_should_contain_entries
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should invoke the advice when the advised methods of indirectly-implementing subclasses are called" do
|
154
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
155
|
+
do_sort list_sorter
|
156
|
+
log_should_contain_entries
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should not invoke the advice after the advice is removed" do
|
160
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
161
|
+
do_sort list_sorter
|
162
|
+
log_should_contain_entries
|
163
|
+
@aspect.unadvise
|
164
|
+
@@aspect_log = ""
|
165
|
+
do_sort list_sorter
|
166
|
+
do_sort Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
167
|
+
@@aspect_log.should be_empty
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should allow #unadvise to be called repeatedly" do
|
171
|
+
expect {@aspect.unadvise}.should_not raise_error
|
172
|
+
expect {@aspect.unadvise}.should_not raise_error
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "Java class used with :type_and_descendents => ..." do
|
177
|
+
before :each do
|
178
|
+
@aspect = Aspect.new :around, :calls_to => :do_work, :type_and_descendents => Java::example.sorter.StringListSorter,
|
179
|
+
:exclude_type => StringListCaseConverterAndSorterWithConvertCaseOverride, :advice => canned_advice
|
180
|
+
@@aspect_log = ""
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should invoke the advice when the advised methods of the class are called" do
|
184
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
185
|
+
do_sort list_sorter
|
186
|
+
log_should_contain_entries
|
187
|
+
@aspect.unadvise
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should invoke the advice when the advised methods of extending subclasses are called" do
|
191
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
192
|
+
do_sort list_sorter
|
193
|
+
log_should_contain_entries
|
194
|
+
@aspect.unadvise
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should not invoke the advice after the advice is removed" do
|
198
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
199
|
+
do_sort list_sorter
|
200
|
+
log_should_contain_entries
|
201
|
+
@aspect.unadvise
|
202
|
+
@@aspect_log = ""
|
203
|
+
do_sort list_sorter
|
204
|
+
do_sort Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
205
|
+
@@aspect_log.should be_empty
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "Derived Java class used with :type_and_descendents => ..." do
|
210
|
+
before :each do
|
211
|
+
@@aspect_log = ""
|
212
|
+
@aspect = Aspect.new :around, :calls_to => :do_work, :type_and_descendents => Java::example.sorter.converter.StringListCaseConverterAndSorter,
|
213
|
+
:exclude_type => StringListCaseConverterAndSorterWithConvertCaseOverride, :advice => canned_advice
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should not invoke the advice when the advised methods of parent classes are called" do
|
217
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
218
|
+
do_sort list_sorter
|
219
|
+
@@aspect_log.should be_empty
|
220
|
+
@aspect.unadvise
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should invoke the advice when the advised methods of the same class are called" do
|
224
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
225
|
+
do_sort list_sorter
|
226
|
+
log_should_contain_entries
|
227
|
+
@aspect.unadvise
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should not invoke the advice after the advice is removed" do
|
231
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
232
|
+
do_sort list_sorter
|
233
|
+
log_should_contain_entries
|
234
|
+
@aspect.unadvise
|
235
|
+
@@aspect_log = ""
|
236
|
+
do_sort list_sorter
|
237
|
+
@@aspect_log.should be_empty
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "Derived Java class used with :type_and_ancestors => ..." do
|
242
|
+
before :each do
|
243
|
+
@@aspect_log = ""
|
244
|
+
@aspect = Aspect.new :around, :calls_to => :do_work, :type_and_ancestors => Java::example.sorter.converter.StringListCaseConverterAndSorter, :advice => canned_advice
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should invoke the advice when the advised methods of parent classes are called" do
|
248
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
249
|
+
do_sort list_sorter
|
250
|
+
log_should_contain_entries
|
251
|
+
@aspect.unadvise
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should invoke the advice when the advised methods of the same class are called" do
|
255
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
256
|
+
do_sort list_sorter
|
257
|
+
log_should_contain_entries
|
258
|
+
@aspect.unadvise
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should not invoke the advice after the advice is removed" do
|
262
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
263
|
+
do_sort list_sorter
|
264
|
+
log_should_contain_entries
|
265
|
+
@aspect.unadvise
|
266
|
+
@@aspect_log = ""
|
267
|
+
do_sort list_sorter
|
268
|
+
@@aspect_log.should be_empty
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe "Java camel-case method name 'doFooBar'" do
|
273
|
+
before :each do
|
274
|
+
@@aspect_log = ""
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should be matched when using the camel-case form of the name 'doFooBar'" do
|
278
|
+
aspect = Aspect.new :around, :calls_to => :doWork, :type_and_descendents => Java::example.sorter.StringListSorter,
|
279
|
+
:restricting_methods_to => [:exclude_ancestor_methods], :advice => canned_advice
|
280
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
281
|
+
do_sort list_sorter, :doWork
|
282
|
+
log_should_contain_entries
|
283
|
+
aspect.unadvise
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should be matched when using the underscore form of the name 'do_foo_bar'" do
|
287
|
+
aspect = Aspect.new :around, :calls_to => :do_work, :type_and_descendents => Java::example.sorter.StringListSorter,
|
288
|
+
:restricting_methods_to => [:exclude_ancestor_methods], :advice => canned_advice
|
289
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
290
|
+
do_sort list_sorter
|
291
|
+
log_should_contain_entries
|
292
|
+
aspect.unadvise
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should advise 'doFooBar' separately from 'do_foo_bar', so that invoking 'do_foo_bar' will not invoke the advice!" do
|
296
|
+
aspect = Aspect.new :around, :calls_to => :doWork, :type_and_descendents => Java::example.sorter.StringListSorter,
|
297
|
+
:restricting_methods_to => [:exclude_ancestor_methods], :advice => canned_advice
|
298
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
299
|
+
do_sort list_sorter, :do_work
|
300
|
+
@@aspect_log.should be_empty
|
301
|
+
aspect.unadvise
|
302
|
+
end
|
303
|
+
it "should advise 'do_foo_bar' separately from 'doFooBar', so that invoking 'doFooBar' will not invoke the advice!" do
|
304
|
+
aspect = Aspect.new :around, :calls_to => :do_work, :type_and_descendents => Java::example.sorter.StringListSorter,
|
305
|
+
:restricting_methods_to => [:exclude_ancestor_methods], :advice => canned_advice
|
306
|
+
list_sorter = Java::example.sorter.StringListSorter.new(StringLengthListComparator.new)
|
307
|
+
do_sort list_sorter, :doWork
|
308
|
+
@@aspect_log.should be_empty
|
309
|
+
aspect.unadvise
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "Java method advice" do
|
314
|
+
it "will not be invoked when the method is called by other Java methods" do
|
315
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
316
|
+
@advise_called = false
|
317
|
+
aspect = Aspect.new :before, :calls_to => :convertCase, :in_type => Java::example.sorter.converter.StringListCaseConverterAndSorter do
|
318
|
+
@advise_called = true
|
319
|
+
end
|
320
|
+
do_sort list_sorter
|
321
|
+
@advise_called.should be_falsey
|
322
|
+
aspect.unadvise
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should be invoked when the method is called by other Java methods, using a ruby subclass that overrides the advised method" do
|
326
|
+
list_sorter = StringListCaseConverterAndSorterWithConvertCaseOverride.new(StringLengthListComparator.new)
|
327
|
+
@advise_called = false
|
328
|
+
aspect = Aspect.new :before, :calls_to => :convertCase, :in_type => Java::example.sorter.converter.StringListCaseConverterAndSorter do
|
329
|
+
@advise_called = true
|
330
|
+
end
|
331
|
+
do_sort list_sorter
|
332
|
+
@advise_called.should be_truthy
|
333
|
+
aspect.unadvise
|
334
|
+
end
|
335
|
+
|
336
|
+
it "should be invoked when the method is called by a Ruby method" do
|
337
|
+
list_sorter = Java::example.sorter.converter.StringListCaseConverterAndSorter.new(StringLengthListComparator.new)
|
338
|
+
@advise_called = false
|
339
|
+
aspect = Aspect.new :before, :calls_to => :convertCase, :in_type => Java::example.sorter.converter.StringListCaseConverterAndSorter do
|
340
|
+
@advise_called = true
|
341
|
+
end
|
342
|
+
list_sorter.convertCase(java.util.ArrayList.new)
|
343
|
+
@advise_called.should be_truthy
|
344
|
+
aspect.unadvise
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "Ruby subclass with advice on method in a Java parent class" do
|
349
|
+
it "should be invoked, but isn't, when the method is advised using the Java form of its name (doFoo), rather than the Ruby form (do_foo) -- BUG #18326" do
|
350
|
+
list_sorter = StringListCaseConverterAndSorterWithConvertCaseOverride.new(StringLengthListComparator.new)
|
351
|
+
@advise_called = false
|
352
|
+
aspect = Aspect.new :before, :calls_to => :doWork, :in_type => StringListCaseConverterAndSorterWithConvertCaseOverride do
|
353
|
+
@advise_called = true
|
354
|
+
end
|
355
|
+
do_sort list_sorter
|
356
|
+
@advise_called.should be_falsey
|
357
|
+
# @advise_called.should be_truthy
|
358
|
+
aspect.unadvise
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should be invoked when the method is called by a Ruby method" do
|
362
|
+
list_sorter = StringListCaseConverterAndSorterWithConvertCaseOverride.new(StringLengthListComparator.new)
|
363
|
+
@advise_called = false
|
364
|
+
aspect = Aspect.new :before, :calls_to => :do_work, :in_type => StringListCaseConverterAndSorterWithConvertCaseOverride do
|
365
|
+
@advise_called = true
|
366
|
+
end
|
367
|
+
do_sort list_sorter
|
368
|
+
@advise_called.should be_truthy
|
369
|
+
aspect.unadvise
|
370
|
+
end
|
371
|
+
|
372
|
+
it "should be removed cleanly when aspect#unadvise is called" do
|
373
|
+
list_sorter = StringListCaseConverterAndSorterWithConvertCaseOverride.new(StringLengthListComparator.new)
|
374
|
+
@advise_called = false
|
375
|
+
aspect = Aspect.new :before, :calls_to => :do_work, :in_type => StringListCaseConverterAndSorterWithConvertCaseOverride do
|
376
|
+
@advise_called = true
|
377
|
+
end
|
378
|
+
do_sort list_sorter
|
379
|
+
@advise_called.should be_truthy
|
380
|
+
aspect.unadvise
|
381
|
+
@advise_called = false
|
382
|
+
do_sort list_sorter
|
383
|
+
@advise_called.should be_falsey
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
describe "JDK classes" do
|
388
|
+
it "should be advisable by Aquarium aspects" do
|
389
|
+
@@aspect_log = ""
|
390
|
+
aspect = Aspect.new :before, :calls_to => :add, :on_type => java.util.ArrayList do |jp, obj, *args|
|
391
|
+
@@aspect_log << "adding: #{args[0]}\n"
|
392
|
+
end
|
393
|
+
list = java.util.ArrayList.new
|
394
|
+
list.add(1)
|
395
|
+
list.add(2)
|
396
|
+
@@aspect_log.should include("adding: 1")
|
397
|
+
@@aspect_log.should include("adding: 2")
|
398
|
+
aspect.unadvise
|
399
|
+
@@aspect_log = ""
|
400
|
+
list.add(1)
|
401
|
+
list.add(2)
|
402
|
+
@@aspect_log.should be_empty
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
|
407
|
+
include Aquarium::Utils
|
408
|
+
|
409
|
+
describe TypeUtils, ".descendents" do
|
410
|
+
it "should return Java classes implementing a Java interface" do
|
411
|
+
actual = TypeUtils.descendents Java::example.Worker
|
412
|
+
actual.size.should == java_example_types.size
|
413
|
+
java_example_types.each {|x| actual.should include(x)}
|
414
|
+
end
|
415
|
+
|
416
|
+
it "should return Java classes extending a Java class" do
|
417
|
+
expected = [
|
418
|
+
Java::example.sorter.StringListSorter,
|
419
|
+
Java::example.sorter.converter.StringListCaseConverterAndSorter,
|
420
|
+
StringListCaseConverterAndSorterWithConvertCaseOverride]
|
421
|
+
actual = TypeUtils.descendents Java::example.sorter.StringListSorter
|
422
|
+
actual.size.should == expected.size
|
423
|
+
expected.each {|x| actual.should include(x)}
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
describe "Java::Packages::Type.ancestors" do
|
428
|
+
it "should return Java classes and interfaces that are ancestors of a Java class" do
|
429
|
+
anc = Java::example.sorter.converter.StringListCaseConverterAndSorter.ancestors
|
430
|
+
[Java::example.Worker, Java::example.sorter.StringListSorter, Java::example.sorter.converter.StringListCaseConverterAndSorter].each do |t|
|
431
|
+
anc.should include(t)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
include Aquarium::Aspects
|
4
|
+
|
5
|
+
# The Aquarium README summarizes the known bugs and limitations of the JRuby integration.
|
6
|
+
|
7
|
+
class VisibilityWrapper < Java::example.visibility.Visibility
|
8
|
+
def public_method(s, i); super; end
|
9
|
+
protected
|
10
|
+
def protected_method(s, i); super; end
|
11
|
+
private
|
12
|
+
def private_method(s, i); super; end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Matching on a private method in a Java type" do
|
16
|
+
before :each do
|
17
|
+
@visibility = Java::example.visibility.Visibility.new
|
18
|
+
end
|
19
|
+
|
20
|
+
it "will not match on a private Java method when the default public access method option is used" do
|
21
|
+
aspect = Aspect.new :around, :calls_to => "private_method", :in_object => @visibility,
|
22
|
+
:ignore_no_matching_join_points => true do |jp|
|
23
|
+
end
|
24
|
+
aspect.join_points_matched.should be_empty
|
25
|
+
aspect.unadvise
|
26
|
+
end
|
27
|
+
|
28
|
+
it "will not match on a private Java method, even when the private method option specifier is used" do
|
29
|
+
aspect = Aspect.new :around, :calls_to => "private_method", :in_object => @visibility,
|
30
|
+
:method_options => [:private], :ignore_no_matching_join_points => true do |jp|
|
31
|
+
end
|
32
|
+
aspect.join_points_matched.should be_empty
|
33
|
+
aspect.unadvise
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "Matching on a protected method in a Java type" do
|
38
|
+
before :each do
|
39
|
+
@visibility = Java::example.visibility.Visibility.new
|
40
|
+
end
|
41
|
+
|
42
|
+
it "will treat a protected Java method as publicly visible" do
|
43
|
+
aspect = Aspect.new :around, :calls_to => "protected_method", :in_object => @visibility,
|
44
|
+
:ignore_no_matching_join_points => false do |jp|
|
45
|
+
end
|
46
|
+
aspect.join_points_matched.size.should eql(1)
|
47
|
+
aspect.join_points_matched.each {|jp| jp.method_name.should eql(:protected_method) }
|
48
|
+
aspect.unadvise
|
49
|
+
end
|
50
|
+
|
51
|
+
it "will NOT match on a protected Java method, even when the :protected method option specifier is used" do
|
52
|
+
aspect = Aspect.new :around, :calls_to => "protected_method", :in_object => @visibility,
|
53
|
+
:method_options => [:protected], :ignore_no_matching_join_points => true do |jp|
|
54
|
+
end
|
55
|
+
aspect.join_points_matched.should be_empty
|
56
|
+
aspect.unadvise
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "Matching on a public method in a Java type" do
|
62
|
+
before :each do
|
63
|
+
@visibility = Java::example.visibility.Visibility.new
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should match on a public method when the default public access is used" do
|
67
|
+
aspect = Aspect.new :around, :calls_to => "public_method", :in_object => @visibility,
|
68
|
+
:ignore_no_matching_join_points => false do |jp|
|
69
|
+
end
|
70
|
+
aspect.join_points_matched.size.should eql(1)
|
71
|
+
aspect.join_points_matched.each {|jp| jp.method_name.should eql(:public_method) }
|
72
|
+
aspect.unadvise
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should match on a public method when the public method option specifier is used" do
|
76
|
+
aspect = Aspect.new :around, :calls_to => "public_method", :in_object => @visibility,
|
77
|
+
:method_options => [:public], :ignore_no_matching_join_points => false do |jp|
|
78
|
+
end
|
79
|
+
aspect.join_points_matched.size.should eql(1)
|
80
|
+
aspect.join_points_matched.each {|jp| jp.method_name.should eql(:public_method) }
|
81
|
+
aspect.unadvise
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
%w[private protected public].each do |vis|
|
86
|
+
if vis == "public"
|
87
|
+
not_string = ""
|
88
|
+
ignore_no_matches = false
|
89
|
+
else
|
90
|
+
not_string = "not "
|
91
|
+
ignore_no_matches = true
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "Matching on a #{vis} method in a Ruby type wrapping a Java type where the Ruby type is advised" do
|
95
|
+
before :each do
|
96
|
+
@visibility = VisibilityWrapper.new
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should #{not_string}advise #{vis} methods when the default public access is used" do
|
100
|
+
aspect = Aspect.new :around, :calls_to => "#{vis}_method", :in_object => @visibility,
|
101
|
+
:ignore_no_matching_join_points => ignore_no_matches do |jp|
|
102
|
+
end
|
103
|
+
if vis == "public"
|
104
|
+
aspect.join_points_matched.size.should eql(1)
|
105
|
+
aspect.join_points_matched.each {|jp| jp.method_name.should eql("#{vis}_method".intern) }
|
106
|
+
else
|
107
|
+
aspect.join_points_matched.should be_empty
|
108
|
+
end
|
109
|
+
aspect.unadvise
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should advise #{vis} methods when the same access method option specifier is used" do
|
113
|
+
aspect = Aspect.new :around, :calls_to => "#{vis}_method", :in_object => @visibility,
|
114
|
+
:method_options => [vis.intern], :ignore_no_matching_join_points => ignore_no_matches do |jp|
|
115
|
+
end
|
116
|
+
aspect.join_points_matched.size.should eql(1)
|
117
|
+
aspect.join_points_matched.each {|jp| jp.method_name.should eql("#{vis}_method".intern) }
|
118
|
+
aspect.unadvise
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|