entitlements-app 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/deploy-entitlements +10 -1
- data/lib/contracts-ruby2/CHANGELOG.markdown +115 -0
- data/lib/contracts-ruby2/Gemfile +17 -0
- data/lib/contracts-ruby2/LICENSE +23 -0
- data/lib/contracts-ruby2/README.md +108 -0
- data/lib/contracts-ruby2/Rakefile +8 -0
- data/lib/contracts-ruby2/TODO.markdown +6 -0
- data/lib/contracts-ruby2/TUTORIAL.md +773 -0
- data/lib/contracts-ruby2/benchmarks/bench.rb +67 -0
- data/lib/contracts-ruby2/benchmarks/hash.rb +69 -0
- data/lib/contracts-ruby2/benchmarks/invariants.rb +91 -0
- data/lib/contracts-ruby2/benchmarks/io.rb +62 -0
- data/lib/contracts-ruby2/benchmarks/wrap_test.rb +57 -0
- data/lib/contracts-ruby2/contracts.gemspec +17 -0
- data/lib/contracts-ruby2/cucumber.yml +1 -0
- data/lib/contracts-ruby2/dependabot.yml +20 -0
- data/lib/contracts-ruby2/features/README.md +17 -0
- data/lib/contracts-ruby2/features/basics/functype.feature +71 -0
- data/lib/contracts-ruby2/features/basics/pretty-print.feature +241 -0
- data/lib/contracts-ruby2/features/basics/simple_example.feature +210 -0
- data/lib/contracts-ruby2/features/builtin_contracts/README.md +22 -0
- data/lib/contracts-ruby2/features/builtin_contracts/and.feature +103 -0
- data/lib/contracts-ruby2/features/builtin_contracts/any.feature +44 -0
- data/lib/contracts-ruby2/features/builtin_contracts/args.feature +80 -0
- data/lib/contracts-ruby2/features/builtin_contracts/array_of.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/bool.feature +64 -0
- data/lib/contracts-ruby2/features/builtin_contracts/enum.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/eq.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/exactly.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/func.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/hash_of.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/int.feature +93 -0
- data/lib/contracts-ruby2/features/builtin_contracts/keyword_args.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/maybe.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/nat.feature +115 -0
- data/lib/contracts-ruby2/features/builtin_contracts/nat_pos.feature +119 -0
- data/lib/contracts-ruby2/features/builtin_contracts/neg.feature +115 -0
- data/lib/contracts-ruby2/features/builtin_contracts/none.feature +145 -0
- data/lib/contracts-ruby2/features/builtin_contracts/not.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/num.feature +64 -0
- data/lib/contracts-ruby2/features/builtin_contracts/or.feature +83 -0
- data/lib/contracts-ruby2/features/builtin_contracts/pos.feature +116 -0
- data/lib/contracts-ruby2/features/builtin_contracts/range_of.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/respond_to.feature +78 -0
- data/lib/contracts-ruby2/features/builtin_contracts/send.feature +147 -0
- data/lib/contracts-ruby2/features/builtin_contracts/set_of.feature +1 -0
- data/lib/contracts-ruby2/features/builtin_contracts/xor.feature +99 -0
- data/lib/contracts-ruby2/features/support/env.rb +6 -0
- data/lib/contracts-ruby2/lib/contracts/attrs.rb +24 -0
- data/lib/contracts-ruby2/lib/contracts/builtin_contracts.rb +542 -0
- data/lib/contracts-ruby2/lib/contracts/call_with.rb +108 -0
- data/lib/contracts-ruby2/lib/contracts/core.rb +52 -0
- data/lib/contracts-ruby2/lib/contracts/decorators.rb +47 -0
- data/lib/contracts-ruby2/lib/contracts/engine/base.rb +136 -0
- data/lib/contracts-ruby2/lib/contracts/engine/eigenclass.rb +50 -0
- data/lib/contracts-ruby2/lib/contracts/engine/target.rb +70 -0
- data/lib/contracts-ruby2/lib/contracts/engine.rb +26 -0
- data/lib/contracts-ruby2/lib/contracts/errors.rb +71 -0
- data/lib/contracts-ruby2/lib/contracts/formatters.rb +136 -0
- data/lib/contracts-ruby2/lib/contracts/invariants.rb +68 -0
- data/lib/contracts-ruby2/lib/contracts/method_handler.rb +187 -0
- data/lib/contracts-ruby2/lib/contracts/method_reference.rb +100 -0
- data/lib/contracts-ruby2/lib/contracts/support.rb +61 -0
- data/lib/contracts-ruby2/lib/contracts/validators.rb +139 -0
- data/lib/contracts-ruby2/lib/contracts/version.rb +3 -0
- data/lib/contracts-ruby2/lib/contracts.rb +281 -0
- data/lib/contracts-ruby2/script/docs-release +3 -0
- data/lib/contracts-ruby2/script/docs-staging +3 -0
- data/lib/contracts-ruby2/script/rubocop.rb +5 -0
- data/lib/contracts-ruby2/spec/attrs_spec.rb +119 -0
- data/lib/contracts-ruby2/spec/builtin_contracts_spec.rb +461 -0
- data/lib/contracts-ruby2/spec/contracts_spec.rb +770 -0
- data/lib/contracts-ruby2/spec/fixtures/fixtures.rb +730 -0
- data/lib/contracts-ruby2/spec/invariants_spec.rb +17 -0
- data/lib/contracts-ruby2/spec/methods_spec.rb +54 -0
- data/lib/contracts-ruby2/spec/module_spec.rb +18 -0
- data/lib/contracts-ruby2/spec/override_validators_spec.rb +162 -0
- data/lib/contracts-ruby2/spec/ruby_version_specific/contracts_spec_1.9.rb +24 -0
- data/lib/contracts-ruby2/spec/ruby_version_specific/contracts_spec_2.0.rb +55 -0
- data/lib/contracts-ruby2/spec/ruby_version_specific/contracts_spec_2.1.rb +63 -0
- data/lib/contracts-ruby2/spec/spec_helper.rb +102 -0
- data/lib/contracts-ruby2/spec/support.rb +10 -0
- data/lib/contracts-ruby2/spec/support_spec.rb +21 -0
- data/lib/contracts-ruby2/spec/validators_spec.rb +47 -0
- data/lib/contracts-ruby3/CHANGELOG.markdown +117 -0
- data/lib/contracts-ruby3/Gemfile +21 -0
- data/lib/contracts-ruby3/LICENSE +23 -0
- data/lib/contracts-ruby3/README.md +114 -0
- data/lib/contracts-ruby3/Rakefile +10 -0
- data/lib/contracts-ruby3/TODO.markdown +6 -0
- data/lib/contracts-ruby3/TUTORIAL.md +773 -0
- data/lib/contracts-ruby3/benchmarks/bench.rb +67 -0
- data/lib/contracts-ruby3/benchmarks/hash.rb +69 -0
- data/lib/contracts-ruby3/benchmarks/invariants.rb +91 -0
- data/lib/contracts-ruby3/benchmarks/io.rb +62 -0
- data/lib/contracts-ruby3/benchmarks/wrap_test.rb +57 -0
- data/lib/contracts-ruby3/contracts.gemspec +20 -0
- data/lib/contracts-ruby3/cucumber.yml +1 -0
- data/lib/contracts-ruby3/dependabot.yml +20 -0
- data/lib/contracts-ruby3/features/README.md +17 -0
- data/lib/contracts-ruby3/features/basics/functype.feature +71 -0
- data/lib/contracts-ruby3/features/basics/pretty-print.feature +241 -0
- data/lib/contracts-ruby3/features/basics/simple_example.feature +210 -0
- data/lib/contracts-ruby3/features/builtin_contracts/README.md +22 -0
- data/lib/contracts-ruby3/features/builtin_contracts/and.feature +103 -0
- data/lib/contracts-ruby3/features/builtin_contracts/any.feature +44 -0
- data/lib/contracts-ruby3/features/builtin_contracts/args.feature +80 -0
- data/lib/contracts-ruby3/features/builtin_contracts/array_of.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/bool.feature +64 -0
- data/lib/contracts-ruby3/features/builtin_contracts/enum.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/eq.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/exactly.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/func.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/hash_of.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/int.feature +93 -0
- data/lib/contracts-ruby3/features/builtin_contracts/keyword_args.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/maybe.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/nat.feature +115 -0
- data/lib/contracts-ruby3/features/builtin_contracts/nat_pos.feature +119 -0
- data/lib/contracts-ruby3/features/builtin_contracts/neg.feature +115 -0
- data/lib/contracts-ruby3/features/builtin_contracts/none.feature +145 -0
- data/lib/contracts-ruby3/features/builtin_contracts/not.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/num.feature +64 -0
- data/lib/contracts-ruby3/features/builtin_contracts/or.feature +83 -0
- data/lib/contracts-ruby3/features/builtin_contracts/pos.feature +116 -0
- data/lib/contracts-ruby3/features/builtin_contracts/range_of.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/respond_to.feature +78 -0
- data/lib/contracts-ruby3/features/builtin_contracts/send.feature +147 -0
- data/lib/contracts-ruby3/features/builtin_contracts/set_of.feature +1 -0
- data/lib/contracts-ruby3/features/builtin_contracts/xor.feature +99 -0
- data/lib/contracts-ruby3/features/support/env.rb +8 -0
- data/lib/contracts-ruby3/lib/contracts/attrs.rb +26 -0
- data/lib/contracts-ruby3/lib/contracts/builtin_contracts.rb +575 -0
- data/lib/contracts-ruby3/lib/contracts/call_with.rb +119 -0
- data/lib/contracts-ruby3/lib/contracts/core.rb +54 -0
- data/lib/contracts-ruby3/lib/contracts/decorators.rb +50 -0
- data/lib/contracts-ruby3/lib/contracts/engine/base.rb +137 -0
- data/lib/contracts-ruby3/lib/contracts/engine/eigenclass.rb +51 -0
- data/lib/contracts-ruby3/lib/contracts/engine/target.rb +72 -0
- data/lib/contracts-ruby3/lib/contracts/engine.rb +28 -0
- data/lib/contracts-ruby3/lib/contracts/errors.rb +74 -0
- data/lib/contracts-ruby3/lib/contracts/formatters.rb +140 -0
- data/lib/contracts-ruby3/lib/contracts/invariants.rb +72 -0
- data/lib/contracts-ruby3/lib/contracts/method_handler.rb +197 -0
- data/lib/contracts-ruby3/lib/contracts/method_reference.rb +102 -0
- data/lib/contracts-ruby3/lib/contracts/support.rb +63 -0
- data/lib/contracts-ruby3/lib/contracts/validators.rb +143 -0
- data/lib/contracts-ruby3/lib/contracts/version.rb +5 -0
- data/lib/contracts-ruby3/lib/contracts.rb +290 -0
- data/lib/contracts-ruby3/script/docs-release +3 -0
- data/lib/contracts-ruby3/script/docs-staging +3 -0
- data/lib/contracts-ruby3/script/rubocop.rb +5 -0
- data/lib/contracts-ruby3/spec/attrs_spec.rb +119 -0
- data/lib/contracts-ruby3/spec/builtin_contracts_spec.rb +457 -0
- data/lib/contracts-ruby3/spec/contracts_spec.rb +773 -0
- data/lib/contracts-ruby3/spec/fixtures/fixtures.rb +725 -0
- data/lib/contracts-ruby3/spec/invariants_spec.rb +17 -0
- data/lib/contracts-ruby3/spec/methods_spec.rb +54 -0
- data/lib/contracts-ruby3/spec/module_spec.rb +18 -0
- data/lib/contracts-ruby3/spec/override_validators_spec.rb +162 -0
- data/lib/contracts-ruby3/spec/ruby_version_specific/contracts_spec_1.9.rb +24 -0
- data/lib/contracts-ruby3/spec/ruby_version_specific/contracts_spec_2.0.rb +55 -0
- data/lib/contracts-ruby3/spec/ruby_version_specific/contracts_spec_2.1.rb +63 -0
- data/lib/contracts-ruby3/spec/spec_helper.rb +102 -0
- data/lib/contracts-ruby3/spec/support.rb +10 -0
- data/lib/contracts-ruby3/spec/support_spec.rb +21 -0
- data/lib/contracts-ruby3/spec/validators_spec.rb +47 -0
- data/lib/entitlements/data/groups/calculated/yaml.rb +7 -1
- data/lib/entitlements/data/people/yaml.rb +9 -1
- data/lib/entitlements/extras/ldap_group/rules/ldap_group.rb +5 -1
- data/lib/entitlements/extras/orgchart/person_methods.rb +7 -1
- data/lib/entitlements.rb +13 -2
- data/lib/ruby_version_check.rb +17 -0
- metadata +209 -14
@@ -0,0 +1,241 @@
|
|
1
|
+
Feature: Pretty printing Contract violations
|
2
|
+
|
3
|
+
Scenario: Big array argument being passed to big array method parameter
|
4
|
+
Given a file named "example.rb" with:
|
5
|
+
"""ruby
|
6
|
+
require "contracts"
|
7
|
+
C = Contracts
|
8
|
+
|
9
|
+
class Example
|
10
|
+
include Contracts::Core
|
11
|
+
|
12
|
+
class << self
|
13
|
+
Contract [
|
14
|
+
C::Or[String, Symbol],
|
15
|
+
C::Or[String, Symbol],
|
16
|
+
C::Or[String, Symbol],
|
17
|
+
C::Or[String, Symbol],
|
18
|
+
C::Or[String, Symbol],
|
19
|
+
C::Or[String, Symbol],
|
20
|
+
C::Or[String, Symbol]
|
21
|
+
] => nil
|
22
|
+
def run(data)
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
puts Example.run([
|
29
|
+
["foo", "foo"],
|
30
|
+
["foo", "foo"],
|
31
|
+
["foo", "foo"],
|
32
|
+
["foo", "foo"],
|
33
|
+
["foo", "foo"],
|
34
|
+
["foo", "foo"],
|
35
|
+
["foo", "foo"],
|
36
|
+
["foo", "foo"],
|
37
|
+
["foo", "foo"]
|
38
|
+
])
|
39
|
+
"""
|
40
|
+
When I run `ruby example.rb`
|
41
|
+
Then the output should contain:
|
42
|
+
"""
|
43
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
44
|
+
Expected: [(String or Symbol),
|
45
|
+
(String or Symbol),
|
46
|
+
(String or Symbol),
|
47
|
+
(String or Symbol),
|
48
|
+
(String or Symbol),
|
49
|
+
(String or Symbol),
|
50
|
+
(String or Symbol)],
|
51
|
+
Actual: [["foo", "foo"],
|
52
|
+
["foo", "foo"],
|
53
|
+
["foo", "foo"],
|
54
|
+
["foo", "foo"],
|
55
|
+
["foo", "foo"],
|
56
|
+
["foo", "foo"],
|
57
|
+
["foo", "foo"],
|
58
|
+
["foo", "foo"],
|
59
|
+
["foo", "foo"]]
|
60
|
+
Value guarded in: Example::run
|
61
|
+
With Contract: Array => NilClass
|
62
|
+
At: example.rb:17
|
63
|
+
"""
|
64
|
+
|
65
|
+
Scenario: Big array value being returned from method expecting different big array type
|
66
|
+
Given a file named "example.rb" with:
|
67
|
+
"""ruby
|
68
|
+
require "contracts"
|
69
|
+
C = Contracts
|
70
|
+
|
71
|
+
class Example
|
72
|
+
include Contracts::Core
|
73
|
+
|
74
|
+
class << self
|
75
|
+
Contract C::None => [
|
76
|
+
C::Or[String, Symbol],
|
77
|
+
C::Or[String, Symbol],
|
78
|
+
C::Or[String, Symbol],
|
79
|
+
C::Or[String, Symbol],
|
80
|
+
C::Or[String, Symbol],
|
81
|
+
C::Or[String, Symbol],
|
82
|
+
C::Or[String, Symbol]
|
83
|
+
]
|
84
|
+
def run
|
85
|
+
[
|
86
|
+
["foo", "foo"],
|
87
|
+
["foo", "foo"],
|
88
|
+
["foo", "foo"],
|
89
|
+
["foo", "foo"],
|
90
|
+
["foo", "foo"],
|
91
|
+
["foo", "foo"],
|
92
|
+
["foo", "foo"],
|
93
|
+
["foo", "foo"],
|
94
|
+
["foo", "foo"]
|
95
|
+
]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
puts Example.run
|
101
|
+
"""
|
102
|
+
When I run `ruby example.rb`
|
103
|
+
Then the output should contain:
|
104
|
+
"""
|
105
|
+
: Contract violation for return value: (ReturnContractError)
|
106
|
+
Expected: [(String or Symbol),
|
107
|
+
(String or Symbol),
|
108
|
+
(String or Symbol),
|
109
|
+
(String or Symbol),
|
110
|
+
(String or Symbol),
|
111
|
+
(String or Symbol),
|
112
|
+
(String or Symbol)],
|
113
|
+
Actual: [["foo", "foo"],
|
114
|
+
["foo", "foo"],
|
115
|
+
["foo", "foo"],
|
116
|
+
["foo", "foo"],
|
117
|
+
["foo", "foo"],
|
118
|
+
["foo", "foo"],
|
119
|
+
["foo", "foo"],
|
120
|
+
["foo", "foo"],
|
121
|
+
["foo", "foo"]]
|
122
|
+
Value guarded in: Example::run
|
123
|
+
With Contract: None => Array
|
124
|
+
At: example.rb:17
|
125
|
+
"""
|
126
|
+
|
127
|
+
Scenario: Big hash argument being passed to big hash method parameter
|
128
|
+
Given a file named "example.rb" with:
|
129
|
+
"""ruby
|
130
|
+
require "contracts"
|
131
|
+
C = Contracts
|
132
|
+
|
133
|
+
class Example
|
134
|
+
include Contracts::Core
|
135
|
+
|
136
|
+
class << self
|
137
|
+
Contract ({
|
138
|
+
a: C::Or[String, Symbol],
|
139
|
+
b: C::Or[String, Symbol],
|
140
|
+
c: C::Or[String, Symbol],
|
141
|
+
d: C::Or[String, Symbol],
|
142
|
+
e: C::Or[String, Symbol],
|
143
|
+
f: C::Or[String, Symbol],
|
144
|
+
g: C::Or[String, Symbol]
|
145
|
+
}) => nil
|
146
|
+
def run(data)
|
147
|
+
nil
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
puts Example.run({
|
153
|
+
a: ["foo", "foo"],
|
154
|
+
b: ["foo", "foo"],
|
155
|
+
c: ["foo", "foo"],
|
156
|
+
d: ["foo", "foo"],
|
157
|
+
e: ["foo", "foo"],
|
158
|
+
f: ["foo", "foo"],
|
159
|
+
g: ["foo", "foo"]
|
160
|
+
})
|
161
|
+
"""
|
162
|
+
When I run `ruby example.rb`
|
163
|
+
Then the output should contain:
|
164
|
+
"""
|
165
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
166
|
+
Expected: {:a=>(String or Symbol),
|
167
|
+
:b=>(String or Symbol),
|
168
|
+
:c=>(String or Symbol),
|
169
|
+
:d=>(String or Symbol),
|
170
|
+
:e=>(String or Symbol),
|
171
|
+
:f=>(String or Symbol),
|
172
|
+
:g=>(String or Symbol)},
|
173
|
+
Actual: {:a=>["foo", "foo"],
|
174
|
+
:b=>["foo", "foo"],
|
175
|
+
:c=>["foo", "foo"],
|
176
|
+
:d=>["foo", "foo"],
|
177
|
+
:e=>["foo", "foo"],
|
178
|
+
:f=>["foo", "foo"],
|
179
|
+
:g=>["foo", "foo"]}
|
180
|
+
Value guarded in: Example::run
|
181
|
+
With Contract: Hash => NilClass
|
182
|
+
At: example.rb:17
|
183
|
+
"""
|
184
|
+
|
185
|
+
Scenario: Big hash value being returned from method expecting different big hash type
|
186
|
+
Given a file named "example.rb" with:
|
187
|
+
"""ruby
|
188
|
+
require "contracts"
|
189
|
+
C = Contracts
|
190
|
+
|
191
|
+
class Example
|
192
|
+
include Contracts::Core
|
193
|
+
|
194
|
+
class << self
|
195
|
+
Contract C::None => ({
|
196
|
+
a: C::Or[String, Symbol],
|
197
|
+
b: C::Or[String, Symbol],
|
198
|
+
c: C::Or[String, Symbol],
|
199
|
+
d: C::Or[String, Symbol],
|
200
|
+
e: C::Or[String, Symbol],
|
201
|
+
f: C::Or[String, Symbol],
|
202
|
+
g: C::Or[String, Symbol]
|
203
|
+
})
|
204
|
+
def run
|
205
|
+
{
|
206
|
+
a: ["foo", "foo"],
|
207
|
+
b: ["foo", "foo"],
|
208
|
+
c: ["foo", "foo"],
|
209
|
+
d: ["foo", "foo"],
|
210
|
+
e: ["foo", "foo"],
|
211
|
+
f: ["foo", "foo"],
|
212
|
+
g: ["foo", "foo"]
|
213
|
+
}
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
puts Example.run
|
219
|
+
"""
|
220
|
+
When I run `ruby example.rb`
|
221
|
+
Then the output should contain:
|
222
|
+
"""
|
223
|
+
: Contract violation for return value: (ReturnContractError)
|
224
|
+
Expected: {:a=>(String or Symbol),
|
225
|
+
:b=>(String or Symbol),
|
226
|
+
:c=>(String or Symbol),
|
227
|
+
:d=>(String or Symbol),
|
228
|
+
:e=>(String or Symbol),
|
229
|
+
:f=>(String or Symbol),
|
230
|
+
:g=>(String or Symbol)},
|
231
|
+
Actual: {:a=>["foo", "foo"],
|
232
|
+
:b=>["foo", "foo"],
|
233
|
+
:c=>["foo", "foo"],
|
234
|
+
:d=>["foo", "foo"],
|
235
|
+
:e=>["foo", "foo"],
|
236
|
+
:f=>["foo", "foo"],
|
237
|
+
:g=>["foo", "foo"]}
|
238
|
+
Value guarded in: Example::run
|
239
|
+
With Contract: None => Hash
|
240
|
+
At: example.rb:17
|
241
|
+
"""
|
@@ -0,0 +1,210 @@
|
|
1
|
+
Feature: Simple examples and Contract violations
|
2
|
+
|
3
|
+
Contracts.ruby allows specification of contracts on per-method basis, where
|
4
|
+
method arguments and return value will be validated upon method call.
|
5
|
+
|
6
|
+
Example:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
Contract C::Num, C::Num => C::Num
|
10
|
+
def add(a, b)
|
11
|
+
a + b
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
Here `Contract arg_contracts... => return_contract` defines list of argument
|
16
|
+
contracts `args_contracts...` as `C::Num, C::Num` (i.e.: both arguments
|
17
|
+
should be numbers) and return value contract `return_contract` as `C::Num`
|
18
|
+
(i.e.: return value should be a number too).
|
19
|
+
|
20
|
+
`Contract arg_contracts... => return_contract` affects next defined instance,
|
21
|
+
class or singleton method, meaning that all of these work:
|
22
|
+
|
23
|
+
- [Instance method](#instance-method),
|
24
|
+
|
25
|
+
- [Class method](#class-method),
|
26
|
+
|
27
|
+
- [Singleton method](#singleton-method).
|
28
|
+
|
29
|
+
Whenever invalid argument is passed to a contracted method, corresponding
|
30
|
+
`ContractError` will be raised. That happens right after bad value got into
|
31
|
+
system protected by contracts and prevents error propagation: first
|
32
|
+
non-contracts library frame in exception's backtrace is a culprit for passing
|
33
|
+
an invalid argument - you do not need to verify 20-30 frames to find a
|
34
|
+
culprit! Example of such error: [instance method contract
|
35
|
+
violation](#instance-method-contract-violation).
|
36
|
+
|
37
|
+
Whenever invalid return value is returned from a contracted method,
|
38
|
+
corresponding `ContractError` will be raised. That happens right after method
|
39
|
+
returned this value and prevents error propagation: `At: your_filename.rb:17`
|
40
|
+
part of error message points directly to a culprit method. Example of such
|
41
|
+
error: [return value contract
|
42
|
+
violation](#singleton-method-return-value-contract-violation).
|
43
|
+
|
44
|
+
Contract violation error consists of such parts:
|
45
|
+
- Violation type:
|
46
|
+
- `Contract violation for argument X of Y: (ParamContractError)`,
|
47
|
+
- `Contract violation for return value (ReturnContractError)`.
|
48
|
+
- Expected contract, example: `Expected: Num`.
|
49
|
+
- Actual value, example: `Actual: "foo"`.
|
50
|
+
- Location of violated contract, example: `Value guarded in: Example::add`.
|
51
|
+
- Full contract, example: `With Contract: Num, Num => Num`.
|
52
|
+
- Source code location of contracted method, example: `At: lib/your_library/some_class.rb:17`.
|
53
|
+
|
54
|
+
Scenario: Instance method
|
55
|
+
Given a file named "instance_method.rb" with:
|
56
|
+
"""ruby
|
57
|
+
require "contracts"
|
58
|
+
C = Contracts
|
59
|
+
|
60
|
+
class Example
|
61
|
+
include Contracts::Core
|
62
|
+
|
63
|
+
Contract C::Num, C::Num => C::Num
|
64
|
+
def add(a, b)
|
65
|
+
a + b
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
puts Example.new.add(2, 2)
|
70
|
+
"""
|
71
|
+
When I run `ruby instance_method.rb`
|
72
|
+
Then the output should contain:
|
73
|
+
"""
|
74
|
+
4
|
75
|
+
"""
|
76
|
+
|
77
|
+
Scenario: Instance method contract violation
|
78
|
+
Given a file named "instance_method_violation.rb" with:
|
79
|
+
"""ruby
|
80
|
+
require "contracts"
|
81
|
+
C = Contracts
|
82
|
+
|
83
|
+
class Example
|
84
|
+
include Contracts::Core
|
85
|
+
|
86
|
+
Contract C::Num, C::Num => C::Num
|
87
|
+
def add(a, b)
|
88
|
+
a + b
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
puts Example.new.add(2, "foo")
|
93
|
+
"""
|
94
|
+
When I run `ruby instance_method_violation.rb`
|
95
|
+
Then the output should contain:
|
96
|
+
"""
|
97
|
+
: Contract violation for argument 2 of 2: (ParamContractError)
|
98
|
+
Expected: Num,
|
99
|
+
Actual: "foo"
|
100
|
+
Value guarded in: Example::add
|
101
|
+
With Contract: Num, Num => Num
|
102
|
+
At: instance_method_violation.rb:8
|
103
|
+
"""
|
104
|
+
|
105
|
+
Scenario: Class method
|
106
|
+
Given a file named "class_method.rb" with:
|
107
|
+
"""ruby
|
108
|
+
require "contracts"
|
109
|
+
C = Contracts
|
110
|
+
|
111
|
+
class Example
|
112
|
+
include Contracts::Core
|
113
|
+
|
114
|
+
Contract C::Num, C::Num => C::Num
|
115
|
+
def self.add(a, b)
|
116
|
+
a + b
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
puts Example.add(2, 2)
|
121
|
+
"""
|
122
|
+
When I run `ruby class_method.rb`
|
123
|
+
Then the output should contain:
|
124
|
+
"""
|
125
|
+
4
|
126
|
+
"""
|
127
|
+
|
128
|
+
Scenario: Class method contract violation
|
129
|
+
Given a file named "class_method_violation.rb" with:
|
130
|
+
"""ruby
|
131
|
+
require "contracts"
|
132
|
+
C = Contracts
|
133
|
+
|
134
|
+
class Example
|
135
|
+
include Contracts::Core
|
136
|
+
|
137
|
+
Contract C::Num, C::Num => C::Num
|
138
|
+
def self.add(a, b)
|
139
|
+
a + b
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
puts Example.add(:foo, 2)
|
144
|
+
"""
|
145
|
+
When I run `ruby class_method_violation.rb`
|
146
|
+
Then the output should contain:
|
147
|
+
"""
|
148
|
+
: Contract violation for argument 1 of 2: (ParamContractError)
|
149
|
+
Expected: Num,
|
150
|
+
Actual: :foo
|
151
|
+
Value guarded in: Example::add
|
152
|
+
With Contract: Num, Num => Num
|
153
|
+
At: class_method_violation.rb:8
|
154
|
+
"""
|
155
|
+
|
156
|
+
Scenario: Singleton method
|
157
|
+
Given a file named "singleton_method.rb" with:
|
158
|
+
"""ruby
|
159
|
+
require "contracts"
|
160
|
+
C = Contracts
|
161
|
+
|
162
|
+
class Example
|
163
|
+
include Contracts::Core
|
164
|
+
|
165
|
+
class << self
|
166
|
+
Contract C::Num, C::Num => C::Num
|
167
|
+
def add(a, b)
|
168
|
+
a + b
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
puts Example.add(2, 2)
|
174
|
+
"""
|
175
|
+
When I run `ruby singleton_method.rb`
|
176
|
+
Then the output should contain:
|
177
|
+
"""
|
178
|
+
4
|
179
|
+
"""
|
180
|
+
|
181
|
+
Scenario: Singleton method return value contract violation
|
182
|
+
Given a file named "singleton_method_violation.rb" with:
|
183
|
+
"""ruby
|
184
|
+
require "contracts"
|
185
|
+
C = Contracts
|
186
|
+
|
187
|
+
class Example
|
188
|
+
include Contracts::Core
|
189
|
+
|
190
|
+
class << self
|
191
|
+
Contract C::Num, C::Num => C::Num
|
192
|
+
def add(a, b)
|
193
|
+
# notice here non-number is returned
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
puts Example.add(2, 2)
|
200
|
+
"""
|
201
|
+
When I run `ruby singleton_method_violation.rb`
|
202
|
+
Then the output should contain:
|
203
|
+
"""
|
204
|
+
: Contract violation for return value: (ReturnContractError)
|
205
|
+
Expected: Num,
|
206
|
+
Actual: nil
|
207
|
+
Value guarded in: Example::add
|
208
|
+
With Contract: Num, Num => Num
|
209
|
+
At: singleton_method_violation.rb:9
|
210
|
+
"""
|
@@ -0,0 +1,22 @@
|
|
1
|
+
To use builtin contracts you can refer them with `Contracts::*`:
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
Contract Contracts::Num => Contracts::Maybe(Contracts::Num)
|
5
|
+
```
|
6
|
+
|
7
|
+
It is recommended to use a short alias for `Contracts`, for example `C`:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
C = Contracts
|
11
|
+
|
12
|
+
Contract C::Num => C::Maybe(C::Num)
|
13
|
+
```
|
14
|
+
|
15
|
+
It is possible to `include Contracts` and refer them without namespace, but
|
16
|
+
this is deprecated and not recommended.
|
17
|
+
|
18
|
+
*NOTE: in the future it will be possible to do `include Contracts::Builtin`
|
19
|
+
instead.*
|
20
|
+
|
21
|
+
*NOTE: all contracts marked as (TODO) have their documentaion `.feature` file
|
22
|
+
as stub. Contributions to those are warmly welcome!*
|
@@ -0,0 +1,103 @@
|
|
1
|
+
Feature: And
|
2
|
+
|
3
|
+
Takes a variable number of contracts. The contract passes if all of the
|
4
|
+
contracts pass.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
Contract C::And[Float, C::Neg] => String
|
8
|
+
```
|
9
|
+
|
10
|
+
This example will validate first argument of a method and accept only
|
11
|
+
negative `Float`.
|
12
|
+
|
13
|
+
Background:
|
14
|
+
Given a file named "and_usage.rb" with:
|
15
|
+
"""ruby
|
16
|
+
require "contracts"
|
17
|
+
C = Contracts
|
18
|
+
|
19
|
+
class Example
|
20
|
+
include Contracts::Core
|
21
|
+
|
22
|
+
Contract C::And[Float, C::Neg] => String
|
23
|
+
def fneg_string(number)
|
24
|
+
number.to_i.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: Accepts negative float
|
30
|
+
Given a file named "accepts_negative_float.rb" with:
|
31
|
+
"""ruby
|
32
|
+
require "./and_usage"
|
33
|
+
puts Example.new.fneg_string(-3.7)
|
34
|
+
"""
|
35
|
+
When I run `ruby accepts_negative_float.rb`
|
36
|
+
Then output should contain:
|
37
|
+
"""
|
38
|
+
-3
|
39
|
+
"""
|
40
|
+
|
41
|
+
Scenario: Rejects positive float
|
42
|
+
Given a file named "rejects_positive_float.rb" with:
|
43
|
+
"""ruby
|
44
|
+
require "./and_usage"
|
45
|
+
puts Example.new.fneg_string(7.5)
|
46
|
+
"""
|
47
|
+
When I run `ruby rejects_positive_float.rb`
|
48
|
+
Then output should contain:
|
49
|
+
"""
|
50
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
51
|
+
Expected: (Float and Neg),
|
52
|
+
Actual: 7.5
|
53
|
+
Value guarded in: Example::fneg_string
|
54
|
+
With Contract: And => String
|
55
|
+
"""
|
56
|
+
|
57
|
+
Scenario: Rejects negative integer
|
58
|
+
Given a file named "rejects_negative_integer.rb" with:
|
59
|
+
"""ruby
|
60
|
+
require "./and_usage"
|
61
|
+
puts Example.new.fneg_string(-5)
|
62
|
+
"""
|
63
|
+
When I run `ruby rejects_negative_integer.rb`
|
64
|
+
Then output should contain:
|
65
|
+
"""
|
66
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
67
|
+
Expected: (Float and Neg),
|
68
|
+
Actual: -5
|
69
|
+
Value guarded in: Example::fneg_string
|
70
|
+
With Contract: And => String
|
71
|
+
"""
|
72
|
+
|
73
|
+
Scenario: Rejects positive integer
|
74
|
+
Given a file named "rejects_positive_integer.rb" with:
|
75
|
+
"""ruby
|
76
|
+
require "./and_usage"
|
77
|
+
puts Example.new.fneg_string(5)
|
78
|
+
"""
|
79
|
+
When I run `ruby rejects_positive_integer.rb`
|
80
|
+
Then output should contain:
|
81
|
+
"""
|
82
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
83
|
+
Expected: (Float and Neg),
|
84
|
+
Actual: 5
|
85
|
+
Value guarded in: Example::fneg_string
|
86
|
+
With Contract: And => String
|
87
|
+
"""
|
88
|
+
|
89
|
+
Scenario: Rejects others
|
90
|
+
Given a file named "rejects_others.rb" with:
|
91
|
+
"""ruby
|
92
|
+
require "./and_usage"
|
93
|
+
puts Example.new.fneg_string(:foo)
|
94
|
+
"""
|
95
|
+
When I run `ruby rejects_others.rb`
|
96
|
+
Then output should contain:
|
97
|
+
"""
|
98
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
99
|
+
Expected: (Float and Neg),
|
100
|
+
Actual: :foo
|
101
|
+
Value guarded in: Example::fneg_string
|
102
|
+
With Contract: And => String
|
103
|
+
"""
|
@@ -0,0 +1,44 @@
|
|
1
|
+
Feature: Any
|
2
|
+
|
3
|
+
Passes for any argument.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
Contract C::Any => String
|
7
|
+
```
|
8
|
+
|
9
|
+
Scenario: Accepts any argument
|
10
|
+
Given a file named "any_usage.rb" with:
|
11
|
+
"""ruby
|
12
|
+
require "contracts"
|
13
|
+
C = Contracts
|
14
|
+
|
15
|
+
class Example
|
16
|
+
include Contracts::Core
|
17
|
+
|
18
|
+
Contract C::Any => String
|
19
|
+
def self.stringify(x)
|
20
|
+
x.inspect
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
puts Example.stringify(25)
|
25
|
+
puts Example.stringify(37.59)
|
26
|
+
puts Example.stringify("foo")
|
27
|
+
puts Example.stringify(:foo)
|
28
|
+
puts Example.stringify(nil)
|
29
|
+
puts Example.stringify(Object)
|
30
|
+
"""
|
31
|
+
When I run `ruby any_usage.rb`
|
32
|
+
Then output should contain:
|
33
|
+
"""
|
34
|
+
25
|
35
|
+
37.59
|
36
|
+
"foo"
|
37
|
+
:foo
|
38
|
+
nil
|
39
|
+
Object
|
40
|
+
"""
|
41
|
+
And output should not contain:
|
42
|
+
"""
|
43
|
+
Contract violation for
|
44
|
+
"""
|
@@ -0,0 +1,80 @@
|
|
1
|
+
Feature: Args
|
2
|
+
|
3
|
+
Used for `*args` (variadic functions). Takes contract and uses it to validate
|
4
|
+
every element passed in through `*args`.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
Contract C::Args[C::Num] => C::Bool
|
8
|
+
def example(*args)
|
9
|
+
```
|
10
|
+
|
11
|
+
This example contract will validate all arguments passed through `*args` to
|
12
|
+
accept only numbers.
|
13
|
+
|
14
|
+
Background:
|
15
|
+
Given a file named "args_usage.rb" with:
|
16
|
+
"""ruby
|
17
|
+
require "contracts"
|
18
|
+
C = Contracts
|
19
|
+
|
20
|
+
class Example
|
21
|
+
include Contracts::Core
|
22
|
+
|
23
|
+
Contract C::Args[C::Num] => C::Bool
|
24
|
+
def only_nums(*args)
|
25
|
+
args.inspect
|
26
|
+
end
|
27
|
+
end
|
28
|
+
"""
|
29
|
+
|
30
|
+
Scenario: Accepts no arguments
|
31
|
+
Given a file named "accepts_no_arguments.rb" with:
|
32
|
+
"""ruby
|
33
|
+
require "./args_usage"
|
34
|
+
puts Example.new.only_nums
|
35
|
+
"""
|
36
|
+
When I run `ruby accepts_no_arguments.rb`
|
37
|
+
Then the output should contain:
|
38
|
+
"""
|
39
|
+
[]
|
40
|
+
"""
|
41
|
+
|
42
|
+
Scenario: Accepts one valid argument
|
43
|
+
Given a file named "accepts_one_argument.rb" with:
|
44
|
+
"""ruby
|
45
|
+
require "./args_usage"
|
46
|
+
puts Example.new.only_nums(42)
|
47
|
+
"""
|
48
|
+
When I run `ruby accepts_one_argument.rb`
|
49
|
+
Then the output should contain:
|
50
|
+
"""
|
51
|
+
[42]
|
52
|
+
"""
|
53
|
+
|
54
|
+
Scenario: Accepts many valid arguments
|
55
|
+
Given a file named "accepts_many_arguments.rb" with:
|
56
|
+
"""ruby
|
57
|
+
require "./args_usage"
|
58
|
+
puts Example.new.only_nums(42, 45, 17, 24)
|
59
|
+
"""
|
60
|
+
When I run `ruby accepts_many_arguments.rb`
|
61
|
+
Then the output should contain:
|
62
|
+
"""
|
63
|
+
[42, 45, 17, 24]
|
64
|
+
"""
|
65
|
+
|
66
|
+
Scenario: Rejects invalid argument
|
67
|
+
Given a file named "rejects_invalid_argument.rb" with:
|
68
|
+
"""ruby
|
69
|
+
require "./args_usage"
|
70
|
+
puts Example.new.only_nums(42, "foo", 17, 24)
|
71
|
+
"""
|
72
|
+
When I run `ruby rejects_invalid_argument.rb`
|
73
|
+
Then the output should contain:
|
74
|
+
"""
|
75
|
+
: Contract violation for argument 1 of 4: (ParamContractError)
|
76
|
+
Expected: (Args[Contracts::Builtin::Num]),
|
77
|
+
Actual: "foo"
|
78
|
+
Value guarded in: Example::only_nums
|
79
|
+
With Contract: Args => Bool
|
80
|
+
"""
|
@@ -0,0 +1 @@
|
|
1
|
+
Feature: ArrayOf (TODO)
|