aquarium 0.1.6 → 0.1.7
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 +18 -0
- data/README +68 -39
- data/RELEASE-PLAN +25 -1
- data/UPGRADE +4 -0
- data/examples/aspect_design_example.rb +9 -3
- data/examples/aspect_design_example_spec.rb +7 -2
- data/examples/method_tracing_example.rb +1 -1
- data/examples/method_tracing_example_spec.rb +2 -2
- data/lib/aquarium/aspects/aspect.rb +53 -60
- data/lib/aquarium/aspects/dsl/aspect_dsl.rb +0 -1
- data/lib/aquarium/aspects/pointcut.rb +72 -17
- data/lib/aquarium/aspects/pointcut_composition.rb +4 -1
- data/lib/aquarium/extensions/hash.rb +65 -28
- data/lib/aquarium/extensions/set.rb +2 -0
- data/lib/aquarium/finders/finder_result.rb +13 -2
- data/lib/aquarium/finders/method_finder.rb +54 -28
- data/lib/aquarium/finders/type_finder.rb +36 -19
- data/lib/aquarium/utils/method_utils.rb +3 -12
- data/lib/aquarium/utils/name_utils.rb +27 -1
- data/lib/aquarium/version.rb +1 -1
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +182 -51
- data/spec/aquarium/aspects/aspect_spec.rb +43 -8
- data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +32 -3
- data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +36 -5
- data/spec/aquarium/aspects/pointcut_spec.rb +373 -99
- data/spec/aquarium/extensions/hash_spec.rb +129 -38
- data/spec/aquarium/finders/finder_result_spec.rb +73 -15
- data/spec/aquarium/finders/method_finder_spec.rb +156 -72
- data/spec/aquarium/finders/object_finder_spec.rb +1 -0
- data/spec/aquarium/finders/type_finder_spec.rb +43 -0
- data/spec/aquarium/utils/name_utils_spec.rb +79 -4
- metadata +3 -3
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'set'
|
2
2
|
require File.dirname(__FILE__) + '/../utils/array_utils'
|
3
3
|
require File.dirname(__FILE__) + '/../utils/invalid_options'
|
4
|
+
require File.dirname(__FILE__) + '/../extensions/hash'
|
4
5
|
require File.dirname(__FILE__) + '/../extensions/regexp'
|
5
6
|
require File.dirname(__FILE__) + '/../extensions/symbol'
|
6
7
|
require File.dirname(__FILE__) + '/finder_result'
|
@@ -27,6 +28,13 @@ module Aquarium
|
|
27
28
|
# <tt>:name => type_or_type_name_or_regexp</tt>::
|
28
29
|
# Sugar for specifying one type name.
|
29
30
|
#
|
31
|
+
# <tt>:exclude_type => type_or_type_name_or_regexp</tt>::
|
32
|
+
# <tt>:exclude_types => type_or_type_name_or_regexp</tt>::
|
33
|
+
# <tt>:exclude_name => type_or_type_name_or_regexp</tt>::
|
34
|
+
# <tt>:exclude_names => type_or_type_name_or_regexp</tt>::
|
35
|
+
# Exclude matching types from the list. These excluded types <b>won't</b> appear
|
36
|
+
# in the FinderResult#not_matched.
|
37
|
+
#
|
30
38
|
# Actually, there is actually no difference between <tt>:types</tt>,
|
31
39
|
# <tt>:type</tt>, <tt>:names</tt>, and <tt>:name</tt>. The extra forms are "sugar"...
|
32
40
|
#
|
@@ -50,18 +58,23 @@ module Aquarium
|
|
50
58
|
# the whole name between the "::" exactly.
|
51
59
|
#
|
52
60
|
def find options = {}
|
53
|
-
result
|
61
|
+
result = Aquarium::Finders::FinderResult.new
|
62
|
+
excluded = Aquarium::Finders::FinderResult.new
|
54
63
|
unknown_options = []
|
55
64
|
options.each do |option, value|
|
56
|
-
|
57
|
-
when "names", "types", "name", "type"
|
58
|
-
result << find_all_by(value)
|
59
|
-
else
|
65
|
+
unless TypeFinder.is_recognized_option option
|
60
66
|
unknown_options << option
|
67
|
+
next
|
68
|
+
end
|
69
|
+
|
70
|
+
if option.to_s =~ /^exclude_/
|
71
|
+
excluded << find_all_by(value)
|
72
|
+
else
|
73
|
+
result << find_all_by(value)
|
61
74
|
end
|
62
75
|
end
|
63
76
|
raise Aquarium::Utils::InvalidOptions.new("Unknown options: #{unknown_options.inspect}.") if unknown_options.size > 0
|
64
|
-
result
|
77
|
+
result - excluded
|
65
78
|
end
|
66
79
|
|
67
80
|
# For a name (not a regular expression), return the corresponding type.
|
@@ -83,22 +96,11 @@ module Aquarium
|
|
83
96
|
|
84
97
|
def find_all_by regexpes_or_names
|
85
98
|
raise Aquarium::Utils::InvalidOptions.new("Input type(s) can't be nil!") if regexpes_or_names.nil?
|
86
|
-
|
87
|
-
expressions = make_array regexpes_or_names
|
88
|
-
expressions.each do |expression|
|
89
|
-
expr = strip expression
|
90
|
-
next if empty expr
|
91
|
-
if expr.kind_of? Regexp
|
92
|
-
result << find_namespace_matched(expr)
|
93
|
-
else
|
94
|
-
result << find_by_name(expr)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
result
|
99
|
+
find_matching regexpes_or_names
|
98
100
|
end
|
99
101
|
|
100
102
|
def self.is_recognized_option option_or_symbol
|
101
|
-
%w[name names type types].include? option_or_symbol.to_s
|
103
|
+
%w[name names type types exclude_type exclude_types exclude_name exclude_names].include? option_or_symbol.to_s
|
102
104
|
end
|
103
105
|
|
104
106
|
private
|
@@ -112,6 +114,21 @@ module Aquarium
|
|
112
114
|
expression.nil? || (expression.respond_to?(:empty?) && expression.empty?)
|
113
115
|
end
|
114
116
|
|
117
|
+
def find_matching regexpes_or_names
|
118
|
+
result = Aquarium::Finders::FinderResult.new
|
119
|
+
expressions = make_array regexpes_or_names
|
120
|
+
expressions.each do |expression|
|
121
|
+
expr = strip expression
|
122
|
+
next if empty expr
|
123
|
+
if expr.kind_of? Regexp
|
124
|
+
result << find_namespace_matched(expr)
|
125
|
+
else
|
126
|
+
result << find_by_name(expr)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
result
|
130
|
+
end
|
131
|
+
|
115
132
|
def find_namespace_matched expression
|
116
133
|
expr = expression.kind_of?(Regexp) ? expression.source : expression.to_s
|
117
134
|
return nil if expr.empty?
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'aquarium/utils/type_utils'
|
2
|
+
|
1
3
|
module Aquarium
|
2
4
|
module Utils
|
3
5
|
module MethodUtils
|
@@ -29,15 +31,12 @@ module Aquarium
|
|
29
31
|
end
|
30
32
|
|
31
33
|
private
|
32
|
-
def self.determine_meta_method_suffixes2 type_or_instance, class_or_instance_only
|
33
|
-
["method_defined"]
|
34
|
-
end
|
35
34
|
|
36
35
|
def self.determine_meta_method_suffixes type_or_instance, class_or_instance_only
|
37
36
|
limits = class_or_instance_only.nil? ? [:instance_method_only, :class_method_only] : [class_or_instance_only]
|
38
37
|
meta_method_suffixes = []
|
39
38
|
limits.each do |limit|
|
40
|
-
if (is_type? type_or_instance)
|
39
|
+
if (Aquarium::Utils::TypeUtils.is_type? type_or_instance)
|
41
40
|
meta_method_suffixes << "instance_methods" if limit == :instance_method_only
|
42
41
|
meta_method_suffixes << "methods" if limit == :class_method_only
|
43
42
|
else
|
@@ -47,14 +46,6 @@ module Aquarium
|
|
47
46
|
meta_method_suffixes
|
48
47
|
end
|
49
48
|
|
50
|
-
def self.is_type? type_or_instance
|
51
|
-
type_or_instance.kind_of?(Class) || type_or_instance.kind_of?(Module)
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.find_method2 type_or_instance, method_sym, meta_method
|
55
|
-
type_or_instance.send(meta_method, method_sym.to_s)
|
56
|
-
end
|
57
|
-
|
58
49
|
def self.find_method type_or_instance, method_sym, meta_method
|
59
50
|
type_or_instance.send(meta_method).include?(method_sym.to_s)
|
60
51
|
end
|
@@ -6,6 +6,28 @@ module Aquarium
|
|
6
6
|
module Utils
|
7
7
|
module NameUtils
|
8
8
|
|
9
|
+
@@char_map = {
|
10
|
+
'=' => '_equal_',
|
11
|
+
'?' => '_questionmark_',
|
12
|
+
'!' => '_exclamationmark_',
|
13
|
+
'~' => '_tilde_',
|
14
|
+
'-' => '_minus_',
|
15
|
+
'+' => '_plus_',
|
16
|
+
'/' => '_slash_',
|
17
|
+
'*' => '_star_',
|
18
|
+
'<' => '_lessthan_',
|
19
|
+
'>' => '_greaterthan_',
|
20
|
+
'<<' => '_leftshift_',
|
21
|
+
'>>' => '_rightshift_',
|
22
|
+
'=~' => '_matches_',
|
23
|
+
'%' => '_percent_',
|
24
|
+
'^' => '_caret_',
|
25
|
+
'[]' => '_brackets_',
|
26
|
+
'&' => '_ampersand_',
|
27
|
+
'|' => '_pipe_',
|
28
|
+
'`' => '_backtick_'
|
29
|
+
}
|
30
|
+
|
9
31
|
def self.make_type_or_object_key type_or_object
|
10
32
|
if Aquarium::Utils::TypeUtils.is_type?(type_or_object)
|
11
33
|
make_valid_type_name type_or_object
|
@@ -28,7 +50,11 @@ module Aquarium
|
|
28
50
|
end
|
29
51
|
|
30
52
|
def self.make_valid_attr_name_from_method_name method_name
|
31
|
-
method_name.to_s
|
53
|
+
new_name = method_name.to_s
|
54
|
+
@@char_map.each do |char, substitute|
|
55
|
+
new_name.gsub! char, substitute
|
56
|
+
end
|
57
|
+
new_name.intern
|
32
58
|
end
|
33
59
|
end
|
34
60
|
end
|
data/lib/aquarium/version.rb
CHANGED
@@ -38,88 +38,219 @@ describe Aspect, "#new, when the arguments contain more than one advice type," d
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def aspects_should_be_equal num_jps, aspect1, aspect2
|
42
|
+
# We don't use @aspect1.should eql(@aspect2) because the "specifications" are different.
|
43
|
+
aspect1.pointcuts.size.should == 1
|
44
|
+
aspect2.pointcuts.size.should == 1
|
45
|
+
aspect1.pointcuts.should eql(aspect2.pointcuts)
|
46
|
+
aspect1.advice.should eql(@advice)
|
47
|
+
aspect2.advice.should eql(@advice)
|
48
|
+
join_points_should_be_equal num_jps, aspect1, aspect2
|
49
|
+
end
|
50
|
+
|
51
|
+
def join_points_should_be_equal num_jps, aspect1, aspect2
|
52
|
+
aspect1.join_points_matched.size.should == num_jps
|
53
|
+
aspect2.join_points_matched.size.should == num_jps
|
54
|
+
aspect1.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
|
55
|
+
aspect2.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
|
56
|
+
aspect1.join_points_matched.should eql(aspect2.join_points_matched)
|
57
|
+
aspect1.join_points_not_matched.should eql(aspect2.join_points_not_matched)
|
58
|
+
end
|
59
|
+
|
41
60
|
describe Aspect, "#new arguments for specifying the types and methods" do
|
61
|
+
before :each do
|
62
|
+
@advice = proc {|jp,*args| "advice"}
|
63
|
+
@expected_methods = [:public_watchful_method]
|
64
|
+
end
|
65
|
+
after :each do
|
66
|
+
@aspect1.unadvise
|
67
|
+
@aspect2.unadvise
|
68
|
+
end
|
69
|
+
|
42
70
|
it "should advise equivalent join points when :type => T and :method => m is used or :pointcut =>{:type => T, :method => m} is used." do
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# We don't use aspect1.should eql(aspect2) because the "specifications" are different.
|
47
|
-
aspect1.pointcuts.should eql(aspect2.pointcuts)
|
48
|
-
aspect1.pointcuts.should eql(aspect2.pointcuts)
|
49
|
-
aspect1.join_points_matched.should eql(aspect2.join_points_matched)
|
50
|
-
aspect1.advice.should eql(aspect2.advice)
|
51
|
-
aspect1.unadvise
|
71
|
+
@aspect1 = Aspect.new :after, :type => Watchful, :method => :public_watchful_method, &@advice
|
72
|
+
@aspect2 = Aspect.new :after, :pointcut => {:type => Watchful, :method => :public_watchful_method}, &@advice
|
73
|
+
aspects_should_be_equal 1, @aspect1, @aspect2
|
52
74
|
end
|
53
75
|
|
54
76
|
it "should advise equivalent join points when :type => T and :method => m is used or :pointcut => pointcut is used, where pointcut matches :type => T and :method => m." do
|
55
|
-
|
56
|
-
aspect1 = Aspect.new :after, :type => Watchful, :method => :public_watchful_method, &advice
|
77
|
+
@aspect1 = Aspect.new :after, :type => Watchful, :method => :public_watchful_method, &@advice
|
57
78
|
pointcut = Aquarium::Aspects::Pointcut.new :type => Watchful, :method => :public_watchful_method
|
58
|
-
aspect2 = Aspect.new :after, :pointcut => pointcut,
|
59
|
-
aspect1
|
60
|
-
aspect1.join_points_matched.should eql(aspect2.join_points_matched)
|
61
|
-
aspect1.advice.should eql(aspect2.advice)
|
62
|
-
aspect1.unadvise
|
79
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
80
|
+
aspects_should_be_equal 1, @aspect1, @aspect2
|
63
81
|
end
|
64
82
|
|
65
83
|
it "should advise equivalent join points when :pointcut =>{:type => T, :method => m} is used or :pointcut => pointcut is used, where pointcut matches :type => T and :method => m." do
|
66
|
-
|
67
|
-
aspect1 = Aspect.new :after, :pointcut => {:type => Watchful, :method => :public_watchful_method}, &advice
|
84
|
+
@aspect1 = Aspect.new :after, :pointcut => {:type => Watchful, :method => :public_watchful_method}, &@advice
|
68
85
|
pointcut = Aquarium::Aspects::Pointcut.new :type => Watchful, :method => :public_watchful_method
|
69
|
-
aspect2 = Aspect.new :after, :pointcut => pointcut,
|
70
|
-
aspect1
|
71
|
-
aspect1.join_points_matched.should eql(aspect2.join_points_matched)
|
72
|
-
aspect1.advice.should eql(aspect2.advice)
|
73
|
-
aspect1.unadvise
|
86
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
87
|
+
aspects_should_be_equal 1, @aspect1, @aspect2
|
74
88
|
end
|
75
89
|
|
76
90
|
it "should advise an equivalent join point when :type => T and :method => m is used or :pointcut => join_point is used, where join_point matches :type => T and :method => m." do
|
77
|
-
|
78
|
-
advice = proc {|jp,*args| "advice"}
|
79
|
-
aspect1 = Aspect.new :after, :type => Watchful, :method => :public_watchful_method, &advice
|
91
|
+
@aspect1 = Aspect.new :after, :type => Watchful, :method => :public_watchful_method, &@advice
|
80
92
|
join_point = Aquarium::Aspects::JoinPoint.new :type => Watchful, :method => :public_watchful_method
|
81
|
-
aspect2 = Aspect.new :after, :pointcut => join_point,
|
82
|
-
aspect1
|
83
|
-
aspect1.advice.should eql(aspect2.advice)
|
84
|
-
aspect1.unadvise
|
93
|
+
@aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
|
94
|
+
join_points_should_be_equal 1, @aspect1, @aspect2
|
85
95
|
end
|
96
|
+
end
|
86
97
|
|
98
|
+
describe Aspect, "#new arguments for specifying the types and attributes" do
|
99
|
+
class ClassWithAttrib1
|
100
|
+
def initialize *args
|
101
|
+
@state = args
|
102
|
+
end
|
103
|
+
def dummy; end
|
104
|
+
attr_accessor :state
|
105
|
+
end
|
106
|
+
|
107
|
+
before :each do
|
108
|
+
@advice = proc {|jp,*args| "advice"}
|
109
|
+
@expected_methods = [:state, :state=]
|
110
|
+
end
|
111
|
+
after :each do
|
112
|
+
@aspect1.unadvise
|
113
|
+
@aspect2.unadvise
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should not advise any method join points except those corresponding to attribute methods." do
|
117
|
+
@aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, &@advice
|
118
|
+
@aspect2 = Aspect.new :after, :pointcut => {:type => ClassWithAttrib1, :attribute => :state}, &@advice
|
119
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should advise equivalent join points when :type => T and :attribute => a is used or :pointcut =>{:type => T, :attribute => a} is used." do
|
123
|
+
@aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, &@advice
|
124
|
+
@aspect2 = Aspect.new :after, :pointcut => {:type => ClassWithAttrib1, :attribute => :state}, &@advice
|
125
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should advise equivalent join points when :type => T and :attribute => a is used or :pointcut => pointcut is used, where pointcut matches :type => T and :attribute => a." do
|
129
|
+
@aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, &@advice
|
130
|
+
pointcut = Aquarium::Aspects::Pointcut.new :type => ClassWithAttrib1, :attribute => :state
|
131
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
132
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should advise equivalent join points when :pointcut =>{:type => T, :attribute => a} is used or :pointcut => pointcut is used, where pointcut matches :type => T and :attribute => a." do
|
136
|
+
@aspect1 = Aspect.new :after, :pointcut => {:type => ClassWithAttrib1, :attribute => :state}, &@advice
|
137
|
+
pointcut = Aquarium::Aspects::Pointcut.new :type => ClassWithAttrib1, :attribute => :state
|
138
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
139
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should advise equivalent join points when :type => T and :attribute => a (the attribute's reader and writer) is used or :pointcut => [join_points] is used, where the join_points match :type => T and :method => :a and :method => :a=." do
|
143
|
+
# pending "working on Pointcut.new first."
|
144
|
+
@aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, &@advice
|
145
|
+
join_point1 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state
|
146
|
+
join_point2 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state=
|
147
|
+
@aspect2 = Aspect.new :after, :pointcut => Pointcut.new(:join_points => [join_point1, join_point2]), &@advice
|
148
|
+
join_points_should_be_equal 2, @aspect1, @aspect2
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should advise an equivalent join point when :type => T and :method => :a= (the attribute's writer) is used or :pointcut => join_point is used, where join_point matches :type => T and :method => a=." do
|
152
|
+
# pending "working on Pointcut.new first."
|
153
|
+
@aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, :attribute_options => [:writer], &@advice
|
154
|
+
join_point = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state=
|
155
|
+
@aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
|
156
|
+
join_points_should_be_equal 1, @aspect1, @aspect2
|
157
|
+
end
|
87
158
|
end
|
88
159
|
|
89
160
|
describe Aspect, "#new arguments for specifying the objects and methods" do
|
161
|
+
before :each do
|
162
|
+
@advice = proc {|jp,*args| "advice"}
|
163
|
+
@expected_methods = [:public_watchful_method]
|
164
|
+
end
|
165
|
+
after :each do
|
166
|
+
@aspect1.unadvise
|
167
|
+
@aspect2.unadvise
|
168
|
+
end
|
169
|
+
|
90
170
|
it "should advise equivalent join points when :object => o and :method => m is used or :pointcut =>{:object => o, :method => m} is used." do
|
91
|
-
advice = proc {|jp,*args| "advice"}
|
92
171
|
watchful = Watchful.new
|
93
|
-
aspect1 = Aspect.new :after, :object => watchful, :method => :public_watchful_method,
|
94
|
-
aspect2 = Aspect.new :after, :pointcut => {:object => watchful, :method => :public_watchful_method},
|
95
|
-
aspect1
|
96
|
-
aspect1.join_points_matched.should eql(aspect2.join_points_matched)
|
97
|
-
aspect1.advice.should eql(aspect2.advice)
|
98
|
-
aspect1.unadvise
|
172
|
+
@aspect1 = Aspect.new :after, :object => watchful, :method => :public_watchful_method, &@advice
|
173
|
+
@aspect2 = Aspect.new :after, :pointcut => {:object => watchful, :method => :public_watchful_method}, &@advice
|
174
|
+
aspects_should_be_equal 1, @aspect1, @aspect2
|
99
175
|
end
|
100
176
|
|
101
177
|
it "should advise equivalent join points when :object => o and :method => m is used or :pointcut => pointcut is used, where pointcut matches :object => o and :method => m." do
|
102
|
-
advice = proc {|jp,*args| "advice"}
|
103
178
|
watchful = Watchful.new
|
104
|
-
aspect1 = Aspect.new :after, :object => watchful, :method => :public_watchful_method,
|
179
|
+
@aspect1 = Aspect.new :after, :object => watchful, :method => :public_watchful_method, &@advice
|
105
180
|
pointcut = Aquarium::Aspects::Pointcut.new :object => watchful, :method => :public_watchful_method
|
106
|
-
aspect2 = Aspect.new :after, :pointcut => pointcut,
|
107
|
-
aspect1
|
108
|
-
aspect1.join_points_matched.should eql(aspect2.join_points_matched)
|
109
|
-
aspect1.advice.should eql(aspect2.advice)
|
110
|
-
aspect1.unadvise
|
181
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
182
|
+
aspects_should_be_equal 1, @aspect1, @aspect2
|
111
183
|
end
|
112
184
|
|
113
185
|
it "should advise equivalent join points when :pointcut =>{:object => o, :method => m} is used or :pointcut => pointcut is used, where pointcut matches :object => o and :method => m." do
|
114
|
-
advice = proc {|jp,*args| "advice"}
|
115
186
|
watchful = Watchful.new
|
116
|
-
aspect1 = Aspect.new :after, :pointcut => {:object => watchful, :method => :public_watchful_method},
|
187
|
+
@aspect1 = Aspect.new :after, :pointcut => {:object => watchful, :method => :public_watchful_method}, &@advice
|
117
188
|
pointcut = Aquarium::Aspects::Pointcut.new :object => watchful, :method => :public_watchful_method
|
118
|
-
aspect2 = Aspect.new :after, :pointcut => pointcut,
|
119
|
-
aspect1
|
120
|
-
|
121
|
-
|
122
|
-
|
189
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
190
|
+
aspects_should_be_equal 1, @aspect1, @aspect2
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe Aspect, "#new arguments for specifying the objects and attributes" do
|
195
|
+
class ClassWithAttrib2
|
196
|
+
def initialize *args
|
197
|
+
@state = args
|
198
|
+
end
|
199
|
+
def dummy; end
|
200
|
+
attr_accessor :state
|
201
|
+
end
|
202
|
+
|
203
|
+
before :each do
|
204
|
+
@advice = proc {|jp,*args| "advice"}
|
205
|
+
@object = ClassWithAttrib2.new
|
206
|
+
@expected_methods = [:state, :state=]
|
207
|
+
end
|
208
|
+
after :each do
|
209
|
+
@aspect1.unadvise
|
210
|
+
@aspect2.unadvise
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should not advise any method join points except those corresponding to attribute methods." do
|
214
|
+
@aspect1 = Aspect.new :after, :object => @object, :attribute => :state, &@advice
|
215
|
+
@aspect2 = Aspect.new :after, :pointcut => {:object => @object, :attribute => :state}, &@advice
|
216
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should advise equivalent join points when :type => T and :attribute => a is used or :pointcut =>{:type => T, :attribute => a} is used." do
|
220
|
+
@aspect1 = Aspect.new :after, :object => @object, :attribute => :state, &@advice
|
221
|
+
@aspect2 = Aspect.new :after, :pointcut => {:object => @object, :attribute => :state}, &@advice
|
222
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should advise equivalent join points when :type => T and :attribute => a is used or :pointcut => pointcut is used, where pointcut matches :type => T and :attribute => a." do
|
226
|
+
@aspect1 = Aspect.new :after, :object => @object, :attribute => :state, &@advice
|
227
|
+
pointcut = Aquarium::Aspects::Pointcut.new :object => @object, :attribute => :state
|
228
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
229
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should advise equivalent join points when :pointcut =>{:type => T, :attribute => a} is used or :pointcut => pointcut is used, where pointcut matches :type => T and :attribute => a." do
|
233
|
+
@aspect1 = Aspect.new :after, :pointcut => {:object => @object, :attribute => :state}, &@advice
|
234
|
+
pointcut = Aquarium::Aspects::Pointcut.new :object => @object, :attribute => :state
|
235
|
+
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
|
236
|
+
aspects_should_be_equal 2, @aspect1, @aspect2
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should advise equivalent join points when :type => T and :attribute => a (the attribute's reader and writer) is used or :pointcut => [join_points] is used, where the join_points match :type => T and :method => :a and :method => :a=." do
|
240
|
+
# pending "working on Pointcut.new first."
|
241
|
+
@aspect1 = Aspect.new :after, :object => @object, :attribute => :state, &@advice
|
242
|
+
join_point1 = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state
|
243
|
+
join_point2 = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state=
|
244
|
+
@aspect2 = Aspect.new :after, :pointcut => Pointcut.new(:join_points => [join_point1, join_point2]), &@advice
|
245
|
+
join_points_should_be_equal 2, @aspect1, @aspect2
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should advise an equivalent join point when :type => T and :method => :a= (the attribute's writer) is used or :pointcut => join_point is used, where join_point matches :type => T and :method => a=." do
|
249
|
+
# pending "working on Pointcut.new first."
|
250
|
+
@aspect1 = Aspect.new :after, :object => @object, :attribute => :state, :attribute_options => [:writer], &@advice
|
251
|
+
join_point = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state=
|
252
|
+
@aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
|
253
|
+
join_points_should_be_equal 1, @aspect1, @aspect2
|
123
254
|
end
|
124
255
|
end
|
125
256
|
|