aquarium 0.5.1 → 0.7.1
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.
- 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
|
+
|