aquarium 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +4 -0
- data/EXAMPLES.rd +4 -0
- data/MIT-LICENSE +20 -0
- data/README +250 -0
- data/RELEASE-PLAN +1 -0
- data/Rakefile +236 -0
- data/UPGRADE +3 -0
- data/examples/aspect_design_example.rb +36 -0
- data/examples/design_by_contract_example.rb +88 -0
- data/examples/method_missing_example.rb +44 -0
- data/examples/method_tracing_example.rb +64 -0
- data/lib/aquarium.rb +7 -0
- data/lib/aquarium/aspects.rb +6 -0
- data/lib/aquarium/aspects/advice.rb +189 -0
- data/lib/aquarium/aspects/aspect.rb +577 -0
- data/lib/aquarium/aspects/default_object_handler.rb +27 -0
- data/lib/aquarium/aspects/dsl.rb +1 -0
- data/lib/aquarium/aspects/dsl/aspect_dsl.rb +61 -0
- data/lib/aquarium/aspects/join_point.rb +158 -0
- data/lib/aquarium/aspects/pointcut.rb +254 -0
- data/lib/aquarium/aspects/pointcut_composition.rb +36 -0
- data/lib/aquarium/extensions.rb +5 -0
- data/lib/aquarium/extensions/hash.rb +85 -0
- data/lib/aquarium/extensions/regexp.rb +20 -0
- data/lib/aquarium/extensions/set.rb +49 -0
- data/lib/aquarium/extensions/string.rb +13 -0
- data/lib/aquarium/extensions/symbol.rb +22 -0
- data/lib/aquarium/extras.rb +4 -0
- data/lib/aquarium/extras/design_by_contract.rb +64 -0
- data/lib/aquarium/finders.rb +4 -0
- data/lib/aquarium/finders/finder_result.rb +121 -0
- data/lib/aquarium/finders/method_finder.rb +228 -0
- data/lib/aquarium/finders/object_finder.rb +74 -0
- data/lib/aquarium/finders/type_finder.rb +127 -0
- data/lib/aquarium/utils.rb +9 -0
- data/lib/aquarium/utils/array_utils.rb +29 -0
- data/lib/aquarium/utils/hash_utils.rb +28 -0
- data/lib/aquarium/utils/html_escaper.rb +17 -0
- data/lib/aquarium/utils/invalid_options.rb +9 -0
- data/lib/aquarium/utils/method_utils.rb +18 -0
- data/lib/aquarium/utils/nil_object.rb +13 -0
- data/lib/aquarium/utils/set_utils.rb +32 -0
- data/lib/aquarium/version.rb +30 -0
- data/rake_tasks/examples.rake +7 -0
- data/rake_tasks/examples_specdoc.rake +8 -0
- data/rake_tasks/examples_with_rcov.rake +8 -0
- data/rake_tasks/verify_rcov.rake +7 -0
- data/spec/aquarium/aspects/advice_chain_node_spec.rb +34 -0
- data/spec/aquarium/aspects/advice_spec.rb +103 -0
- data/spec/aquarium/aspects/aspect_invocation_spec.rb +111 -0
- data/spec/aquarium/aspects/aspect_spec.rb +978 -0
- data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +129 -0
- data/spec/aquarium/aspects/concurrent_aspects_spec.rb +423 -0
- data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +103 -0
- data/spec/aquarium/aspects/concurrently_accessed.rb +21 -0
- data/spec/aquarium/aspects/dsl/aspect_dsl_spec.rb +514 -0
- data/spec/aquarium/aspects/join_point_spec.rb +302 -0
- data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +131 -0
- data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +111 -0
- data/spec/aquarium/aspects/pointcut_spec.rb +800 -0
- data/spec/aquarium/extensions/hash_spec.rb +187 -0
- data/spec/aquarium/extensions/regex_spec.rb +40 -0
- data/spec/aquarium/extensions/set_spec.rb +105 -0
- data/spec/aquarium/extensions/string_spec.rb +25 -0
- data/spec/aquarium/extensions/symbol_spec.rb +37 -0
- data/spec/aquarium/extras/design_by_contract_spec.rb +68 -0
- data/spec/aquarium/finders/finder_result_spec.rb +359 -0
- data/spec/aquarium/finders/method_finder_spec.rb +878 -0
- data/spec/aquarium/finders/method_sorting_spec.rb +16 -0
- data/spec/aquarium/finders/object_finder_spec.rb +230 -0
- data/spec/aquarium/finders/type_finder_spec.rb +210 -0
- data/spec/aquarium/spec_example_classes.rb +117 -0
- data/spec/aquarium/spec_helper.rb +3 -0
- data/spec/aquarium/utils/array_utils_spec.rb +47 -0
- data/spec/aquarium/utils/hash_utils_spec.rb +48 -0
- data/spec/aquarium/utils/html_escaper_spec.rb +18 -0
- data/spec/aquarium/utils/method_utils_spec.rb +50 -0
- data/spec/aquarium/utils/nil_object_spec.rb +19 -0
- data/spec/aquarium/utils/set_utils_spec.rb +60 -0
- metadata +132 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../spec_example_classes'
|
3
|
+
require 'aquarium/extensions/hash'
|
4
|
+
require 'aquarium/utils/array_utils'
|
5
|
+
require 'aquarium/utils/hash_utils'
|
6
|
+
require 'set'
|
7
|
+
|
8
|
+
describe Hash, "#intersection" do
|
9
|
+
include Aquarium::Utils::ArrayUtils
|
10
|
+
include Aquarium::Utils::HashUtils
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
@hash = {:a => 'a', :b => [:b1, :b2], :c => 'c'}
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return the same hash if intersected with itself." do
|
17
|
+
@hash.intersection(@hash).should == @hash
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the same hash if intersected with an equivalent hash." do
|
21
|
+
@hash.intersection({:a => 'a', :b => [:b1, :b2], :c => 'c'}).should == @hash
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return an empty hash if one of the input hashes is empty." do
|
25
|
+
{}.intersection(@hash).should == {}
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return the common subset hash for two, non-equivalent hashes." do
|
29
|
+
hash2 = {:b =>:b1, :c => 'c', :d => 'd'}
|
30
|
+
@hash.intersection(hash2){|values1, values2| Set.new(make_array(values1)).intersection(Set.new(make_array(values2)))}.should == {:b =>Set.new([:b1]), :c => 'c'}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "intersection of hashes", :shared => true do
|
35
|
+
include Aquarium::Utils::ArrayUtils
|
36
|
+
include Aquarium::Utils::HashUtils
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
@hash = {:a => 'a', :b => [:b1, :b2], :c => 'c'}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return the same hash if intersected with itself." do
|
43
|
+
@hash.intersection(@hash).should == @hash
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return the same hash if intersected with an equivalent hash." do
|
47
|
+
@hash.intersection({:a => 'a', :b => [:b1, :b2], :c => 'c'}).should == @hash
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return an empty hash if one of the input hashes is empty." do
|
51
|
+
{}.intersection(@hash).should == {}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should return the common subset hash for two, non-equivalent hashes." do
|
55
|
+
hash2 = {:b =>:b1, :c => 'c', :d => 'd'}
|
56
|
+
@hash.intersection(hash2){|value1, value2| Set.new(make_array(value1)).intersection(Set.new(make_array(value2)))}.should == {:b =>Set.new([:b1]), :c => 'c'}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe Hash, "#intersection" do
|
61
|
+
it_should_behave_like "intersection of hashes"
|
62
|
+
end
|
63
|
+
|
64
|
+
describe Hash, "#and" do
|
65
|
+
it_should_behave_like "intersection of hashes"
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "union of hashes", :shared => true do
|
69
|
+
include Aquarium::Utils::ArrayUtils
|
70
|
+
include Aquarium::Utils::HashUtils
|
71
|
+
|
72
|
+
before(:each) do
|
73
|
+
@hash = {:a => 'a', :b => [:b1, :b2], :c => 'c'}
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return the same hash if unioned with itself." do
|
77
|
+
@hash.union(@hash).should == @hash
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return the same hash if unioned with an equivalent hash." do
|
81
|
+
@hash.union({:a => 'a', :b => [:b1, :b2], :c => 'c'}).should == @hash
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should return a hash that is equivalent to the non-empty hash if the other hash is empty." do
|
85
|
+
{}.union(@hash).should == @hash
|
86
|
+
@hash.union({}).should == @hash
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should return the same hash if unioned with nil." do
|
90
|
+
@hash.union(nil).should == @hash
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return a hash equivalent to the output of Hash#merge for two, non-equivalent hashes, with no block given." do
|
94
|
+
hash2 = {:b =>:b3, :c => 'c2', :d => 'd'}
|
95
|
+
@hash.union(hash2).should == {:a => 'a', :b => :b3, :c => 'c2', :d => 'd'}
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should return the combined hashes for two, non-equivalent hashes, with a block given to merge values into an array." do
|
99
|
+
hash2 = {:b =>:b3, :c => 'c2', :d => 'd'}
|
100
|
+
@hash.union(hash2){|value1, value2| Set.new(make_array(value1)).union(Set.new(make_array(value2)))}.should == {:a => 'a', :b => Set.new([:b1, :b2, :b3]), :c => Set.new(['c', 'c2']), :d => 'd'}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe Hash, "#union" do
|
105
|
+
it_should_behave_like "union of hashes"
|
106
|
+
end
|
107
|
+
|
108
|
+
describe Hash, "#or" do
|
109
|
+
it_should_behave_like "union of hashes"
|
110
|
+
end
|
111
|
+
|
112
|
+
describe Hash, "#eql_when_keys_compared?" do
|
113
|
+
include Aquarium::Utils::ArrayUtils
|
114
|
+
include Aquarium::Utils::HashUtils
|
115
|
+
|
116
|
+
it "should return true when comparing a hash to itself." do
|
117
|
+
h1={"1" => :a1, "2" => :a2, "3" => :a3}
|
118
|
+
h1.eql_when_keys_compared?(h1).should == true
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should return true for hashes with string keys that satisfy String#==." do
|
122
|
+
h1={"1" => :a1, "2" => :a2, "3" => :a3}
|
123
|
+
h2={"1" => :a1, "2" => :a2, "3" => :a3}
|
124
|
+
h1.eql_when_keys_compared?(h2).should == true
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should return false for hashes with matching keys, but different values." do
|
128
|
+
h1={"1" => :a1, "2" => :a2, "3" => /a/}
|
129
|
+
h2={"1" => :a1, "2" => :a2, "3" => /b/}
|
130
|
+
h1.eql_when_keys_compared?(h2).should == false
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should return false for hashes where one hash is a subset of the other." do
|
134
|
+
h1={"1" => :a1, "2" => :a2}
|
135
|
+
h2={"1" => :a1, "2" => :a2, "3" => :a3}
|
136
|
+
h1.eql_when_keys_compared?(h2).should == false
|
137
|
+
h2.eql_when_keys_compared?(h1).should == false
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should return true for hashes with Object keys that define a #<=> method, while Hash#eql? would return false." do
|
141
|
+
class Key
|
142
|
+
def initialize key
|
143
|
+
@key = key
|
144
|
+
end
|
145
|
+
attr_reader :key
|
146
|
+
def eql? other
|
147
|
+
key.eql? other.key
|
148
|
+
end
|
149
|
+
def <=> other
|
150
|
+
key <=> other.key
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
h1 = {}; h2 = {}
|
155
|
+
(0...4).each do |index|
|
156
|
+
h1[Key.new(index)] = {index.to_s => [index, index+1]}
|
157
|
+
h2[Key.new(index)] = {index.to_s => [index, index+1]}
|
158
|
+
end
|
159
|
+
h1.eql_when_keys_compared?(h2).should == true
|
160
|
+
h1.eql?(h2).should == false
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe Hash, "#equivalent_key" do
|
165
|
+
it "should return the key in the hash for which input_value#==(key) is true." do
|
166
|
+
class Key
|
167
|
+
def initialize key
|
168
|
+
@key = key
|
169
|
+
end
|
170
|
+
attr_reader :key
|
171
|
+
def eql? other
|
172
|
+
key.eql? other.key
|
173
|
+
end
|
174
|
+
alias :== :eql?
|
175
|
+
end
|
176
|
+
|
177
|
+
h1 = {}; h2 = {}
|
178
|
+
(0...4).each do |index|
|
179
|
+
h1[Key.new(index)] = {index.to_s => [index, index+1]}
|
180
|
+
h2[Key.new(index)] = {index.to_s => [index, index+1]}
|
181
|
+
end
|
182
|
+
h1[Key.new(0)].should be_nil
|
183
|
+
h1.equivalent_key(Key.new(0)).should_not be_nil
|
184
|
+
h1.equivalent_key(Key.new(5)).should be_nil
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require 'aquarium/extensions/regexp'
|
3
|
+
|
4
|
+
describe Regexp, "#empty?" do
|
5
|
+
|
6
|
+
it "should return true for an empty regular expression" do
|
7
|
+
//.empty?.should be_true
|
8
|
+
Regexp.new("").empty?.should be_true
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return true for an empty regular expression with whitespace" do
|
12
|
+
/ /.empty?.should be_true
|
13
|
+
Regexp.new(" ").empty?.should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return false for a non-empty regular expression" do
|
17
|
+
/x/.empty?.should be_false
|
18
|
+
Regexp.new("x").empty?.should be_false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe Regexp, "#strip" do
|
23
|
+
it "should return equivalent Regexp if there is no leading or trailing whitespace." do
|
24
|
+
re = /^.{3}.*[a-z]$/
|
25
|
+
re.strip.should == re
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return new Regexp with removed leading and/or trailing whitespace, when present." do
|
29
|
+
re_string = "^.{3}.*[a-z]$"
|
30
|
+
re = Regexp.new " #{re_string} "
|
31
|
+
re.strip.source.should == re_string
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Regexp, "#<=>" do
|
36
|
+
it "should sort by the output of #to_s" do
|
37
|
+
ary = [/^x/, /x/, /x$/]
|
38
|
+
ary.sort.should == [/^x/, /x$/, /x/]
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../spec_example_classes'
|
3
|
+
require 'aquarium/extensions/set'
|
4
|
+
|
5
|
+
class Foo
|
6
|
+
def initialize name
|
7
|
+
@name = name
|
8
|
+
end
|
9
|
+
attr_reader :name
|
10
|
+
def eql? other
|
11
|
+
name.eql? other.name
|
12
|
+
end
|
13
|
+
alias :== :eql?
|
14
|
+
end
|
15
|
+
class Bar
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "set comparison", :shared => true do
|
19
|
+
it "should return true for the same set" do
|
20
|
+
s = Set.new [Foo.new("f1"), Foo.new("f2")]
|
21
|
+
s.should eql(s)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return true for equivalent sets" do
|
25
|
+
s1 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
26
|
+
s2 = Set.new [Foo.new("f2"), Foo.new("f1")]
|
27
|
+
s1.should eql(s2)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return false for sets where one is a subset of, but not equivalent to, the other set" do
|
31
|
+
s1 = Set.new [Foo.new("f1")]
|
32
|
+
s2 = Set.new [Foo.new("f2"), Foo.new("f1")]
|
33
|
+
s1.should_not eql(s2)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return false for sets where some element pairs are of different types" do
|
37
|
+
s1 = Set.new [Foo.new("f1"), Bar.new]
|
38
|
+
s2 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
39
|
+
s1.should_not eql(s2)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe Set, "#==" do
|
44
|
+
it_should_behave_like "set comparison"
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Set, "#eql?" do
|
48
|
+
it_should_behave_like "set comparison"
|
49
|
+
end
|
50
|
+
|
51
|
+
describe Set, "#union_using_eql_comparison" do
|
52
|
+
it "should return an equivalent set if unioned with itself" do
|
53
|
+
s = Set.new [Foo.new("f1"), Foo.new("f2")]
|
54
|
+
s.union_using_eql_comparison(s).should eql(s)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return an equivalent set if unioned with another equivalent set" do
|
58
|
+
s1 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
59
|
+
s2 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
60
|
+
s1.union_using_eql_comparison(s2).should eql(s1)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return an equivalent set if unioned with subset" do
|
64
|
+
s1 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
65
|
+
s2 = Set.new [Foo.new("f1")]
|
66
|
+
s1.union_using_eql_comparison(s2).should eql(s1)
|
67
|
+
s2.union_using_eql_comparison(s1).should eql(s1)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should return a combined set if unioned with a disjoint set" do
|
71
|
+
s1 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
72
|
+
s2 = Set.new [Foo.new("f3")]
|
73
|
+
s3 = Set.new [Foo.new("f1"), Foo.new("f2"), Foo.new("f3")]
|
74
|
+
s1.union_using_eql_comparison(s2).should eql(s3)
|
75
|
+
s2.union_using_eql_comparison(s1).should eql(s3)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe Set, "#intersection_using_eql_comparison" do
|
80
|
+
it "should return an equivalent set if intersectioned with itself" do
|
81
|
+
s = Set.new [Foo.new("f1"), Foo.new("f2")]
|
82
|
+
s.intersection_using_eql_comparison(s).should eql(s)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return an equivalent set if intersectioned with another equivalent set" do
|
86
|
+
s1 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
87
|
+
s2 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
88
|
+
s1.intersection_using_eql_comparison(s2).should eql(s1)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return a subset if intersectioned with an equivalent subset" do
|
92
|
+
s1 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
93
|
+
s2 = Set.new [Foo.new("f1")]
|
94
|
+
s1.intersection_using_eql_comparison(s2).should eql(s2)
|
95
|
+
s2.intersection_using_eql_comparison(s1).should eql(s2)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should return an empty set if intersectioned with a disjoint set" do
|
99
|
+
s1 = Set.new [Foo.new("f1"), Foo.new("f2")]
|
100
|
+
s2 = Set.new [Foo.new("f3")]
|
101
|
+
s1.intersection_using_eql_comparison(s2).should eql(Set.new)
|
102
|
+
s2.intersection_using_eql_comparison(s1).should eql(Set.new)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require 'aquarium/extensions/string'
|
3
|
+
|
4
|
+
describe String, "#to_camel_case" do
|
5
|
+
it "should return a camel-case string unchanged" do
|
6
|
+
"CamelCaseString".to_camel_case.should == "CamelCaseString"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return a camel-case string from an input string with substrings separated by underscores" do
|
10
|
+
"camel_case_string".to_camel_case.should == "CamelCaseString"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return a camel-case string with the first letters of each substring in uppercase and the rest of the letters in each substring unchanged" do
|
14
|
+
"cAmEl_cASE_stRinG".to_camel_case.should == "CAmElCASEStRinG"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should remove leading and trailing underscores" do
|
18
|
+
"camel_case_string_".to_camel_case.should == "CamelCaseString"
|
19
|
+
"_camel_case_string".to_camel_case.should == "CamelCaseString"
|
20
|
+
"camel_case_string__".to_camel_case.should == "CamelCaseString"
|
21
|
+
"__camel_case_string".to_camel_case.should == "CamelCaseString"
|
22
|
+
"_camel_case_string_".to_camel_case.should == "CamelCaseString"
|
23
|
+
"__camel_case_string__".to_camel_case.should == "CamelCaseString"
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require 'aquarium/extensions/symbol'
|
3
|
+
|
4
|
+
describe "Symbol#empty?" do
|
5
|
+
|
6
|
+
it "should return true for an empty symbol with whitespace" do
|
7
|
+
:" \t ".empty?.should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return false for a non-empty symbol" do
|
11
|
+
:x.empty?.should be_false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Symbol#strip" do
|
16
|
+
it "should return equivalent Symbol if there is no leading or trailing whitespace." do
|
17
|
+
:a.strip.should == :a
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return new Symbol with removed leading and/or trailing whitespace, when present." do
|
21
|
+
:" \ta\t ".strip.should == :a
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "Symbol#<=>" do
|
26
|
+
it "should return < 0 if the string representation of the left-hand side symbol is less than the string representation of the right-hand side symbol." do
|
27
|
+
(:a <=> :b).should == -1
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return > 0 if the string representation of the left-hand side symbol is greater than the string representation of the right-hand side symbol." do
|
31
|
+
(:b <=> :a).should == 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should return 0 if the string representation of the left-hand side symbol is equal to the string representation of the right-hand side symbol." do
|
35
|
+
(:a <=> :a).should == 0
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require 'aquarium/extras/design_by_contract'
|
3
|
+
|
4
|
+
describe Aquarium::Extras::DesignByContract, "precondition" do
|
5
|
+
class PreCond
|
6
|
+
def action *args
|
7
|
+
end
|
8
|
+
|
9
|
+
precondition :method => :action, :message => "Must pass more than one argument." do |jp, *args|
|
10
|
+
args.size > 0
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should add advice that raises if the precondition is not satisfied" do
|
15
|
+
lambda {PreCond.new.action}.should raise_error(Aquarium::Extras::DesignByContract::ContractError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should add advice that does not raise if the precondition is satisfied" do
|
19
|
+
PreCond.new.action(:a1)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Aquarium::Extras::DesignByContract, "postcondition" do
|
24
|
+
class PostCond
|
25
|
+
def action *args
|
26
|
+
end
|
27
|
+
|
28
|
+
postcondition :method => :action, :message => "Must pass more than one argument and first argument must be non-empty." do |jp, *args|
|
29
|
+
args.size > 0 && ! args[0].empty?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should add advice that raises if the postcondition is not satisfied" do
|
34
|
+
lambda {PostCond.new.action}.should raise_error(Aquarium::Extras::DesignByContract::ContractError)
|
35
|
+
lambda {PostCond.new.action("")}.should raise_error(Aquarium::Extras::DesignByContract::ContractError)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should add advice that does not raise if the postcondition is satisfied" do
|
39
|
+
PostCond.new.action(:a1)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
describe Aquarium::Extras::DesignByContract, "invariant" do
|
45
|
+
class InvarCond
|
46
|
+
def initialize
|
47
|
+
@invar = 0
|
48
|
+
end
|
49
|
+
attr_reader :invar
|
50
|
+
def good_action
|
51
|
+
end
|
52
|
+
def bad_action
|
53
|
+
@invar = 1
|
54
|
+
end
|
55
|
+
|
56
|
+
invariant :methods => /action$/, :message => "Must not change the @invar value." do |jp, *args|
|
57
|
+
jp.context.advised_object.invar == 0
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should add advice that raises if the invariant is not satisfied" do
|
62
|
+
lambda {InvarCond.new.bad_action}.should raise_error(Aquarium::Extras::DesignByContract::ContractError)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should add advice that does not raise if the invariant is satisfied" do
|
66
|
+
InvarCond.new.good_action
|
67
|
+
end
|
68
|
+
end
|