aquarium 0.1.5 → 0.1.6
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 +64 -0
- data/README +19 -8
- data/UPGRADE +7 -1
- data/examples/method_tracing_example.rb +18 -8
- data/examples/method_tracing_example_spec.rb +34 -20
- data/lib/aquarium/aspects/advice.rb +11 -3
- data/lib/aquarium/aspects/aspect.rb +11 -9
- data/lib/aquarium/aspects/join_point.rb +55 -20
- data/lib/aquarium/aspects/pointcut.rb +49 -20
- data/lib/aquarium/extras/design_by_contract.rb +2 -1
- data/lib/aquarium/finders/type_finder.rb +55 -16
- data/lib/aquarium/utils/method_utils.rb +5 -1
- data/lib/aquarium/version.rb +1 -1
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +12 -0
- data/spec/aquarium/aspects/aspect_spec.rb +85 -8
- data/spec/aquarium/aspects/aspect_with_subtypes_spec.rb +49 -0
- data/spec/aquarium/aspects/join_point_spec.rb +94 -23
- data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +5 -3
- data/spec/aquarium/aspects/pointcut_spec.rb +104 -22
- data/spec/aquarium/extras/design_by_contract_spec.rb +6 -0
- data/spec/aquarium/finders/type_finder_spec.rb +60 -14
- metadata +4 -3
@@ -9,6 +9,17 @@ class Dummy
|
|
9
9
|
def count; 0; end
|
10
10
|
end
|
11
11
|
|
12
|
+
class ProtectionExample
|
13
|
+
def public_instance_m; end
|
14
|
+
protected
|
15
|
+
def protected_instance_m; end
|
16
|
+
private
|
17
|
+
def private_instance_m; end
|
18
|
+
def self.public_class_m; end
|
19
|
+
def self.private_class_m; end
|
20
|
+
private_class_method :private_class_m
|
21
|
+
end
|
22
|
+
|
12
23
|
describe Aquarium::Aspects::JoinPoint, "#initialize with invalid parameters" do
|
13
24
|
|
14
25
|
it "should require either a :type or an :object parameter when creating." do
|
@@ -29,48 +40,44 @@ describe Aquarium::Aspects::JoinPoint, "#initialize with parameters that specify
|
|
29
40
|
it "should assume the :method_name refers to an instance method, by default." do
|
30
41
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split
|
31
42
|
jp.instance_method?.should be_true
|
43
|
+
jp.class_method?.should be_false
|
32
44
|
end
|
33
45
|
|
34
46
|
it "should treat the :method_name as refering to an instance method if :instance_method is specified as true." do
|
35
47
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :instance_method => true
|
36
48
|
jp.instance_method?.should be_true
|
49
|
+
jp.class_method?.should be_false
|
37
50
|
end
|
38
51
|
|
39
52
|
it "should treat the :method_name as refering to a class method if :instance_method is specified as false." do
|
40
53
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :instance_method => false
|
41
54
|
jp.instance_method?.should be_false
|
55
|
+
jp.class_method?.should be_true
|
42
56
|
end
|
43
57
|
|
44
58
|
it "should treat the :method_name as refering to an instance method if :class_method is specified as false." do
|
45
59
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :class_method => false
|
46
60
|
jp.instance_method?.should be_true
|
61
|
+
jp.class_method?.should be_false
|
47
62
|
end
|
48
63
|
|
49
64
|
it "should treat the :method_name as refering to a class method if :class_method is specified as true." do
|
50
65
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :class_method => true
|
51
66
|
jp.instance_method?.should be_false
|
67
|
+
jp.class_method?.should be_true
|
52
68
|
end
|
53
69
|
|
54
70
|
it "should treat give precedence to :instance_method if appears with :class_method." do
|
55
71
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :instance_method => false, :class_method => true
|
56
72
|
jp.instance_method?.should be_false
|
73
|
+
jp.class_method?.should be_true
|
57
74
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method => :split, :instance_method => true, :class_method => false
|
58
75
|
jp.instance_method?.should be_true
|
76
|
+
jp.class_method?.should be_false
|
59
77
|
end
|
60
78
|
end
|
61
79
|
|
62
80
|
describe Aquarium::Aspects::JoinPoint, "#visibility" do
|
63
|
-
class ProtectionExample
|
64
|
-
def public_instance_m; end
|
65
|
-
protected
|
66
|
-
def protected_instance_m; end
|
67
|
-
private
|
68
|
-
def private_instance_m; end
|
69
|
-
def self.public_class_m; end
|
70
|
-
def self.private_class_m; end
|
71
|
-
private_class_method :private_class_m
|
72
|
-
end
|
73
|
-
|
74
81
|
it "should return :public for public instance methods." do
|
75
82
|
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method => :public_instance_m
|
76
83
|
jp.visibility.should == :public
|
@@ -159,6 +166,21 @@ describe Aquarium::Aspects::JoinPoint, "#visibility" do
|
|
159
166
|
jp.visibility.should == nil
|
160
167
|
end
|
161
168
|
end
|
169
|
+
|
170
|
+
describe Aquarium::Aspects::JoinPoint, "#target_type" do
|
171
|
+
it "should return the type at the JoinPoint" do
|
172
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method => :foo
|
173
|
+
jp.target_type.should be_eql(ProtectionExample)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe Aquarium::Aspects::JoinPoint, "#target_object" do
|
178
|
+
it "should return the object at the JoinPoint" do
|
179
|
+
example = ProtectionExample.new
|
180
|
+
jp = Aquarium::Aspects::JoinPoint.new :object => example, :method => :foo
|
181
|
+
jp.target_object.should be_eql(example)
|
182
|
+
end
|
183
|
+
end
|
162
184
|
|
163
185
|
describe Aquarium::Aspects::JoinPoint, "#dup" do
|
164
186
|
it "should duplicate the fields in the join point." do
|
@@ -274,6 +296,67 @@ describe Aquarium::Aspects::JoinPoint, "#make_current_context_join_point when th
|
|
274
296
|
end
|
275
297
|
end
|
276
298
|
|
299
|
+
describe Aquarium::Aspects::JoinPoint, "#type_or_object" do
|
300
|
+
it "should return the type if the object is nil" do
|
301
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
302
|
+
jp.type_or_object.should eql(String)
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should return the object if the type is nil" do
|
306
|
+
jp = Aquarium::Aspects::JoinPoint.new :object => String.new, :method_name => :split
|
307
|
+
jp.type_or_object.should eql("")
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe Aquarium::Aspects::JoinPoint, "#exists?" do
|
312
|
+
it "should return false if the join point represents a non-existent join point for an instance method in the runtime environment" do
|
313
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method_name => :foo
|
314
|
+
jp.exists?.should be_false
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should return false if the join point represents a non-existent join point for a class method in the runtime environment" do
|
318
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method_name => :foo, :class_method => true
|
319
|
+
jp.exists?.should be_false
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should return true if the join point represents a real join point for a public instance method in the runtime environment" do
|
323
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method_name => :public_instance_m
|
324
|
+
jp.exists?.should be_true
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should return true if the join point represents a real join point for a protected instance method in the runtime environment" do
|
328
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method_name => :protected_instance_m
|
329
|
+
jp.exists?.should be_true
|
330
|
+
end
|
331
|
+
|
332
|
+
it "should return true if the join point represents a real join point for a private instance method in the runtime environment" do
|
333
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method_name => :private_instance_m
|
334
|
+
jp.exists?.should be_true
|
335
|
+
end
|
336
|
+
|
337
|
+
it "should return true if the join point represents a real join point for a public class method in the runtime environment" do
|
338
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method_name => :public_class_m, :class_method => true
|
339
|
+
jp.exists?.should be_true
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should return true if the join point represents a real join point for a private class method in the runtime environment" do
|
343
|
+
jp = Aquarium::Aspects::JoinPoint.new :type => ProtectionExample, :method_name => :private_class_m, :class_method => true
|
344
|
+
jp.exists?.should be_true
|
345
|
+
end
|
346
|
+
|
347
|
+
class ProtectionExample2
|
348
|
+
def public_instance_m; end
|
349
|
+
protected
|
350
|
+
def protected_instance_m; end
|
351
|
+
private
|
352
|
+
def private_instance_m; end
|
353
|
+
def self.public_class_m; end
|
354
|
+
def self.private_class_m; end
|
355
|
+
private_class_method :private_class_m
|
356
|
+
end
|
357
|
+
|
358
|
+
end
|
359
|
+
|
277
360
|
describe Aquarium::Aspects::JoinPoint, "#make_current_context_join_point when the Aquarium::Aspects::JoinPoint::Context object is not nil" do
|
278
361
|
it "should return a new join_point that contains the non-context information of the advised_object plus an updated Aquarium::Aspects::JoinPoint::Context with the specified context information." do
|
279
362
|
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
@@ -296,18 +379,6 @@ describe Aquarium::Aspects::JoinPoint, "#make_current_context_join_point when th
|
|
296
379
|
end
|
297
380
|
end
|
298
381
|
|
299
|
-
describe Aquarium::Aspects::JoinPoint, "#type_or_object" do
|
300
|
-
it "should return the type if the object is nil" do
|
301
|
-
jp = Aquarium::Aspects::JoinPoint.new :type => String, :method_name => :split
|
302
|
-
jp.type_or_object.should eql(String)
|
303
|
-
end
|
304
|
-
|
305
|
-
it "should return the object if the type is nil" do
|
306
|
-
jp = Aquarium::Aspects::JoinPoint.new :object => String.new, :method_name => :split
|
307
|
-
jp.type_or_object.should eql("")
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
382
|
describe Aquarium::Aspects::JoinPoint::Context, "#initialize" do
|
312
383
|
it "should require :advice_kind, :advised_object and :parameters arguments." do
|
313
384
|
lambda { Aquarium::Aspects::JoinPoint::Context.new :advised_object => "object", :parameters => [","]}.should raise_error(Aquarium::Utils::InvalidOptions)
|
@@ -32,12 +32,14 @@ describe "Aquarium::Aspects::Pointcut#and" do
|
|
32
32
|
|
33
33
|
it "should return a new Aquarium::Aspects::Pointcut whose join points are the union of the left- and right-hand side Aquarium::Aspects::Pointcuts for type-based Aquarium::Aspects::Pointcuts." do
|
34
34
|
pc1 = Aquarium::Aspects::Pointcut.new :types => ClassWithAttribs, :attributes => [/^attr/], :attribute_options => [:writers, :suppress_ancestor_methods]
|
35
|
-
|
35
|
+
# "[^F]" excludes the ClassWithFunkyMethodNames...
|
36
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => /Class[^F]+Method/, :method_options => :suppress_ancestor_methods
|
36
37
|
pc = pc1.or pc2
|
37
38
|
jp1 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrRW_ClassWithAttribs=
|
38
39
|
jp2 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttribs, :method => :attrW_ClassWithAttribs=
|
39
|
-
jp3 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod,
|
40
|
-
|
40
|
+
jp3 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod, :method => :public_instance_test_method
|
41
|
+
jp4 = Aquarium::Aspects::JoinPoint.new :type => ClassWithPublicInstanceMethod2, :method => :public_instance_test_method2
|
42
|
+
pc.join_points_matched.should == Set.new([jp1, jp2, jp3, jp4])
|
41
43
|
pc.join_points_not_matched.should == @not_matched_jps
|
42
44
|
end
|
43
45
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
2
|
require File.dirname(__FILE__) + '/../spec_example_classes'
|
3
|
+
require 'aquarium/utils/invalid_options'
|
3
4
|
require 'aquarium/extensions/hash'
|
5
|
+
require 'aquarium/aspects/join_point'
|
4
6
|
require 'aquarium/aspects/pointcut'
|
5
7
|
require 'aquarium/utils'
|
6
8
|
|
@@ -21,7 +23,13 @@ def common_setup
|
|
21
23
|
@expected_not_matched_jps = Set.new [@apro_jp, @apri_jp, @acpub_jp, @acpri_jp]
|
22
24
|
end
|
23
25
|
|
24
|
-
describe Aquarium::Aspects::Pointcut, " (
|
26
|
+
describe Aquarium::Aspects::Pointcut, "#new (invalid arguments)" do
|
27
|
+
it "should raise if an unknown argument is specified" do
|
28
|
+
lambda { Aquarium::Aspects::Pointcut.new :foo => :bar }.should raise_error(Aquarium::Utils::InvalidOptions)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe Aquarium::Aspects::Pointcut, "#new (empty)" do
|
25
33
|
it "should match no join points by default." do
|
26
34
|
pc = Aquarium::Aspects::Pointcut.new
|
27
35
|
pc.should be_empty
|
@@ -51,6 +59,16 @@ describe Aquarium::Aspects::Pointcut, " (empty)" do
|
|
51
59
|
pc = Aquarium::Aspects::Pointcut.new :objects => nil
|
52
60
|
pc.should be_empty
|
53
61
|
end
|
62
|
+
|
63
|
+
it "should match no join points if join_points = nil specified." do
|
64
|
+
pc = Aquarium::Aspects::Pointcut.new :join_points => nil
|
65
|
+
pc.should be_empty
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should match no join points if join_points = [] specified." do
|
69
|
+
pc = Aquarium::Aspects::Pointcut.new :join_points => []
|
70
|
+
pc.should be_empty
|
71
|
+
end
|
54
72
|
end
|
55
73
|
|
56
74
|
describe Aquarium::Aspects::Pointcut, "#empty?" do
|
@@ -81,11 +99,17 @@ describe Aquarium::Aspects::Pointcut, " (types specified using regular expressio
|
|
81
99
|
common_setup
|
82
100
|
end
|
83
101
|
|
84
|
-
it "should match multiple classes using regular expressions." do
|
85
|
-
pc = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :method_options => :suppress_ancestor_methods
|
102
|
+
it "should match multiple classes using regular expressions that cover the full class names." do
|
103
|
+
pc = Aquarium::Aspects::Pointcut.new :types => /Class.*Method\Z/, :method_options => :suppress_ancestor_methods
|
86
104
|
pc.join_points_matched.should == @expected_matched_jps
|
87
105
|
pc.join_points_not_matched.should == @expected_not_matched_jps
|
88
106
|
end
|
107
|
+
|
108
|
+
it "should match classes using regular expressions that only cover partial class names." do
|
109
|
+
pc = Aquarium::Aspects::Pointcut.new :types => /lass.*Pro.*Inst.*Met/, :method_options => [:public, :protected, :suppress_ancestor_methods]
|
110
|
+
pc.join_points_matched.should == Set.new([@pro_jp])
|
111
|
+
pc.join_points_not_matched.size.should == 0
|
112
|
+
end
|
89
113
|
end
|
90
114
|
|
91
115
|
describe Aquarium::Aspects::Pointcut, " (types specified using names)" do
|
@@ -438,6 +462,35 @@ describe Aquarium::Aspects::Pointcut, " (types or objects specified with attribu
|
|
438
462
|
end
|
439
463
|
end
|
440
464
|
|
465
|
+
describe Aquarium::Aspects::Pointcut, " (join points specified)" do
|
466
|
+
setup do
|
467
|
+
common_setup
|
468
|
+
@anClassWithPublicInstanceMethod = ClassWithPublicInstanceMethod.new
|
469
|
+
@expected_matched = [@pub_jp, @pro_jp, @pri_jp, @cpub_jp, @cpri_jp,
|
470
|
+
Aquarium::Aspects::JoinPoint.new(:object => @anClassWithPublicInstanceMethod, :method => :public_instance_test_method)]
|
471
|
+
@expected_not_matched = [
|
472
|
+
Aquarium::Aspects::JoinPoint.new(:type => ClassWithPublicInstanceMethod, :method => :foo),
|
473
|
+
Aquarium::Aspects::JoinPoint.new(:object => @anClassWithPublicInstanceMethod, :method => :foo)]
|
474
|
+
end
|
475
|
+
|
476
|
+
it "should return matches only for existing join points." do
|
477
|
+
pc = Aquarium::Aspects::Pointcut.new :join_points => (@expected_matched + @expected_not_matched)
|
478
|
+
pc.join_points_matched.should == Set.new(@expected_matched)
|
479
|
+
end
|
480
|
+
|
481
|
+
it "should return non-matches for non-existing join points." do
|
482
|
+
pc = Aquarium::Aspects::Pointcut.new :join_points => (@expected_matched + @expected_not_matched)
|
483
|
+
pc.join_points_not_matched.should == Set.new(@expected_not_matched)
|
484
|
+
end
|
485
|
+
|
486
|
+
it "should ignore :methods, :attributes, :method_options, and :attribute_options for the join points specified." do
|
487
|
+
pc = Aquarium::Aspects::Pointcut.new :join_points => (@expected_matched + @expected_not_matched),
|
488
|
+
:methods => :kind_of?, :attributes => :name, :method_options => [:class], :attribute_options => [:readers]
|
489
|
+
pc.join_points_matched.should == Set.new(@expected_matched)
|
490
|
+
pc.join_points_not_matched.should == Set.new(@expected_not_matched)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
441
494
|
describe Aquarium::Aspects::Pointcut, " (methods that end in non-alphanumeric characters)" do
|
442
495
|
class ClassWithFunkyMethodNames
|
443
496
|
def huh?; true; end
|
@@ -611,8 +664,8 @@ describe Aquarium::Aspects::Pointcut, "#eql?" do
|
|
611
664
|
end
|
612
665
|
|
613
666
|
it "should return false if the not_matched types are different." do
|
614
|
-
pc1 = Aquarium::Aspects::Pointcut.new :types =>
|
615
|
-
pc2 = Aquarium::Aspects::Pointcut.new :types =>
|
667
|
+
pc1 = Aquarium::Aspects::Pointcut.new :types => :UnknownFoo
|
668
|
+
pc2 = Aquarium::Aspects::Pointcut.new :types => :UnknownBar
|
616
669
|
pc1.should_not eql(pc2)
|
617
670
|
end
|
618
671
|
|
@@ -685,7 +738,7 @@ describe "Aquarium::Aspects::Pointcut#eql?" do
|
|
685
738
|
end
|
686
739
|
end
|
687
740
|
|
688
|
-
describe
|
741
|
+
describe Aquarium::Aspects::Pointcut, "#candidate_types" do
|
689
742
|
setup do
|
690
743
|
common_setup
|
691
744
|
end
|
@@ -715,7 +768,7 @@ describe "Aquarium::Aspects::Pointcut#candidate_types" do
|
|
715
768
|
end
|
716
769
|
end
|
717
770
|
|
718
|
-
describe
|
771
|
+
describe Aquarium::Aspects::Pointcut, "#candidate_objects" do
|
719
772
|
setup do
|
720
773
|
common_setup
|
721
774
|
end
|
@@ -730,7 +783,36 @@ describe "Aquarium::Aspects::Pointcut#candidate_objects" do
|
|
730
783
|
end
|
731
784
|
end
|
732
785
|
|
733
|
-
describe
|
786
|
+
describe Aquarium::Aspects::Pointcut, "#candidate_join_points" do
|
787
|
+
setup do
|
788
|
+
common_setup
|
789
|
+
end
|
790
|
+
|
791
|
+
it "should return only candidate non-matching join points for the input join points that do not exist." do
|
792
|
+
anClassWithPublicInstanceMethod = ClassWithPublicInstanceMethod.new
|
793
|
+
example_jps = [
|
794
|
+
Aquarium::Aspects::JoinPoint.new(:type => ClassWithPublicInstanceMethod, :method => :foo),
|
795
|
+
Aquarium::Aspects::JoinPoint.new(:object => anClassWithPublicInstanceMethod, :method => :foo)]
|
796
|
+
pc = Aquarium::Aspects::Pointcut.new :join_points => example_jps
|
797
|
+
pc.candidate_join_points.matched.size.should == 0
|
798
|
+
pc.candidate_join_points.not_matched[example_jps[0]].should_not be_nil
|
799
|
+
pc.candidate_join_points.not_matched[example_jps[1]].should_not be_nil
|
800
|
+
end
|
801
|
+
|
802
|
+
it "should return only candidate matching join points for the input join points that do exist." do
|
803
|
+
anClassWithPublicInstanceMethod = ClassWithPublicInstanceMethod.new
|
804
|
+
example_jps = [
|
805
|
+
Aquarium::Aspects::JoinPoint.new(:type => ClassWithPublicInstanceMethod, :method => :public_instance_test_method),
|
806
|
+
Aquarium::Aspects::JoinPoint.new(:object => anClassWithPublicInstanceMethod, :method => :public_instance_test_method)]
|
807
|
+
pc = Aquarium::Aspects::Pointcut.new :join_points => example_jps
|
808
|
+
pc.candidate_join_points.matched.size.should == 2
|
809
|
+
pc.candidate_join_points.matched[example_jps[0]].should_not be_nil
|
810
|
+
pc.candidate_join_points.matched[example_jps[1]].should_not be_nil
|
811
|
+
pc.candidate_join_points.not_matched.size.should == 0
|
812
|
+
end
|
813
|
+
end
|
814
|
+
|
815
|
+
describe Aquarium::Aspects::Pointcut, "#specification" do
|
734
816
|
setup do
|
735
817
|
common_setup
|
736
818
|
@expected_specification_subset = {
|
@@ -741,15 +823,15 @@ describe "Aquarium::Aspects::Pointcut#specification" do
|
|
741
823
|
|
742
824
|
it "should return ':attribute_options => []', by default, if no arguments are given." do
|
743
825
|
pc = Aquarium::Aspects::Pointcut.new
|
744
|
-
pc.specification.should == { :types => @empty_set, :objects => @empty_set, :
|
745
|
-
:methods => Set.new([:all]), :method_options => Set.new([]),
|
826
|
+
pc.specification.should == { :types => @empty_set, :objects => @empty_set, :join_points => @empty_set,
|
827
|
+
:methods => Set.new([:all]), :method_options => Set.new([]), :default_object => @empty_set,
|
746
828
|
:attributes => @empty_set, :attribute_options => @empty_set }
|
747
829
|
end
|
748
830
|
|
749
831
|
it "should return the input :types and :type arguments combined into an array keyed by :types." do
|
750
832
|
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :type => String
|
751
|
-
pc.specification.should == { :types => Set.new(@example_types + [String]), :objects => @empty_set, :
|
752
|
-
:methods => Set.new([:all]), :method_options => Set.new([]),
|
833
|
+
pc.specification.should == { :types => Set.new(@example_types + [String]), :objects => @empty_set, :join_points => @empty_set,
|
834
|
+
:methods => Set.new([:all]), :method_options => Set.new([]), :default_object => @empty_set,
|
753
835
|
:attributes => @empty_set, :attribute_options => @empty_set }
|
754
836
|
end
|
755
837
|
|
@@ -757,36 +839,36 @@ describe "Aquarium::Aspects::Pointcut#specification" do
|
|
757
839
|
example_objs = @example_types.map {|t| t.new}
|
758
840
|
s1234 = "1234"
|
759
841
|
pc = Aquarium::Aspects::Pointcut.new :objects => example_objs, :object => s1234
|
760
|
-
pc.specification.should == { :types => @empty_set, :objects => Set.new(example_objs + [s1234]), :
|
761
|
-
:methods => Set.new([:all]), :method_options => Set.new([]),
|
842
|
+
pc.specification.should == { :types => @empty_set, :objects => Set.new(example_objs + [s1234]), :join_points => @empty_set,
|
843
|
+
:methods => Set.new([:all]), :method_options => Set.new([]), :default_object => @empty_set,
|
762
844
|
:attributes => @empty_set, :attribute_options => @empty_set }
|
763
845
|
end
|
764
846
|
|
765
847
|
it "should return the input :methods and :method arguments combined into an array keyed by :methods." do
|
766
848
|
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :methods => /^get/, :method => "dup"
|
767
|
-
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :
|
768
|
-
:methods => Set.new([/^get/, "dup"]), :method_options => Set.new([]),
|
849
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :join_points => @empty_set,
|
850
|
+
:methods => Set.new([/^get/, "dup"]), :method_options => Set.new([]), :default_object => @empty_set,
|
769
851
|
:attributes => @empty_set, :attribute_options => @empty_set }
|
770
852
|
end
|
771
853
|
|
772
854
|
it "should return the input :method_options verbatim." do
|
773
855
|
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :methods => /^get/, :method => "dup", :method_options => [:instance, :public]
|
774
|
-
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :
|
775
|
-
:methods => Set.new([/^get/, "dup"]), :method_options => Set.new([:instance, :public]),
|
856
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :join_points => @empty_set,
|
857
|
+
:methods => Set.new([/^get/, "dup"]), :method_options => Set.new([:instance, :public]), :default_object => @empty_set,
|
776
858
|
:attributes => @empty_set, :attribute_options => @empty_set }
|
777
859
|
end
|
778
860
|
|
779
861
|
it "should return the input :methods and :method arguments combined into an array keyed by :methods." do
|
780
862
|
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :attributes => /^state/, :attribute => "name"
|
781
|
-
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :
|
782
|
-
:methods => @empty_set, :method_options => Set.new([]),
|
863
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :join_points => @empty_set,
|
864
|
+
:methods => @empty_set, :method_options => Set.new([]), :default_object => @empty_set,
|
783
865
|
:attributes => Set.new([/^state/, "name"]), :attribute_options => @empty_set }
|
784
866
|
end
|
785
867
|
|
786
868
|
it "should return the input :attributes, :attribute and :attribute_options arguments, verbatim." do
|
787
869
|
pc = Aquarium::Aspects::Pointcut.new :types => @example_types, :attributes => /^state/, :attribute => "name", :attribute_options => :reader
|
788
|
-
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :
|
789
|
-
:methods => @empty_set, :method_options => Set.new([]),
|
870
|
+
pc.specification.should == { :types => Set.new(@example_types), :objects => @empty_set, :join_points => @empty_set,
|
871
|
+
:methods => @empty_set, :method_options => Set.new([]), :default_object => @empty_set,
|
790
872
|
:attributes => Set.new([/^state/, "name"]), :attribute_options => Set.new([:reader]) }
|
791
873
|
end
|
792
874
|
end
|
@@ -51,9 +51,11 @@ describe Aquarium::Extras::DesignByContract, "invariant" do
|
|
51
51
|
end
|
52
52
|
attr_reader :invar
|
53
53
|
def good_action
|
54
|
+
"good"
|
54
55
|
end
|
55
56
|
def bad_action
|
56
57
|
@invar = 1
|
58
|
+
"bad"
|
57
59
|
end
|
58
60
|
|
59
61
|
invariant :methods => /action$/, :message => "Must not change the @invar value." do |jp, *args|
|
@@ -68,4 +70,8 @@ describe Aquarium::Extras::DesignByContract, "invariant" do
|
|
68
70
|
it "should add advice that does not raise if the invariant is satisfied" do
|
69
71
|
InvarCond.new.good_action
|
70
72
|
end
|
73
|
+
|
74
|
+
it "should return the value returned by the checked method when the invariant is satisfied" do
|
75
|
+
InvarCond.new.good_action.should == "good"
|
76
|
+
end
|
71
77
|
end
|
@@ -11,13 +11,13 @@ describe Aquarium::Finders::TypeFinder, "#find" do
|
|
11
11
|
lambda { Aquarium::Finders::TypeFinder.new.find "foo" }.should raise_error(Aquarium::Utils::InvalidOptions)
|
12
12
|
end
|
13
13
|
|
14
|
-
it "should return no matched and no unmatched expressions by default (i.e., the input is empty)." do
|
14
|
+
it "should return no matched types and no unmatched type expressions by default (i.e., the input is empty)." do
|
15
15
|
actual = Aquarium::Finders::TypeFinder.new.find
|
16
16
|
actual.matched.should == {}
|
17
17
|
actual.not_matched.should == {}
|
18
18
|
end
|
19
19
|
|
20
|
-
it "should return no matched and no unmatched expressions if the input hash is empty." do
|
20
|
+
it "should return no matched types and no unmatched type expressions if the input hash is empty." do
|
21
21
|
actual = Aquarium::Finders::TypeFinder.new.find {}
|
22
22
|
actual.matched.should == {}
|
23
23
|
actual.not_matched.should == {}
|
@@ -61,17 +61,25 @@ end
|
|
61
61
|
|
62
62
|
class Outside
|
63
63
|
class Inside1; end
|
64
|
-
class Inside2
|
64
|
+
class Inside2
|
65
|
+
class ReallyInside; end
|
66
|
+
end
|
65
67
|
end
|
66
68
|
|
67
69
|
describe Aquarium::Finders::TypeFinder, "#find with :type or :name used to specify a single type" do
|
68
|
-
it "should find a type matching a simple name (without :: namespace delimiters) using its name." do
|
70
|
+
it "should find a type matching a simple name (without :: namespace delimiters) using its name and the :type option." do
|
69
71
|
actual = Aquarium::Finders::TypeFinder.new.find :type => :Object
|
70
72
|
actual.matched_keys.should == [Object]
|
71
73
|
actual.not_matched.should == {}
|
72
74
|
end
|
73
75
|
|
74
|
-
it "should
|
76
|
+
it "should find a type matching a simple name (without :: namespace delimiters) using its name and the :name option." do
|
77
|
+
actual = Aquarium::Finders::TypeFinder.new.find :name => :Object
|
78
|
+
actual.matched_keys.should == [Object]
|
79
|
+
actual.not_matched.should == {}
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should return an empty match for a simple name (without :: namespace delimiters) that doesn't match an existing type." do
|
75
83
|
actual = Aquarium::Finders::TypeFinder.new.find :name => :Unknown
|
76
84
|
actual.matched.should == {}
|
77
85
|
actual.not_matched_keys.should == [:Unknown]
|
@@ -84,7 +92,7 @@ describe Aquarium::Finders::TypeFinder, "#find with :type or :name used to speci
|
|
84
92
|
end
|
85
93
|
end
|
86
94
|
|
87
|
-
describe Aquarium::Finders::TypeFinder, "#find with :types, :names, :type, and :name used to specify one or more names
|
95
|
+
describe Aquarium::Finders::TypeFinder, "#find with :types, :names, :type, and :name used to specify one or more names" do
|
88
96
|
it "should find types matching simple names (without :: namespace delimiters) using their names." do
|
89
97
|
expected_found_types = [Class, Kernel, Module, Object]
|
90
98
|
expected_unfound_exps = %w[TestCase Unknown1 Unknown2]
|
@@ -92,30 +100,61 @@ describe Aquarium::Finders::TypeFinder, "#find with :types, :names, :type, and :
|
|
92
100
|
actual.matched_keys.sort.should == expected_found_types.sort
|
93
101
|
actual.not_matched_keys.should == expected_unfound_exps
|
94
102
|
end
|
103
|
+
|
104
|
+
it "should find types with :: namespace delimiters using their names." do
|
105
|
+
expected_found_types = [Outside::Inside1, Outside::Inside2]
|
106
|
+
expected_unfound_exps = %w[Foo::Bar::Baz]
|
107
|
+
actual = Aquarium::Finders::TypeFinder.new.find :names => (expected_found_types.map {|t| t.to_s} + expected_unfound_exps)
|
108
|
+
actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
|
109
|
+
actual.not_matched_keys.sort.should == expected_unfound_exps.sort
|
110
|
+
end
|
111
|
+
end
|
95
112
|
|
113
|
+
describe Aquarium::Finders::TypeFinder, "#find with :types, :names, :type, and :name used to specify one or more regular expressions" do
|
96
114
|
it "should find types matching simple names (without :: namespace delimiters) using lists of regular expressions." do
|
97
115
|
expected_found_types = [Class, Kernel, Module, Object]
|
98
116
|
expected_unfound_exps = [/Unknown2/, /^.*TestCase.*$/, /^Unknown1/]
|
99
|
-
actual = Aquarium::Finders::TypeFinder.new.find :types => [/K.+l/, /^Mod.+e$/, /^Object$/,
|
117
|
+
actual = Aquarium::Finders::TypeFinder.new.find :types => [/K.+l/, /^Mod.+e$/, /^Object$/, /^Clas{2}$/, /^.*TestCase.*$/, /^Unknown1/, /Unknown2/]
|
100
118
|
actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
|
101
119
|
actual.not_matched_keys.sort.should == expected_unfound_exps.sort
|
102
120
|
end
|
103
121
|
|
104
|
-
it "should find types
|
105
|
-
expected_found_types = [
|
106
|
-
expected_unfound_exps =
|
107
|
-
actual = Aquarium::Finders::TypeFinder.new.find :
|
122
|
+
it "should find types matching simple names (without :: namespace delimiters) using regular expressions that match parts of the names." do
|
123
|
+
expected_found_types = [FalseClass, Module, TrueClass]
|
124
|
+
expected_unfound_exps = []
|
125
|
+
actual = Aquarium::Finders::TypeFinder.new.find :types => [/eClass$/, /^Modu/]
|
108
126
|
actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
|
109
127
|
actual.not_matched_keys.sort.should == expected_unfound_exps.sort
|
110
128
|
end
|
111
129
|
|
112
130
|
it "should find types with :: namespace delimiters using lists of regular expressions." do
|
113
|
-
expected_found_types = [Outside::Inside1, Outside::Inside2]
|
131
|
+
expected_found_types = [Outside::Inside1, Outside::Inside2, Outside::Inside2::ReallyInside]
|
114
132
|
expected_unfound_exps = [/^.*Fo+::.*Bar+::Baz.$/]
|
115
|
-
actual = Aquarium::Finders::TypeFinder.new.find :types => [/^.*Fo+::.*Bar+::Baz.$/, /Outside::.*1$/,
|
133
|
+
actual = Aquarium::Finders::TypeFinder.new.find :types => [/^.*Fo+::.*Bar+::Baz.$/, /Outside::.*1$/, /Out.*::In.*2/, /Out.*::In.*2::R.*/]
|
116
134
|
actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
|
117
135
|
actual.not_matched_keys.should == expected_unfound_exps
|
118
136
|
end
|
137
|
+
|
138
|
+
it "should allow a partial trailing name before the first :: namespace delimiter in a regular expression." do
|
139
|
+
expected_found_types = [Outside::Inside1, Outside::Inside2]
|
140
|
+
actual = Aquarium::Finders::TypeFinder.new.find :types => [/side::In.*/]
|
141
|
+
actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
|
142
|
+
actual.not_matched_keys.size.should == 0
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should allow a partial leading name after the last :: namespace delimiter in a regular expression." do
|
146
|
+
expected_found_types = [Outside::Inside1, Outside::Inside2, Outside::Inside2::ReallyInside]
|
147
|
+
actual = Aquarium::Finders::TypeFinder.new.find :types => [/side::In/, /side::Inside2::Real/]
|
148
|
+
actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
|
149
|
+
actual.not_matched_keys.size.should == 0
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should require a full name-matching regular expression between :: namespace delimiters." do
|
153
|
+
expected_found_types = [Outside::Inside2::ReallyInside]
|
154
|
+
actual = Aquarium::Finders::TypeFinder.new.find :types => [/side::In::Real/]
|
155
|
+
actual.matched_keys.size.should == 0
|
156
|
+
actual.not_matched_keys.should == [/side::In::Real/]
|
157
|
+
end
|
119
158
|
end
|
120
159
|
|
121
160
|
describe Aquarium::Finders::TypeFinder, "#find" do
|
@@ -131,7 +170,7 @@ describe Aquarium::Finders::TypeFinder, "#find_all_by" do
|
|
131
170
|
it "should find types with :: namespace delimiters using lists of regular expressions." do
|
132
171
|
expected_found_types = [Outside::Inside1, Outside::Inside2]
|
133
172
|
expected_unfound_exps = [/^.*Fo+::.*Bar+::Baz.$/]
|
134
|
-
actual = Aquarium::Finders::TypeFinder.new.find_all_by [/^.*Fo+::.*Bar+::Baz.$/, /Outside::.*1$/,
|
173
|
+
actual = Aquarium::Finders::TypeFinder.new.find_all_by [/^.*Fo+::.*Bar+::Baz.$/, /Outside::.*1$/, /Out.*::In.*2/]
|
135
174
|
actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
|
136
175
|
actual.not_matched_keys.should == expected_unfound_exps
|
137
176
|
end
|
@@ -206,5 +245,12 @@ describe Aquarium::Finders::TypeFinder, "#find_by_type" do
|
|
206
245
|
actual.not_matched_keys.should == []
|
207
246
|
end
|
208
247
|
end
|
248
|
+
|
249
|
+
# TODO refactor this protected method into a new class.
|
250
|
+
describe Aquarium::Finders::TypeFinder, "#get_type_from_parent should" do
|
251
|
+
it "should raise if a type doesn't exist that matches the constant" do
|
252
|
+
lambda {Aquarium::Finders::TypeFinder.new.send(:get_type_from_parent, Aquarium::Finders, "Nonexistent", /Non/)}.should raise_error(NameError)
|
253
|
+
end
|
254
|
+
end
|
209
255
|
|
210
256
|
|