ruby-contract 0.1.1
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/COPYING +56 -0
- data/Manifest +85 -0
- data/README +32 -0
- data/TODO +83 -0
- data/doc/classes/Contract.html +599 -0
- data/doc/classes/Contract/Check.html +229 -0
- data/doc/classes/Contract/Check/All.html +172 -0
- data/doc/classes/Contract/Check/Any.html +172 -0
- data/doc/classes/Contract/Check/Block.html +172 -0
- data/doc/classes/Contract/Check/None.html +173 -0
- data/doc/classes/Contract/Check/Quack.html +172 -0
- data/doc/classes/Contract/ContractError.html +151 -0
- data/doc/classes/Contract/ContractException.html +162 -0
- data/doc/classes/Contract/ContractMismatch.html +134 -0
- data/doc/classes/Kernel.html +256 -0
- data/doc/classes/Method.html +135 -0
- data/doc/classes/MethodSignatureMixin.html +208 -0
- data/doc/classes/Module.html +526 -0
- data/doc/created.rid +1 -0
- data/doc/dot/f_0.dot +14 -0
- data/doc/dot/f_0.png +0 -0
- data/doc/dot/f_1.dot +14 -0
- data/doc/dot/f_1.png +0 -0
- data/doc/dot/f_2.dot +14 -0
- data/doc/dot/f_2.png +0 -0
- data/doc/dot/f_3.dot +112 -0
- data/doc/dot/f_3.png +0 -0
- data/doc/dot/f_4.dot +62 -0
- data/doc/dot/f_4.png +0 -0
- data/doc/dot/f_5.dot +62 -0
- data/doc/dot/f_5.png +0 -0
- data/doc/dot/f_6.dot +224 -0
- data/doc/dot/f_6.png +0 -0
- data/doc/dot/f_6_0.dot +24 -0
- data/doc/dot/f_6_0.png +0 -0
- data/doc/dot/f_6_1.dot +24 -0
- data/doc/dot/f_6_1.png +0 -0
- data/doc/dot/f_7.dot +62 -0
- data/doc/dot/f_7.png +0 -0
- data/doc/files/COPYING.html +168 -0
- data/doc/files/README.html +146 -0
- data/doc/files/TODO.html +240 -0
- data/doc/files/lib/contract/assertions_rb.html +118 -0
- data/doc/files/lib/contract/exception_rb.html +125 -0
- data/doc/files/lib/contract/integration_rb.html +130 -0
- data/doc/files/lib/contract/overrides_rb.html +118 -0
- data/doc/files/lib/contract_rb.html +127 -0
- data/doc/fr_class_index.html +40 -0
- data/doc/fr_file_index.html +34 -0
- data/doc/fr_method_index.html +45 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/contract.rb +146 -0
- data/lib/contract/assertions.rb +42 -0
- data/lib/contract/exception.rb +95 -0
- data/lib/contract/integration.rb +664 -0
- data/lib/contract/overrides.rb +41 -0
- data/setup.rb +1360 -0
- data/test/coverage/_-lib-contract-assertions_rb.html +526 -0
- data/test/coverage/_-lib-contract-exception_rb.html +632 -0
- data/test/coverage/_-lib-contract-integration_rb.html +1450 -0
- data/test/coverage/_-lib-contract-overrides_rb.html +524 -0
- data/test/coverage/_-lib-contract_rb.html +724 -0
- data/test/coverage/__-lib-contract-assertions_rb.html +484 -0
- data/test/coverage/__-lib-contract-exception_rb.html +537 -0
- data/test/coverage/__-lib-contract-integration_rb.html +946 -0
- data/test/coverage/__-lib-contract-overrides_rb.html +483 -0
- data/test/coverage/__-lib-contract_rb.html +583 -0
- data/test/coverage/index.html +93 -0
- data/test/tc_all.rb +8 -0
- data/test/tc_contract.rb +109 -0
- data/test/tc_exception.rb +43 -0
- data/test/tc_integration.rb +357 -0
- metadata +136 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
<?xml version="1.0" encoding="ISO-8859-15"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
5
|
+
<head><title>coverage</title>
|
6
|
+
<style type="text/css">body {
|
7
|
+
background-color: rgb(180, 180, 180));
|
8
|
+
}
|
9
|
+
span.marked {
|
10
|
+
background-color: rgb(185, 200, 200);
|
11
|
+
display: block;
|
12
|
+
}
|
13
|
+
span.inferred {
|
14
|
+
background-color: rgb(180, 195, 195);
|
15
|
+
display: block;
|
16
|
+
}
|
17
|
+
span.overview {
|
18
|
+
border-bottom: 8px solid black;
|
19
|
+
}
|
20
|
+
</style></head>
|
21
|
+
<body><h3><tt>Sat Feb 05 23:35:41 Westeurop�ische Normalzeit 2005</tt></h3><h1>Average (code only): 45.9%</h1><h2>Average (with comments): 47.8%</h2><table><tr>
|
22
|
+
<td><a href="_-lib-contract_rb.html">./lib/contract.rb</a></td>
|
23
|
+
<td><tt>282</tt></td>
|
24
|
+
<td> </td><td> </td><td> </td>
|
25
|
+
<td><tt>122</tt></td>
|
26
|
+
<td> </td><td> </td><td> </td>
|
27
|
+
<td><tt>48.9%</tt></td>
|
28
|
+
<td> </td><td> </td><td> </td>
|
29
|
+
<td><tt>47.5%</tt></td>
|
30
|
+
</tr>
|
31
|
+
<tr>
|
32
|
+
<td><a href="_-lib-contract-assertions_rb.html">./lib/contract/assertions.rb</a></td>
|
33
|
+
<td><tt>84</tt></td>
|
34
|
+
<td> </td><td> </td><td> </td>
|
35
|
+
<td><tt>20</tt></td>
|
36
|
+
<td> </td><td> </td><td> </td>
|
37
|
+
<td><tt>50.0%</tt></td>
|
38
|
+
<td> </td><td> </td><td> </td>
|
39
|
+
<td><tt>50.0%</tt></td>
|
40
|
+
</tr>
|
41
|
+
<tr>
|
42
|
+
<td><a href="_-lib-contract-exception_rb.html">./lib/contract/exception.rb</a></td>
|
43
|
+
<td><tt>190</tt></td>
|
44
|
+
<td> </td><td> </td><td> </td>
|
45
|
+
<td><tt>110</tt></td>
|
46
|
+
<td> </td><td> </td><td> </td>
|
47
|
+
<td><tt>50.0%</tt></td>
|
48
|
+
<td> </td><td> </td><td> </td>
|
49
|
+
<td><tt>50.0%</tt></td>
|
50
|
+
</tr>
|
51
|
+
<tr>
|
52
|
+
<td><a href="_-lib-contract-integration_rb.html">./lib/contract/integration.rb</a></td>
|
53
|
+
<td><tt>1008</tt></td>
|
54
|
+
<td> </td><td> </td><td> </td>
|
55
|
+
<td><tt>494</tt></td>
|
56
|
+
<td> </td><td> </td><td> </td>
|
57
|
+
<td><tt>46.6%</tt></td>
|
58
|
+
<td> </td><td> </td><td> </td>
|
59
|
+
<td><tt>43.9%</tt></td>
|
60
|
+
</tr>
|
61
|
+
<tr>
|
62
|
+
<td><a href="_-lib-contract-overrides_rb.html">./lib/contract/overrides.rb</a></td>
|
63
|
+
<td><tt>82</tt></td>
|
64
|
+
<td> </td><td> </td><td> </td>
|
65
|
+
<td><tt>50</tt></td>
|
66
|
+
<td> </td><td> </td><td> </td>
|
67
|
+
<td><tt>50.0%</tt></td>
|
68
|
+
<td> </td><td> </td><td> </td>
|
69
|
+
<td><tt>50.0%</tt></td>
|
70
|
+
</tr>
|
71
|
+
<tr><td>TOTAL</td>
|
72
|
+
<td><tt>1646</tt></td>
|
73
|
+
<td> </td><td> </td><td> </td>
|
74
|
+
<td><tt>796</tt></td>
|
75
|
+
<td> </td><td> </td><td> </td>
|
76
|
+
<td><tt>47.8%</tt></td>
|
77
|
+
<td> </td><td> </td><td> </td>
|
78
|
+
<td><tt>45.9%</tt></td>
|
79
|
+
</tr></table>
|
80
|
+
<hr />
|
81
|
+
<p>
|
82
|
+
<a href="http://validator.w3.org/check/referer">
|
83
|
+
<img src="http://www.w3.org/Icons/valid-xhtml11"
|
84
|
+
alt="Valid XHTML 1.1!" height="31" width="88" />
|
85
|
+
</a>
|
86
|
+
<a href="http://jigsaw.w3.org/css-validator/">
|
87
|
+
<img style="border:0;width:88px;height:31px"
|
88
|
+
src="http://jigsaw.w3.org/css-validator/images/vcss"
|
89
|
+
alt="Valid CSS!" />
|
90
|
+
</a>
|
91
|
+
</p>
|
92
|
+
</body>
|
93
|
+
</html>
|
data/test/tc_all.rb
ADDED
data/test/tc_contract.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$LOAD_PATH << "../lib"
|
3
|
+
require 'contract'
|
4
|
+
|
5
|
+
class TC_Integration_Signature < Test::Unit::TestCase
|
6
|
+
class EnumerableContract < Contract
|
7
|
+
provides :each
|
8
|
+
end
|
9
|
+
|
10
|
+
module List
|
11
|
+
module NonEmpty; end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ListContract < Contract
|
15
|
+
implies List
|
16
|
+
|
17
|
+
def self.check_count() 3 end
|
18
|
+
|
19
|
+
provides :each
|
20
|
+
provides :[]
|
21
|
+
provides :size do
|
22
|
+
assert(@object.size >= 0)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class NonEmptyListContract < ListContract
|
27
|
+
implies List::NonEmpty
|
28
|
+
|
29
|
+
provides :size do
|
30
|
+
assert(@object.size > 0)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class EmptyList
|
35
|
+
def each() end
|
36
|
+
def [](idx) end
|
37
|
+
def size() 0 end
|
38
|
+
|
39
|
+
fulfills ListContract
|
40
|
+
end
|
41
|
+
|
42
|
+
class NonEmptyList < EmptyList
|
43
|
+
def size() 1 end
|
44
|
+
|
45
|
+
fulfills NonEmptyListContract
|
46
|
+
end
|
47
|
+
|
48
|
+
class BrokenContract < Contract
|
49
|
+
provides :size do
|
50
|
+
[][]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_contract_test()
|
55
|
+
result = EnumerableContract.test([])
|
56
|
+
assert_equal(nil, result)
|
57
|
+
result = EnumerableContract.test(5)
|
58
|
+
assert_instance_of(Contract::ContractMismatch, result)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_contract_test_all()
|
62
|
+
result = ListContract.test_all([])
|
63
|
+
assert_equal(nil, result)
|
64
|
+
result = ListContract.test_all(Object.new)
|
65
|
+
assert_instance_of(Array, result)
|
66
|
+
assert_equal(ListContract.check_count, result.size)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_contract_fulfilled_by?()
|
70
|
+
result = EnumerableContract.fulfilled_by?([])
|
71
|
+
assert_equal(true, result)
|
72
|
+
result = EnumerableContract.fulfilled_by?(5)
|
73
|
+
assert_equal(false, result)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_contract_enforce()
|
77
|
+
assert_nothing_raised { ListContract.enforce([]) }
|
78
|
+
assert_raise(Contract::ContractMismatch) do
|
79
|
+
ListContract.enforce(5)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_broken_contract()
|
84
|
+
result = BrokenContract.test(5)
|
85
|
+
assert_instance_of(Contract::ContractError, result)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_implies_non_module()
|
89
|
+
assert_raise(TypeError) do
|
90
|
+
Class.new(Contract) { implies 5 }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_implications()
|
95
|
+
assert_equal([List], ListContract.implications)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_inherited_implications()
|
99
|
+
assert_equal([List, List::NonEmpty], NonEmptyListContract.implications)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_implies()
|
103
|
+
assert_equal(true, EmptyList.ancestors.include?(List))
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_inherited_implies()
|
107
|
+
assert_equal(true, NonEmptyList.ancestors.include?(List::NonEmpty))
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$LOAD_PATH << "../lib"
|
3
|
+
require 'contract'
|
4
|
+
|
5
|
+
class TC_Exception < Test::Unit::TestCase
|
6
|
+
def test_extract_method_name()
|
7
|
+
{ "test_provides_each(ListContract)" => "test_provides_each",
|
8
|
+
"test_foo(Foo::Bar)" => "test_foo",
|
9
|
+
"test_bar(#<Class:0x2ba5e08>)" => "test_bar"
|
10
|
+
}.each do |from, to|
|
11
|
+
assert_equal(to, Contract.extract_method_name(from))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_fault_to_exception()
|
16
|
+
name, backtrace, message, object, contract =
|
17
|
+
"test_name(Contract)", caller, "message", Object.new,
|
18
|
+
Class.new(Contract)
|
19
|
+
exception = Exception.new(message)
|
20
|
+
exception.set_backtrace(backtrace)
|
21
|
+
|
22
|
+
[ Test::Unit::Failure.new(name, backtrace, message),
|
23
|
+
Test::Unit::Error.new(name, exception)
|
24
|
+
].each do |fault|
|
25
|
+
result = Contract.fault_to_exception(fault, object, contract)
|
26
|
+
|
27
|
+
assert_kind_of(Contract::ContractException, result)
|
28
|
+
assert_equal("test_name", result.test_method)
|
29
|
+
assert_equal(backtrace, result.backtrace)
|
30
|
+
assert_equal(message, result.original_message)
|
31
|
+
assert_equal(object, result.test_object)
|
32
|
+
assert_equal(contract, result.test_contract)
|
33
|
+
|
34
|
+
case fault
|
35
|
+
when Test::Unit::Failure then
|
36
|
+
assert_instance_of(Contract::ContractMismatch, result)
|
37
|
+
when Test::Unit::Error then
|
38
|
+
assert_instance_of(Contract::ContractError, result)
|
39
|
+
assert_equal(exception.class, result.type)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,357 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$LOAD_PATH << "../lib"
|
3
|
+
require 'contract'
|
4
|
+
|
5
|
+
module SignatureHelpers
|
6
|
+
def object(type = Object, *args, &block)
|
7
|
+
Class.new(type, &block).new(*args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class TC_Integration_Signature < Test::Unit::TestCase
|
12
|
+
include SignatureHelpers
|
13
|
+
|
14
|
+
def setup()
|
15
|
+
Contract.check_signatures = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_incompatible_signature()
|
19
|
+
exception = assert_raise(ArgumentError) do
|
20
|
+
object do
|
21
|
+
signature :to_s, :any
|
22
|
+
end
|
23
|
+
end
|
24
|
+
assert_equal("signature isn't compatible with arity",
|
25
|
+
exception.message)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_empty_repeated()
|
29
|
+
exception = assert_raise(ArgumentError) do
|
30
|
+
object do
|
31
|
+
signature :to_s, :repeated => []
|
32
|
+
end
|
33
|
+
end
|
34
|
+
assert_equal("repeated arguments may not be an empty Array",
|
35
|
+
exception.message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_invalid_specifier()
|
39
|
+
assert_raise(ArgumentError) do
|
40
|
+
object do
|
41
|
+
signature :is_a?, Class.new { undef :=== }.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_no_arguments()
|
47
|
+
obj = object do
|
48
|
+
alias :old_to_s :to_s
|
49
|
+
signature :to_s
|
50
|
+
end
|
51
|
+
assert_nothing_raised { obj.to_s }
|
52
|
+
assert_equal(obj.old_to_s, obj.to_s)
|
53
|
+
assert_raise(ArgumentError) { obj.to_s(1) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_return()
|
57
|
+
obj = object do
|
58
|
+
signature :inspect, :return => String
|
59
|
+
def foo() end
|
60
|
+
signature :foo, :return => String
|
61
|
+
end
|
62
|
+
assert_nothing_raised { obj.inspect }
|
63
|
+
assert_raise(StandardError) { obj.foo }
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_no_block()
|
67
|
+
obj = object do
|
68
|
+
signature :to_s, :block => false
|
69
|
+
end
|
70
|
+
assert_nothing_raised { obj.to_s }
|
71
|
+
assert_raise(ArgumentError) { obj.to_s { 1+1 } }
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_block()
|
75
|
+
obj = object(Array) do
|
76
|
+
signature :each, :block => true
|
77
|
+
end
|
78
|
+
assert_nothing_raised { obj.each {} }
|
79
|
+
assert_raise(ArgumentError) { obj.each }
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_any_arguments()
|
83
|
+
obj = object do
|
84
|
+
signature :respond_to?, :any, :any
|
85
|
+
end
|
86
|
+
assert_nothing_raised { obj.respond_to?(:inspect, true) }
|
87
|
+
assert_raise(ArgumentError) { obj.respond_to?() }
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_allow_trailing()
|
91
|
+
obj = object(Array) do
|
92
|
+
signature :zip, :allow_trailing => true
|
93
|
+
signature :values_at, :any, :allow_trailing => true
|
94
|
+
end
|
95
|
+
assert_nothing_raised { obj.zip }
|
96
|
+
assert_nothing_raised { obj.zip(obj) }
|
97
|
+
assert_nothing_raised { obj.values_at(0) }
|
98
|
+
assert_nothing_raised { obj.values_at(0, 0) }
|
99
|
+
assert_raise(ArgumentError) { obj.values_at }
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_classes()
|
103
|
+
obj = object(Array) do
|
104
|
+
signature :is_a?, Module
|
105
|
+
signature :join, String
|
106
|
+
signature :at, Integer
|
107
|
+
end
|
108
|
+
assert_nothing_raised { obj.is_a?(Array) }
|
109
|
+
assert_nothing_raised { obj.join(", ") }
|
110
|
+
assert_nothing_raised { obj.at(0) }
|
111
|
+
assert_raise(ArgumentError) { obj.is_a?(5) }
|
112
|
+
assert_raise(ArgumentError) { obj.join(5) }
|
113
|
+
assert_raise(ArgumentError) { obj.at("x") }
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_callable()
|
117
|
+
obj = object(Array) do
|
118
|
+
alias :x :*
|
119
|
+
|
120
|
+
signature :*, lambda { |arg| arg >= 0 }
|
121
|
+
signature :x, 0.method(:<=)
|
122
|
+
end
|
123
|
+
|
124
|
+
assert_nothing_raised { obj * 0 }
|
125
|
+
assert_nothing_raised { obj.x(0) }
|
126
|
+
assert_raise(ArgumentError) { obj * -1 }
|
127
|
+
assert_raise(ArgumentError) { obj.x(-1) }
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_optional()
|
131
|
+
obj = object do
|
132
|
+
def foo(x, y=5, z=3, *args) [x, y, z, *args] end
|
133
|
+
signature :foo, Numeric, :optional => [Numeric, Numeric],
|
134
|
+
:allow_trailing => true
|
135
|
+
end
|
136
|
+
|
137
|
+
assert_nothing_raised { obj.foo(5) }
|
138
|
+
assert_equal([5, 5, 3], obj.foo(5))
|
139
|
+
assert_nothing_raised { obj.foo(5, 4, 3) }
|
140
|
+
assert_nothing_raised { obj.foo(5, 4, 3, 2) }
|
141
|
+
assert_equal([5, 4, 3, 2], obj.foo(5, 4, 3, 2))
|
142
|
+
assert_raise(ArgumentError) { obj.foo }
|
143
|
+
assert_raise(ArgumentError) { obj.foo(5, "foo") }
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_repeated()
|
147
|
+
obj = object(Array) do
|
148
|
+
signature :zip, :repeated => [Enumerable]
|
149
|
+
signature :values_at, Numeric, :repeated => Numeric
|
150
|
+
end
|
151
|
+
assert_nothing_raised { obj.zip }
|
152
|
+
assert_nothing_raised { obj.zip(obj) }
|
153
|
+
assert_nothing_raised { obj.values_at(0) }
|
154
|
+
assert_nothing_raised { obj.values_at(0, 0) }
|
155
|
+
assert_raise(ArgumentError) { obj.values_at }
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_no_adaption()
|
159
|
+
obj = object do
|
160
|
+
signature :respond_to?, Symbol, :no_adaption => true
|
161
|
+
end
|
162
|
+
assert_nothing_raised { obj.respond_to?(:to_s) }
|
163
|
+
assert_raises(ArgumentError) { obj.respond_to?("to_s") }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
class TC_Integration_Checks < Test::Unit::TestCase
|
169
|
+
def test_block()
|
170
|
+
check = Contract::Check.block { |obj| obj > 0 }
|
171
|
+
assert_equal(true, check === 5)
|
172
|
+
assert_equal(false, check === -5)
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_quack()
|
176
|
+
check = Contract::Check::Quack[:to_str]
|
177
|
+
assert_equal(true, check === "foo")
|
178
|
+
assert_equal(false, check === Object.new)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_all()
|
182
|
+
check = Contract::Check::All[Numeric, 3 .. 10]
|
183
|
+
assert_equal(false, check === "x")
|
184
|
+
assert_equal(false, check === 2)
|
185
|
+
assert_equal(true, check === 5)
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_any()
|
189
|
+
check = Contract::Check::Any[Numeric, Symbol]
|
190
|
+
assert_equal(false, check === "x")
|
191
|
+
assert_equal(true, check === 5)
|
192
|
+
assert_equal(true, check === :x)
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_none()
|
196
|
+
check = Contract::Check::None[Numeric, Symbol]
|
197
|
+
assert_equal(true, check === "x")
|
198
|
+
assert_equal(false, check === 5)
|
199
|
+
assert_equal(false, check === :x)
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_aliases()
|
203
|
+
assert_equal(Contract::Check::All, Contract::Check::And)
|
204
|
+
assert_equal(Contract::Check::Any, Contract::Check::Or)
|
205
|
+
assert_equal(Contract::Check::None, Contract::Check::Not)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
class TC_Integration_Fulfills < Test::Unit::TestCase
|
211
|
+
class ListContract < Contract
|
212
|
+
provides :each, :[]
|
213
|
+
provides :size do
|
214
|
+
assert_nothing_raised { @object.size }
|
215
|
+
assert(@object.size >= 0)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class ListWrapper
|
220
|
+
def initialize(list)
|
221
|
+
@list = list
|
222
|
+
end
|
223
|
+
|
224
|
+
def each(&block) @list.each(&block) end
|
225
|
+
def size() @list.size end
|
226
|
+
def [](*args) @list[*args] end
|
227
|
+
|
228
|
+
fulfills ListContract
|
229
|
+
end
|
230
|
+
|
231
|
+
def setup()
|
232
|
+
Contract.check_fulfills = true
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_fulfills()
|
236
|
+
assert_nothing_raised { ListWrapper.new([]) }
|
237
|
+
assert_raise(Contract::ContractMismatch) { ListWrapper.new(Object.new) }
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
class TC_Integration_Adaption < Test::Unit::TestCase
|
243
|
+
include SignatureHelpers
|
244
|
+
|
245
|
+
def test_no_from_and_to()
|
246
|
+
assert_raises(ArgumentError) do
|
247
|
+
object { adaption :via => :to_s }
|
248
|
+
end
|
249
|
+
|
250
|
+
assert_raises(ArgumentError) do
|
251
|
+
cls = Class.new
|
252
|
+
adaption :from => cls, :to => cls, :via => :to_s
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_no_via()
|
257
|
+
assert_raises(ArgumentError) do
|
258
|
+
adaption :from => Class.new, :to => Class.new
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_via_and_block()
|
263
|
+
assert_raises(ArgumentError) do
|
264
|
+
adaption :from => Class.new, :to => Class.new, :via => :to_s do |obj|
|
265
|
+
obj.to_s
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_block()
|
271
|
+
obj = object do
|
272
|
+
adaption(:to => String) { "string" }
|
273
|
+
end
|
274
|
+
|
275
|
+
assert_equal("string", Contract.adapt(obj, String))
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_callable_if()
|
279
|
+
cls = Class.new(Object) do
|
280
|
+
attr_accessor :value
|
281
|
+
|
282
|
+
def initialize(value)
|
283
|
+
@value = value
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
obj = object do
|
288
|
+
adaption :from => cls, :to => String, :via => :value,
|
289
|
+
:if => lambda { |obj| obj.value.is_a?(String) }
|
290
|
+
end
|
291
|
+
|
292
|
+
assert_equal("foo", Contract.adapt(cls.new("foo"), String))
|
293
|
+
obj = cls.new(5)
|
294
|
+
assert_equal(obj, Contract.adapt(obj, String))
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_default_adaptions()
|
298
|
+
obj = object do
|
299
|
+
[Symbol, String, Array, Integer].each do |cls|
|
300
|
+
method = cls.name.downcase.intern
|
301
|
+
define_method(method) { |arg| arg }
|
302
|
+
signature(method, cls)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
string_like = object { def to_str() "foo" end }
|
307
|
+
array_like = object { def to_ary() [1, 2] end }
|
308
|
+
|
309
|
+
assert_equal(:foo, obj.symbol("foo"))
|
310
|
+
assert_equal("foo", obj.string(string_like))
|
311
|
+
assert_equal([1, 2], obj.array(array_like))
|
312
|
+
assert_equal(5, obj.integer(5.0))
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
|
317
|
+
class TC_Integration_MethodSignatureMixin < Test::Unit::TestCase
|
318
|
+
include SignatureHelpers
|
319
|
+
|
320
|
+
def test_origin()
|
321
|
+
assert_equal(String, "foo".method(:+).origin)
|
322
|
+
assert_equal(Array, Array.instance_method(:[]).origin)
|
323
|
+
end
|
324
|
+
|
325
|
+
def test_name()
|
326
|
+
assert_equal(:+, "foo".method(:+).name)
|
327
|
+
assert_equal(:[], Array.instance_method(:[]).name)
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_has_signature?()
|
331
|
+
assert(!"foo".method(:+).has_signature?)
|
332
|
+
obj = object do
|
333
|
+
def x() end
|
334
|
+
signature :x
|
335
|
+
end
|
336
|
+
assert(obj.method(:x).has_signature?)
|
337
|
+
end
|
338
|
+
|
339
|
+
def test_signature()
|
340
|
+
obj = object do
|
341
|
+
def m0() end
|
342
|
+
def m1(a) end
|
343
|
+
def t(a,*) end
|
344
|
+
end
|
345
|
+
assert_equal([[], {}], obj.method(:m0).signature)
|
346
|
+
assert_equal([[:any], {}], obj.method(:m1).signature)
|
347
|
+
assert_equal([[:any], { :allow_trailing => true }],
|
348
|
+
obj.method(:t).signature)
|
349
|
+
|
350
|
+
sign = [[Fixnum, String], { :repeated => [1 .. 10, 2 .. 3] }]
|
351
|
+
obj = object do
|
352
|
+
def x(*) end
|
353
|
+
signature(:x, *sign.flatten)
|
354
|
+
end
|
355
|
+
assert_equal(sign, obj.method(:x).signature)
|
356
|
+
end
|
357
|
+
end
|