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.
@@ -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
- pc2 = Aquarium::Aspects::Pointcut.new :types => /Class.*Method/, :method_options => :suppress_ancestor_methods
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, :method => :public_instance_test_method
40
- pc.join_points_matched.should == Set.new([jp1, jp2, jp3])
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, " (empty)" do
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 => /Foo/
615
- pc2 = Aquarium::Aspects::Pointcut.new :types => /Bar/
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 "Aquarium::Aspects::Pointcut#candidate_types" do
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 "Aquarium::Aspects::Pointcut#candidate_objects" do
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 "Aquarium::Aspects::Pointcut#specification" do
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, :default_object => @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, :default_object => @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]), :default_object => @empty_set,
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, :default_object => @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, :default_object => @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, :default_object => @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, :default_object => @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; end
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 return an empty match for a simple name (without :: namespace delimiters) that doesn't match an existing class." do
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 and/or regular expressions" do
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$/, /Clas{2}/, /^.*TestCase.*$/, /^Unknown1/, /Unknown2/]
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 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)
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$/, "Out.*::In.*2"]
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$/, "Out.*::In.*2"]
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