aquarium 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/Aquarium.ipr +253 -0
  2. data/Aquarium.iws +629 -0
  3. data/CHANGES +43 -0
  4. data/UPGRADE +13 -7
  5. data/examples/method_tracing_example_spec.rb +4 -1
  6. data/lib/aquarium/aspects/aspect.rb +28 -11
  7. data/lib/aquarium/aspects/exclusion_handler.rb +1 -1
  8. data/lib/aquarium/aspects/join_point.rb +58 -14
  9. data/lib/aquarium/aspects/pointcut.rb +5 -6
  10. data/lib/aquarium/extras/design_by_contract.rb +1 -1
  11. data/lib/aquarium/finders/method_finder.rb +1 -4
  12. data/lib/aquarium/finders/type_finder.rb +8 -1
  13. data/lib/aquarium/utils.rb +1 -0
  14. data/lib/aquarium/utils/default_logger.rb +20 -0
  15. data/lib/aquarium/utils/options_utils.rb +74 -12
  16. data/lib/aquarium/utils/type_utils.rb +1 -7
  17. data/lib/aquarium/version.rb +1 -1
  18. data/spec/aquarium/aspects/advice_chain_node_spec.rb +1 -1
  19. data/spec/aquarium/aspects/advice_spec.rb +1 -1
  20. data/spec/aquarium/aspects/aspect_invocation_spec.rb +1531 -1465
  21. data/spec/aquarium/aspects/aspect_spec.rb +22 -27
  22. data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +1 -1
  23. data/spec/aquarium/aspects/aspect_with_subtypes_spec.rb +1 -1
  24. data/spec/aquarium/aspects/concurrent_aspects_spec.rb +1 -1
  25. data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +1 -1
  26. data/spec/aquarium/aspects/dsl/aspect_dsl_spec.rb +434 -424
  27. data/spec/aquarium/aspects/join_point_spec.rb +27 -4
  28. data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +98 -102
  29. data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +95 -107
  30. data/spec/aquarium/aspects/pointcut_spec.rb +1365 -1382
  31. data/spec/aquarium/extensions/hash_spec.rb +1 -1
  32. data/spec/aquarium/extensions/set_spec.rb +1 -1
  33. data/spec/aquarium/finders/finder_result_spec.rb +1 -1
  34. data/spec/aquarium/finders/method_finder_spec.rb +1 -1
  35. data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +63 -145
  36. data/spec/aquarium/{spec_example_classes.rb → spec_example_types.rb} +35 -0
  37. data/spec/aquarium/utils/default_logger_spec.rb +28 -0
  38. data/spec/aquarium/utils/hash_utils_spec.rb +1 -1
  39. data/spec/aquarium/utils/logic_error_spec.rb +1 -1
  40. data/spec/aquarium/utils/name_utils_spec.rb +1 -1
  41. data/spec/aquarium/utils/nil_object_spec.rb +1 -1
  42. data/spec/aquarium/utils/options_utils_spec.rb +122 -0
  43. data/spec/aquarium/utils/set_utils_spec.rb +1 -1
  44. metadata +9 -4
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
- require File.dirname(__FILE__) + '/../spec_example_classes'
2
+ require File.dirname(__FILE__) + '/../spec_example_types'
3
3
 
4
4
  require 'aquarium/extensions/hash'
5
5
  require 'aquarium/aspects/join_point'
@@ -22,18 +22,41 @@ end
22
22
 
23
23
  describe Aquarium::Aspects::JoinPoint, "#initialize with invalid parameters" do
24
24
 
25
- it "should require either a :type or an :object parameter when creating." do
25
+ it "should require either a :type or an :object parameter, but not both." do
26
26
  lambda { Aquarium::Aspects::JoinPoint.new :method_name => :count }.should raise_error(Aquarium::Utils::InvalidOptions)
27
27
  lambda { Aquarium::Aspects::JoinPoint.new :type => String, :object => "", :method_name => :count }.should raise_error(Aquarium::Utils::InvalidOptions)
28
28
  end
29
29
 
30
- it "should require a :method_name parameter when creating." do
30
+ it "should require a :method_name." do
31
31
  lambda { Aquarium::Aspects::JoinPoint.new :type => String }.should raise_error(Aquarium::Utils::InvalidOptions)
32
32
  end
33
33
 
34
- it "should except :method as a synonym for the :method_name parameter." do
34
+ it "should except :method as a synonym for :method_name." do
35
35
  lambda { Aquarium::Aspects::JoinPoint.new :type => String, :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
36
36
  end
37
+
38
+ it "should require a valid type name if a name is specified." do
39
+ lambda { Aquarium::Aspects::JoinPoint.new :type => "String", :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
40
+ lambda { Aquarium::Aspects::JoinPoint.new :type => "Stringgy", :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
41
+ end
42
+
43
+ it "should require a valid type name symbol if a name is specified." do
44
+ lambda { Aquarium::Aspects::JoinPoint.new :type => :String, :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
45
+ lambda { Aquarium::Aspects::JoinPoint.new :type => :Stringgy, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
46
+ end
47
+
48
+ it "should require a valid type name regular expression if one is specified." do
49
+ lambda { Aquarium::Aspects::JoinPoint.new :type => /^String$/, :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
50
+ lambda { Aquarium::Aspects::JoinPoint.new :type => /^Stringgy$/, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
51
+ end
52
+
53
+ it "should reject a regular expression that matches no types." do
54
+ lambda { Aquarium::Aspects::JoinPoint.new :type => /^Stringgy$/, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
55
+ end
56
+
57
+ it "should reject a regular expression that matches more than one type." do
58
+ lambda { Aquarium::Aspects::JoinPoint.new :type => /^M/, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
59
+ end
37
60
  end
38
61
 
39
62
  describe Aquarium::Aspects::JoinPoint, "#initialize with parameters that specify class vs. instance methods" do
@@ -1,14 +1,39 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
- require File.dirname(__FILE__) + '/../spec_example_classes'
2
+ require File.dirname(__FILE__) + '/../spec_example_types'
3
3
  require 'aquarium/utils'
4
4
  require 'aquarium/extensions'
5
5
  require 'aquarium/aspects/pointcut'
6
6
  require 'aquarium/aspects/pointcut_composition'
7
7
 
8
- describe "Intersection of Pointcuts", :shared => true do
9
- include Aquarium::Utils::HashUtils
10
- # include Aquarium::Utils::HtmlEscaper
8
+ include Aquarium::Utils::HashUtils
9
+ include Aquarium::Aspects
10
+
11
+ describe Pointcut, "#and" do
12
+ it "should return a new Pointcut." do
13
+ pc1 = Pointcut.new
14
+ pc2 = Pointcut.new :types => ClassWithPublicInstanceMethod, :method_options => :exclude_ancestor_methods
15
+ pc12 = (pc1.and(pc2))
16
+ pc12.should_not equal(pc1)
17
+ pc12.should_not equal(pc2)
18
+ end
19
+ end
20
+
21
+ describe Pointcut, "#and (when one pointcut is empty)" do
22
+ before :all do
23
+ @pc1 = Pointcut.new
24
+ @pc2 = Pointcut.new :types => ClassWithPublicInstanceMethod, :method_options => :exclude_ancestor_methods
25
+ end
11
26
 
27
+ it "should return a new empty Pointcut if the left-hand Pointcut is empty, independent of the right-hand Pointcut." do
28
+ (@pc1.and(@pc2)).should == @pc1
29
+ end
30
+
31
+ it "should return a new empty Pointcut if the right-hand Pointcut is empty, independent of the left-hand Pointcut." do
32
+ (@pc2.and(@pc1)).should == @pc1
33
+ end
34
+ end
35
+
36
+ describe Pointcut, "#and (when both pointcuts are not empty)" do
12
37
  before(:each) do
13
38
  @example_types = {}
14
39
  [ClassWithPublicInstanceMethod, ClassWithProtectedInstanceMethod, ClassWithPrivateInstanceMethod,
@@ -16,145 +41,116 @@ describe "Intersection of Pointcuts", :shared => true do
16
41
  @empty_set = Set.new
17
42
  end
18
43
 
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
44
+ it "should return a new Pointcut whose join points are the intersection of the left- and right-hand side Pointcuts, each with multiple types." do
45
+ pc1 = Pointcut.new :types => [ClassWithAttribs, ClassWithPublicInstanceMethod, ClassWithPrivateInstanceMethod], :attributes => [/^attr/], :attribute_options => [:readers]
46
+ pc2 = Pointcut.new :types => [ClassWithAttribs, ClassWithPublicInstanceMethod, ClassWithProtectedInstanceMethod], :attributes => :attrRW_ClassWithAttribs, :attribute_options => [:exclude_ancestor_methods]
38
47
  pc = pc1.and pc2
39
- expected_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs
48
+ expected_jp = JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs
40
49
  pc.join_points_matched.should == Set.new([expected_jp])
41
50
  pc.join_points_not_matched.should == @empty_set
42
51
  end
43
52
 
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
53
+ it "should return a new Pointcut whose join points are the intersection of the left- and right-hand side Pointcuts, each with multiple objects." do
45
54
  cwa = ClassWithAttribs.new
46
55
  pub = ClassWithPublicInstanceMethod.new
47
56
  pri = ClassWithPrivateInstanceMethod.new
48
57
  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
58
+ pc1 = Pointcut.new :objects => [cwa, pub, pri], :attributes => [/^attr/], :attribute_options => [:readers, :exclude_ancestor_methods]
59
+ pc2 = Pointcut.new :objects => [cwa, pub, pro], :attributes => :attrRW_ClassWithAttribs
51
60
  pc = pc1.and pc2
52
- expected_jp = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs
61
+ expected_jp = JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs
53
62
  pc.join_points_matched.should == Set.new([expected_jp])
54
63
  pc.join_points_not_matched.should == @empty_set
55
64
  end
56
65
 
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
66
+ it "should return a new Pointcut whose join points are the intersection of the left- and right-hand side Pointcuts, each with a single type." do
67
+ pc1 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers]
68
+ pc2 = Pointcut.new :types => "ClassWithAttribs", :attributes => :attrRW_ClassWithAttribs
60
69
  pc = pc1.and pc2
61
- expected_jp = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs
70
+ expected_jp = JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs
62
71
  pc.join_points_matched.should == Set.new([expected_jp])
63
72
  pc.join_points_not_matched.should == @empty_set
64
73
  end
65
74
 
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
75
+ it "should return a new Pointcut whose join points are the intersection of the left- and right-hand side Pointcuts, each with a single object." do
67
76
  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
77
+ pc1 = Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:readers]
78
+ pc2 = Pointcut.new :object => cwa, :attributes => :attrRW_ClassWithAttribs
70
79
  pc = pc1.and pc2
71
- expected_jp = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs
80
+ expected_jp = JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs
72
81
  pc.join_points_matched.should == Set.new([expected_jp])
73
82
  pc.join_points_not_matched.should == @empty_set
74
83
  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
84
+ end
85
+
86
+ describe Pointcut, "#and (algebraic properties for type-based pointcuts)" do
87
+ before :all do
88
+ @pc1 = Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
89
+ @pc2 = Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
90
+ @pc3 = Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/]
82
91
  end
83
92
 
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
93
+ it "should be unitary for type-based Pointcuts." do
94
+ pc = @pc1.and @pc2
95
+ pc.should == @pc1
96
+ pc.should == @pc2
91
97
  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
98
+
99
+ it "should be commutative for type-based Pointcuts." do
100
+ pc13 = @pc1.and @pc3
101
+ pc31 = @pc3.and @pc1
102
+ pc13.should == pc31
99
103
  end
100
104
 
101
- it "should be commutative for object-based Aquarium::Aspects::Pointcuts." do
105
+ it "should be associativity for type-based Pointcuts." do
106
+ pc123a = (@pc1.and(@pc2)).and(@pc3)
107
+ pc123b = @pc1.and(@pc2.and(@pc3))
108
+ pc123a.should == pc123b
109
+ end
110
+ end
111
+
112
+ describe Pointcut, "#and (algebraic properties for object-based pointcuts)" do
113
+ before :all do
102
114
  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
115
+ @pc1 = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
116
+ @pc2 = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
117
+ @pc3 = Pointcut.new :objects => cwa, :attributes => [/^attr/]
118
+ end
119
+
120
+ it "should be unitary for object-based Pointcuts." do
121
+ pc = @pc1.and @pc2
122
+ pc.should == @pc1
123
+ pc.should == @pc2
109
124
  end
110
125
 
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
126
+ it "should be commutative for object-based Pointcuts." do
127
+ pc13 = @pc1.and @pc3
128
+ pc31 = @pc3.and @pc1
129
+ pc13.should == pc31
118
130
  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))
131
+
132
+ it "should be associativity for object-based Pointcuts." do
133
+ pc123a = (@pc1.and(@pc2)).and(@pc3)
134
+ pc123b = @pc1.and(@pc2.and(@pc3))
128
135
  pc123a.should == pc123b
129
136
  end
130
137
  end
131
138
 
132
- describe Aquarium::Aspects::Pointcut, "#and" do
133
- it_should_behave_like "Intersection of Pointcuts"
134
- end
135
-
136
- describe Aquarium::Aspects::Pointcut, "#&" do
137
- include Aquarium::Utils::HashUtils
139
+ describe Pointcut, "#&" do
138
140
 
139
- it_should_behave_like "Intersection of Pointcuts"
140
-
141
- it "should be associativity for type-based Aquarium::Aspects::Pointcuts." do
142
- pc1 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
143
- pc2 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:readers]
144
- pc3 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/
141
+ it "should be a synonym for #and." do
142
+ pc1 = Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
143
+ pc2 = Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers]
144
+ pc3 = Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/]
145
145
  pc123a = (pc1 & pc2) & pc3
146
146
  pc123b = pc1 & (pc2 & pc3)
147
147
  pc123a.should == pc123b
148
- end
149
-
150
- it "should be associativity for object-based Aquarium::Aspects::Pointcuts." do
151
148
  cwa = ClassWithAttribs.new
152
- pub = ClassWithPublicInstanceMethod.new
153
- pc1 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
154
- pc2 = Aquarium::Aspects::Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:readers]
155
- pc3 = Aquarium::Aspects::Pointcut.new :objects => pub
156
- pc123a = (pc1 & pc2) & pc3
157
- pc123b = pc1 & (pc2 & pc3)
158
- pc123a.should == pc123b
149
+ pca = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
150
+ pcb = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
151
+ pcc = Pointcut.new :objects => cwa, :attributes => [/^attr/]
152
+ pcabc1 = (pca & pcb) & pcc
153
+ pcabc2 = pca & (pcb & pcc)
154
+ pcabc1.should == pcabc2
159
155
  end
160
156
  end
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
- require File.dirname(__FILE__) + '/../spec_example_classes'
2
+ require File.dirname(__FILE__) + '/../spec_example_types'
3
3
  require 'aquarium/utils'
4
4
  require 'aquarium/extensions'
5
5
  require 'aquarium/aspects/pointcut'
@@ -8,148 +8,136 @@ require 'aquarium/aspects/pointcut_composition'
8
8
  include Aquarium::Utils::HashUtils
9
9
  include Aquarium::Aspects
10
10
 
11
- describe "Union of Pointcuts", :shared => true do
11
+ describe Pointcut, "#or" do
12
12
 
13
- before(:each) do
14
- classes = [
15
- ClassWithProtectedInstanceMethod,
16
- ClassWithPrivateInstanceMethod,
17
- ClassWithPublicClassMethod,
18
- ClassWithPrivateClassMethod,
19
- ClassIncludingModuleWithPrivateClassMethod,
20
- ClassIncludingModuleWithPublicClassMethod,
21
- ClassIncludingModuleWithProtectedInstanceMethod,
22
- ClassIncludingModuleWithPrivateInstanceMethod]
23
- jps_array = classes.map {|c| Aquarium::Aspects::JoinPoint.new :type => c, :method => :all}
24
- @not_matched_jps = Set.new(jps_array)
13
+ before :all do
14
+ @pc1 = Pointcut.new
15
+ @pc2 = Pointcut.new :types => /Class.*Public.*Method/, :method_options => [:exclude_ancestor_methods]
16
+ @pc3 = Pointcut.new :object => ClassWithProtectedInstanceMethod.new, :method_options => [:protected, :exclude_ancestor_methods]
25
17
  end
26
-
27
- it "should return a Pointcut equal to the second, appended, non-empty Pointcut if self is empty (has no join points)." do
28
- pc1 = Pointcut.new
29
- pc2 = Pointcut.new :types => /Class.*Method/
30
- pc1.or(pc2).should eql(pc2)
31
- pc3 = Pointcut.new :object => ClassWithPublicInstanceMethod.new
32
- pc1.or(pc3).should eql(pc3)
18
+
19
+ it "should return a new Pointcut equal to the second, appended, non-empty Pointcut if self is empty (has no join points)." do
20
+ @pc1.or(@pc2).should eql(@pc2)
21
+ @pc1.or(@pc3).should eql(@pc3)
33
22
  end
34
23
 
35
- it "should return a Pointcut equal to self if the second pointcut is empty." do
36
- pc1 = Pointcut.new :types => /Class.*Method/
37
- pc2 = Pointcut.new
38
- pc1.or(pc2).should eql(pc1)
39
- pc3 = Pointcut.new :object => ClassWithPublicInstanceMethod.new
40
- pc3.or(pc2).should eql(pc3)
24
+ it "should return a new Pointcut equal to self if the second pointcut is empty." do
25
+ @pc2.or(@pc1).should eql(@pc2)
26
+ @pc3.or(@pc1).should eql(@pc3)
41
27
  end
28
+ end
42
29
 
30
+ describe Pointcut, "#or (with two non-empty pointcuts)" do
31
+
43
32
  it "should return a new Pointcut whose join points are the union of the left- and right-hand side Pointcuts for type-based Pointcuts." do
44
- pc1 = Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
45
- # "[^F]" excludes the ClassWithFunkyMethodNames ...
46
- pc2 = Pointcut.new :types => [/ClassWith[^F]+Method/, /ClassDerived/, /ClassIncludingMod/], :method_options => :exclude_ancestor_methods
47
- pc = pc1.or pc2
48
- jp1 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs=
49
- jp2 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrW_ClassWithAttribs=
50
- jp3 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod, :method => :public_instance_test_method
51
- jp4 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod2, :method => :public_instance_test_method2
52
- jp5 = Aquarium::Aspects::JoinPoint.new :type => ClassDerivedFromClassIncludingModuleWithPublicInstanceMethod, :method => :public_instance_class_derived_from_class_including_module_test_method
53
- jp6 = Aquarium::Aspects::JoinPoint.new :type => ClassIncludingModuleWithPublicInstanceMethod, :method => :public_instance_class_including_module_test_method
54
- pc.join_points_matched.should == Set.new([jp1, jp2, jp3, jp4, jp5, jp6])
55
- pc.join_points_not_matched.should == @not_matched_jps
33
+ pc4 = Pointcut.new :type => ClassWithPublicInstanceMethod, :method_options => :exclude_ancestor_methods
34
+ pc5 = Pointcut.new :type => ClassWithAttribs, :methods => /^attr.*=$/, :method_options => :exclude_ancestor_methods
35
+ jp_np1 = JoinPoint.new :type => ClassIncludingModuleWithPublicInstanceMethod, :method => :public_instance_class_including_module_test_method
36
+ jp_np2 = JoinPoint.new :type => ModuleWithPublicInstanceMethod, :method => :public_instance_module_test_method
37
+ pc4.join_points_not_matched << jp_np1
38
+ pc5.join_points_not_matched << jp_np2
39
+ pc = pc4.or pc5
40
+ jp1 = JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs=
41
+ jp2 = JoinPoint.new :type => ClassWithAttribs, :method => :attrW_ClassWithAttribs=
42
+ jp3 = JoinPoint.new :type => ClassWithPublicInstanceMethod, :method => :public_instance_test_method
43
+ pc.join_points_matched.should == Set.new([jp1, jp2, jp3])
44
+ pc.join_points_not_matched.should == Set.new([jp_np1, jp_np2])
56
45
  end
57
46
 
58
47
  it "should return a new Pointcut whose join points are the union of the left- and right-hand side Pointcuts for object-based Pointcuts." do
59
48
  cwa = ClassWithAttribs.new
60
49
  pub = ClassWithPublicInstanceMethod.new
61
- pc1 = Pointcut.new :objects => [cwa], :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
62
- pc2 = Pointcut.new :object => pub, :method_options => :exclude_ancestor_methods
63
- pc = pc1.or pc2
64
- jp1 = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs=
65
- jp2 = Aquarium::Aspects::JoinPoint.new :object => cwa, :method => :attrW_ClassWithAttribs=
66
- jp3 = Aquarium::Aspects::JoinPoint.new :object => pub, :method => :public_instance_test_method
50
+ pc4 = Pointcut.new :objects => [cwa], :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
51
+ pc5 = Pointcut.new :object => pub, :method_options => :exclude_ancestor_methods
52
+ pc = pc4.or pc5
53
+ jp1 = JoinPoint.new :object => cwa, :method => :attrRW_ClassWithAttribs=
54
+ jp2 = JoinPoint.new :object => cwa, :method => :attrW_ClassWithAttribs=
55
+ jp3 = JoinPoint.new :object => pub, :method => :public_instance_test_method
67
56
  pc.join_points_matched.sort.should == [jp1, jp2, jp3].sort
68
57
  pc.join_points_not_matched.sort.should == []
69
58
  end
70
-
59
+ end
60
+
61
+ describe Pointcut, "#or (algebraic properties for type-based pointcuts)" do
62
+ before :all do
63
+ @pc1 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
64
+ @pc2 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
65
+ @pc3 = Pointcut.new :types => /Class.*Public.*Method/, :method_options => [:public, :exclude_ancestor_methods]
66
+ end
67
+
71
68
  it "should be unitary for type-based Pointcuts." do
72
- pc1 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
73
- pc2 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
74
- pc = pc1.or pc2
75
- pc.should eql(pc1)
76
- pc.should eql(pc2)
69
+ pc = @pc1.or @pc2
70
+ pc.should eql(@pc1)
71
+ pc.should eql(@pc2)
77
72
  end
78
73
 
79
- it "should be unitary for object-based Pointcuts." do
80
- cwa = ClassWithAttribs.new
81
- pc1 = Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
82
- pc2 = Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
83
- pc = pc1.or pc2
84
- pc.should eql(pc1)
85
- pc.should eql(pc2)
74
+ it "should be commutative for type-based Pointcuts." do
75
+ pc13 = @pc1.or @pc3
76
+ pc31 = @pc3.or @pc1
77
+ pc13.should eql(pc31)
86
78
  end
87
79
 
88
- it "should be commutative for type-based Pointcuts." do
89
- pc1 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
90
- pc2 = Pointcut.new :types => /Class.*Method/
91
- pc12 = pc1.or pc2
92
- pc21 = pc2.or pc1
93
- pc12.should eql(pc21)
80
+ it "should be associativity for type-based Pointcuts." do
81
+ pc123a = (@pc1.or(@pc2)).or(@pc3)
82
+ pc123b = @pc1.or(@pc2.or(@pc3))
83
+ pc123a.should eql(pc123b)
94
84
  end
85
+ end
95
86
 
96
- it "should be commutative for object-based Pointcuts." do
87
+ describe Pointcut, "#or (algebraic properties for object-based pointcuts)" do
88
+ before :all do
97
89
  cwa = ClassWithAttribs.new
98
90
  pub = ClassWithPublicInstanceMethod.new
99
- pc1 = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
100
- pc2 = Pointcut.new :objects => pub, :attributes => [/^attr/], :attribute_options => [:writers]
101
- pc12 = pc1.or pc2
102
- pc21 = pc2.or pc1
103
- pc12.should eql(pc21)
91
+ @pc1 = Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
92
+ @pc2 = Pointcut.new :object => cwa, :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
93
+ @pc3 = Pointcut.new :objects => pub, :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
94
+ end
95
+
96
+ it "should be unitary for object-based Pointcuts." do
97
+ pc12 = @pc1.or @pc2
98
+ pc12.should eql(@pc1)
99
+ pc12.should eql(@pc2)
104
100
  end
105
101
 
106
- it "should be associativity for type-based Pointcuts." do
107
- pc1 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
108
- pc2 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers]
109
- pc3 = Pointcut.new :types => /Class.*Method/
110
- pc123a = (pc1.or(pc2)).or(pc3)
111
- pc123b = pc1.or(pc2.or(pc3))
112
- pc123a.should eql(pc123b)
102
+ it "should be commutative for object-based Pointcuts." do
103
+ pc13 = @pc1.or @pc3
104
+ pc31 = @pc3.or @pc1
105
+ pc13.should eql(pc31)
113
106
  end
114
107
 
115
108
  it "should be associativity for object-based Pointcuts." do
116
- cwa = ClassWithAttribs.new
117
- pub = ClassWithPublicInstanceMethod.new
118
- pc1 = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
119
- pc2 = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:readers]
120
- pc3 = Pointcut.new :objects => pub
121
- pc123a = (pc1.or(pc2)).or(pc3)
122
- pc123b = pc1.or(pc2.or(pc3))
109
+ pc123a = (@pc1.or(@pc2)).or(@pc3)
110
+ pc123b = @pc1.or(@pc2.or(@pc3))
123
111
  pc123a.should eql(pc123b)
124
112
  end
125
-
126
113
  end
127
114
 
128
- describe Pointcut, "#or" do
129
- it_should_behave_like "Union of Pointcuts"
130
- end
131
115
 
132
116
  describe Pointcut, "#|" do
133
-
134
- it_should_behave_like "Union of Pointcuts"
135
-
136
- it "should be associativity for type-based Pointcuts." do
137
- pc1 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers]
138
- pc2 = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers]
139
- pc3 = Pointcut.new :types => /Class.*Method/
140
- pc123a = (pc1 | pc2) | pc3
141
- pc123b = pc1 | (pc2 | pc3)
142
- pc123a.should eql(pc123b)
143
- end
144
-
145
- it "should be associativity for object-based Pointcuts." do
117
+ it "should be a synonym for #or." do
118
+ pc1 = Pointcut.new
119
+ pc2 = Pointcut.new :types => /Class.*Public.*Method/, :method_options => [:public, :exclude_ancestor_methods]
120
+ pc3 = Pointcut.new :object => ClassWithPublicInstanceMethod.new, :method_options => [:exclude_ancestor_methods]
121
+ pc12 = pc1 | pc2
122
+ pc32 = pc3 | pc2
123
+ pc23 = pc2 | pc3
124
+ pc12.should_not equal(pc1)
125
+ pc12.should_not equal(pc2)
126
+ pc12.should eql(pc2)
127
+ pc32.should eql(pc23)
128
+ pca = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
129
+ pcb = Pointcut.new :types => "ClassWithAttribs", :attributes => [/^attr/], :attribute_options => [:readers, :exclude_ancestor_methods]
130
+ pcc = Pointcut.new :types => /Class.*Method/, :method_options => [:exclude_ancestor_methods]
131
+ pcabc1 = (pca | pcb) | pcc
132
+ pcabc2 = pca | (pcb | pcc)
133
+ pcabc1.should eql(pcabc2)
146
134
  cwa = ClassWithAttribs.new
147
135
  pub = ClassWithPublicInstanceMethod.new
148
- pc1 = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers]
149
- pc2 = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:readers]
150
- pc3 = Pointcut.new :objects => pub
151
- pc123a = (pc1 | pc2) | pc3
152
- pc123b = pc1 | (pc2 | pc3)
153
- pc123a.should eql(pc123b)
136
+ pcd = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:writers, :exclude_ancestor_methods]
137
+ pce = Pointcut.new :objects => cwa, :attributes => [/^attr/], :attribute_options => [:readers, :exclude_ancestor_methods]
138
+ pcf = Pointcut.new :objects => pub, :method_options => [:exclude_ancestor_methods]
139
+ pcdef1 = (pcd | pce) | pcf
140
+ pcdef2 = pcd | (pce | pcf)
141
+ pcdef1.should eql(pcdef2)
154
142
  end
155
143
  end