entitlements 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,64 @@
|
|
1
|
+
Feature: Num
|
2
|
+
|
3
|
+
Checks that an argument is `Numeric`.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
Contract C::Num => C::Num
|
7
|
+
```
|
8
|
+
|
9
|
+
Background:
|
10
|
+
Given a file named "num_usage.rb" with:
|
11
|
+
"""ruby
|
12
|
+
require "contracts"
|
13
|
+
C = Contracts
|
14
|
+
|
15
|
+
class Example
|
16
|
+
include Contracts::Core
|
17
|
+
|
18
|
+
Contract C::Num => C::Num
|
19
|
+
def increase(number)
|
20
|
+
number + 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
"""
|
24
|
+
|
25
|
+
Scenario: Accepts integers
|
26
|
+
Given a file named "accepts_integers.rb" with:
|
27
|
+
"""ruby
|
28
|
+
require "./num_usage"
|
29
|
+
puts Example.new.increase(7)
|
30
|
+
"""
|
31
|
+
When I run `ruby accepts_integers.rb`
|
32
|
+
Then output should contain:
|
33
|
+
"""
|
34
|
+
8
|
35
|
+
"""
|
36
|
+
|
37
|
+
Scenario: Accepts floats
|
38
|
+
Given a file named "accepts_floats.rb" with:
|
39
|
+
"""ruby
|
40
|
+
require "./num_usage"
|
41
|
+
puts Example.new.increase(7.5)
|
42
|
+
"""
|
43
|
+
When I run `ruby accepts_floats.rb`
|
44
|
+
Then output should contain:
|
45
|
+
"""
|
46
|
+
8.5
|
47
|
+
"""
|
48
|
+
|
49
|
+
Scenario: Rejects other values
|
50
|
+
Given a file named "rejects_others.rb" with:
|
51
|
+
"""ruby
|
52
|
+
require "./num_usage"
|
53
|
+
puts Example.new.increase("foo")
|
54
|
+
"""
|
55
|
+
When I run `ruby rejects_others.rb`
|
56
|
+
Then output should contain:
|
57
|
+
"""
|
58
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
59
|
+
Expected: Num,
|
60
|
+
Actual: "foo"
|
61
|
+
Value guarded in: Example::increase
|
62
|
+
With Contract: Num => Num
|
63
|
+
"""
|
64
|
+
And output should contain "num_usage.rb:8"
|
@@ -0,0 +1,83 @@
|
|
1
|
+
Feature: Or
|
2
|
+
|
3
|
+
Takes a variable number of contracts. The contract passes if any of the
|
4
|
+
contracts pass.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
Contract C::Or[Float, C::Nat] => String
|
8
|
+
```
|
9
|
+
|
10
|
+
This example will validate first argument of a method and accept either
|
11
|
+
`Float` or natural integer.
|
12
|
+
|
13
|
+
Background:
|
14
|
+
Given a file named "or_usage.rb" with:
|
15
|
+
"""ruby
|
16
|
+
require "contracts"
|
17
|
+
C = Contracts
|
18
|
+
|
19
|
+
class Example
|
20
|
+
include Contracts::Core
|
21
|
+
|
22
|
+
Contract C::Or[Float, C::Nat] => String
|
23
|
+
def nat_string(number)
|
24
|
+
number.to_i.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: Accepts float
|
30
|
+
Given a file named "accepts_float.rb" with:
|
31
|
+
"""ruby
|
32
|
+
require "./or_usage"
|
33
|
+
puts Example.new.nat_string(3.7)
|
34
|
+
"""
|
35
|
+
When I run `ruby accepts_float.rb`
|
36
|
+
Then output should contain:
|
37
|
+
"""
|
38
|
+
3
|
39
|
+
"""
|
40
|
+
|
41
|
+
Scenario: Accepts natural
|
42
|
+
Given a file named "accepts_natural.rb" with:
|
43
|
+
"""ruby
|
44
|
+
require "./or_usage"
|
45
|
+
puts Example.new.nat_string(7)
|
46
|
+
"""
|
47
|
+
When I run `ruby accepts_natural.rb`
|
48
|
+
Then output should contain:
|
49
|
+
"""
|
50
|
+
7
|
51
|
+
"""
|
52
|
+
|
53
|
+
Scenario: Rejects negative integer
|
54
|
+
Given a file named "rejects_negative_integer.rb" with:
|
55
|
+
"""ruby
|
56
|
+
require "./or_usage"
|
57
|
+
puts Example.new.nat_string(-3)
|
58
|
+
"""
|
59
|
+
When I run `ruby rejects_negative_integer.rb`
|
60
|
+
Then output should contain:
|
61
|
+
"""
|
62
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
63
|
+
Expected: (Float or Nat),
|
64
|
+
Actual: -3
|
65
|
+
Value guarded in: Example::nat_string
|
66
|
+
With Contract: Or => String
|
67
|
+
"""
|
68
|
+
|
69
|
+
Scenario: Rejects other values
|
70
|
+
Given a file named "rejects_other.rb" with:
|
71
|
+
"""ruby
|
72
|
+
require "./or_usage"
|
73
|
+
puts Example.new.nat_string(nil)
|
74
|
+
"""
|
75
|
+
When I run `ruby rejects_other.rb`
|
76
|
+
Then output should contain:
|
77
|
+
"""
|
78
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
79
|
+
Expected: (Float or Nat),
|
80
|
+
Actual: nil
|
81
|
+
Value guarded in: Example::nat_string
|
82
|
+
With Contract: Or => String
|
83
|
+
"""
|
@@ -0,0 +1,116 @@
|
|
1
|
+
Feature: Pos
|
2
|
+
|
3
|
+
Checks that an argument is positive `Numeric`.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
Contract C::Pos => C::Pos
|
7
|
+
```
|
8
|
+
|
9
|
+
Background:
|
10
|
+
Given a file named "pos_usage.rb" with:
|
11
|
+
"""ruby
|
12
|
+
require "contracts"
|
13
|
+
C = Contracts
|
14
|
+
|
15
|
+
class Example
|
16
|
+
include Contracts::Core
|
17
|
+
|
18
|
+
Contract C::Pos, C::Pos => C::Pos
|
19
|
+
def power(number, power)
|
20
|
+
return number if power <= 1
|
21
|
+
number * self.power(number, power - 1)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
"""
|
25
|
+
|
26
|
+
Scenario: Accepts positive integers
|
27
|
+
Given a file named "accepts_positive_integers.rb" with:
|
28
|
+
"""ruby
|
29
|
+
require "./pos_usage"
|
30
|
+
puts Example.new.power(3, 4)
|
31
|
+
"""
|
32
|
+
When I run `ruby accepts_positive_integers.rb`
|
33
|
+
Then output should contain:
|
34
|
+
"""
|
35
|
+
81
|
36
|
+
"""
|
37
|
+
|
38
|
+
Scenario: Accepts positive floats
|
39
|
+
Given a file named "accepts_positive_floats.rb" with:
|
40
|
+
"""ruby
|
41
|
+
require "./pos_usage"
|
42
|
+
puts Example.new.power(3.7, 4.5)
|
43
|
+
"""
|
44
|
+
When I run `ruby accepts_positive_floats.rb`
|
45
|
+
Then output should contain:
|
46
|
+
"""
|
47
|
+
693.4395
|
48
|
+
"""
|
49
|
+
|
50
|
+
Scenario: Rejects negative integers
|
51
|
+
Given a file named "rejects_negative_integers.rb" with:
|
52
|
+
"""ruby
|
53
|
+
require "./pos_usage"
|
54
|
+
puts Example.new.power(3, -4)
|
55
|
+
"""
|
56
|
+
When I run `ruby rejects_negative_integers.rb`
|
57
|
+
Then output should contain:
|
58
|
+
"""
|
59
|
+
: Contract violation for argument 2 of 2: (ParamContractError)
|
60
|
+
Expected: Pos,
|
61
|
+
Actual: -4
|
62
|
+
Value guarded in: Example::power
|
63
|
+
With Contract: Pos, Pos => Pos
|
64
|
+
"""
|
65
|
+
And output should contain "pos_usage.rb:8"
|
66
|
+
|
67
|
+
Scenario: Rejects negative floats
|
68
|
+
Given a file named "rejects_negative_floats.rb" with:
|
69
|
+
"""ruby
|
70
|
+
require "./pos_usage"
|
71
|
+
puts Example.new.power(3.7, -4.4)
|
72
|
+
"""
|
73
|
+
When I run `ruby rejects_negative_floats.rb`
|
74
|
+
Then output should contain:
|
75
|
+
"""
|
76
|
+
: Contract violation for argument 2 of 2: (ParamContractError)
|
77
|
+
Expected: Pos,
|
78
|
+
Actual: -4.4
|
79
|
+
Value guarded in: Example::power
|
80
|
+
With Contract: Pos, Pos => Pos
|
81
|
+
"""
|
82
|
+
And output should contain "pos_usage.rb:8"
|
83
|
+
|
84
|
+
Scenario: Rejects zero
|
85
|
+
Given a file named "rejects_zero.rb" with:
|
86
|
+
"""ruby
|
87
|
+
require "./pos_usage"
|
88
|
+
puts Example.new.power(3, 0)
|
89
|
+
"""
|
90
|
+
When I run `ruby rejects_zero.rb`
|
91
|
+
Then output should contain:
|
92
|
+
"""
|
93
|
+
: Contract violation for argument 2 of 2: (ParamContractError)
|
94
|
+
Expected: Pos,
|
95
|
+
Actual: 0
|
96
|
+
Value guarded in: Example::power
|
97
|
+
With Contract: Pos, Pos => Pos
|
98
|
+
"""
|
99
|
+
And output should contain "pos_usage.rb:8"
|
100
|
+
|
101
|
+
Scenario: Rejects other values
|
102
|
+
Given a file named "rejects_others.rb" with:
|
103
|
+
"""ruby
|
104
|
+
require "./pos_usage"
|
105
|
+
puts Example.new.power("foo", 2)
|
106
|
+
"""
|
107
|
+
When I run `ruby rejects_others.rb`
|
108
|
+
Then output should contain:
|
109
|
+
"""
|
110
|
+
: Contract violation for argument 1 of 2: (ParamContractError)
|
111
|
+
Expected: Pos,
|
112
|
+
Actual: "foo"
|
113
|
+
Value guarded in: Example::power
|
114
|
+
With Contract: Pos, Pos => Pos
|
115
|
+
"""
|
116
|
+
And output should contain "pos_usage.rb:8"
|
@@ -0,0 +1 @@
|
|
1
|
+
Feature: RangeOf (TODO)
|
@@ -0,0 +1,78 @@
|
|
1
|
+
Feature: RespondTo
|
2
|
+
|
3
|
+
Takes a variable number of method names as symbols. The contract passes if
|
4
|
+
the argument responds to all of those methods.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
Contract C::RespondTo[:email, :password, :confirmation] => C::Bool
|
8
|
+
```
|
9
|
+
|
10
|
+
This contract will pass only for objects that `respond_to?` `:email`,
|
11
|
+
`:password` and `:confirmation`.
|
12
|
+
|
13
|
+
Background:
|
14
|
+
Given a file named "signup_validator.rb" with:
|
15
|
+
"""ruby
|
16
|
+
require "contracts"
|
17
|
+
C = Contracts
|
18
|
+
|
19
|
+
class SignupValidator
|
20
|
+
include Contracts::Core
|
21
|
+
|
22
|
+
Contract C::RespondTo[:email, :password, :confirmation] => C::Bool
|
23
|
+
def valid?(signup)
|
24
|
+
!!signup.email.match("@") &&
|
25
|
+
signup.password.length > 6 &&
|
26
|
+
signup.password == signup.confirmation
|
27
|
+
end
|
28
|
+
end
|
29
|
+
"""
|
30
|
+
|
31
|
+
Given a file named "signup.rb" with:
|
32
|
+
"""ruby
|
33
|
+
Signup = Struct.new(:email, :password, :confirmation)
|
34
|
+
"""
|
35
|
+
|
36
|
+
Given a file named "signin.rb" with:
|
37
|
+
"""ruby
|
38
|
+
Signin = Struct.new(:email, :password)
|
39
|
+
"""
|
40
|
+
|
41
|
+
Given a file named "helper.rb" with:
|
42
|
+
"""ruby
|
43
|
+
require "./signup_validator"
|
44
|
+
require "./signup"
|
45
|
+
require "./signin"
|
46
|
+
"""
|
47
|
+
|
48
|
+
Scenario: Accepts correct object
|
49
|
+
Given a file named "correct.rb" with:
|
50
|
+
"""ruby
|
51
|
+
require "./helper"
|
52
|
+
|
53
|
+
puts SignupValidator.new.valid?(Signup["john@example.org", "welcome", "welcome"])
|
54
|
+
puts SignupValidator.new.valid?(Signup["john@example.org", "welcome", "welcomr"])
|
55
|
+
"""
|
56
|
+
When I run `ruby correct.rb`
|
57
|
+
Then output should contain:
|
58
|
+
"""
|
59
|
+
true
|
60
|
+
false
|
61
|
+
"""
|
62
|
+
|
63
|
+
Scenario: Rejects incorrect object
|
64
|
+
Given a file named "incorrect.rb" with:
|
65
|
+
"""ruby
|
66
|
+
require "./helper"
|
67
|
+
|
68
|
+
puts SignupValidator.new.valid?(Signin["john@example.org", "welcome"])
|
69
|
+
"""
|
70
|
+
When I run `ruby incorrect.rb`
|
71
|
+
Then output should contain:
|
72
|
+
"""
|
73
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
74
|
+
Expected: (a value that responds to [:email, :password, :confirmation]),
|
75
|
+
Actual: #<struct Signin email="john@example.org", password="welcome">
|
76
|
+
Value guarded in: SignupValidator::valid?
|
77
|
+
With Contract: RespondTo => Bool
|
78
|
+
"""
|
@@ -0,0 +1,147 @@
|
|
1
|
+
Feature: Send
|
2
|
+
|
3
|
+
Takes a variable number of method names as symbols. Given an argument, all of
|
4
|
+
those methods are called on the argument one by one. If they all return true,
|
5
|
+
the contract passes.
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
Contract C::Send[:valid?, :has_items?] => C::ArrayOf[Item]
|
9
|
+
```
|
10
|
+
|
11
|
+
This contract will pass only if:
|
12
|
+
`arg.valid? == true && arg.has_items? == true`,
|
13
|
+
where `arg` is the first argument.
|
14
|
+
|
15
|
+
Background:
|
16
|
+
Given a file named "item.rb" with:
|
17
|
+
"""ruby
|
18
|
+
Item = Struct.new(:name, :cost)
|
19
|
+
Item::DEFAULT = Item["default", 0]
|
20
|
+
"""
|
21
|
+
|
22
|
+
Given a file named "send_usage.rb" with:
|
23
|
+
"""ruby
|
24
|
+
require "contracts"
|
25
|
+
C = Contracts
|
26
|
+
require "./item"
|
27
|
+
|
28
|
+
class FetchItemCommand
|
29
|
+
include Contracts::Core
|
30
|
+
|
31
|
+
Contract C::Send[:valid?, :has_items?] => C::ArrayOf[Item]
|
32
|
+
def call(subject)
|
33
|
+
([Item::DEFAULT] + subject.items).uniq
|
34
|
+
end
|
35
|
+
end
|
36
|
+
"""
|
37
|
+
|
38
|
+
Scenario: All methods return `true`
|
39
|
+
Given a file named "box.rb" with:
|
40
|
+
"""ruby
|
41
|
+
class Box
|
42
|
+
def valid?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def has_items?
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
def items
|
51
|
+
[Item["cat", 599.99]]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
require "./send_usage"
|
56
|
+
p FetchItemCommand.new.call(Box.new)
|
57
|
+
"""
|
58
|
+
When I run `ruby box.rb`
|
59
|
+
Then output should contain:
|
60
|
+
"""
|
61
|
+
[#<struct Item name="default", cost=0>, #<struct Item name="cat", cost=599.99>]
|
62
|
+
"""
|
63
|
+
|
64
|
+
Scenario: When second method returns `false`
|
65
|
+
Given a file named "cat.rb" with:
|
66
|
+
"""ruby
|
67
|
+
class Cat
|
68
|
+
def valid?
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_items?
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
require "./send_usage"
|
78
|
+
p FetchItemCommand.new.call(Cat.new)
|
79
|
+
"""
|
80
|
+
When I run `ruby cat.rb`
|
81
|
+
Then output should contain:
|
82
|
+
"""
|
83
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
84
|
+
Expected: (a value that returns true for all of [:valid?, :has_items?]),
|
85
|
+
"""
|
86
|
+
And output should contain:
|
87
|
+
"""
|
88
|
+
Actual: #<Cat
|
89
|
+
"""
|
90
|
+
|
91
|
+
Scenario: When first method returns `false`
|
92
|
+
Given a file named "invalid.rb" with:
|
93
|
+
"""ruby
|
94
|
+
class Invalid
|
95
|
+
def valid?
|
96
|
+
false
|
97
|
+
end
|
98
|
+
|
99
|
+
def has_items?
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
def items
|
104
|
+
[]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
require "./send_usage"
|
109
|
+
p FetchItemCommand.new.call(Invalid.new)
|
110
|
+
"""
|
111
|
+
When I run `ruby invalid.rb`
|
112
|
+
Then output should contain:
|
113
|
+
"""
|
114
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
115
|
+
Expected: (a value that returns true for all of [:valid?, :has_items?]),
|
116
|
+
"""
|
117
|
+
And output should contain:
|
118
|
+
"""
|
119
|
+
Actual: #<Invalid
|
120
|
+
"""
|
121
|
+
|
122
|
+
Scenario: When all methods return `false`
|
123
|
+
Given a file named "nothing.rb" with:
|
124
|
+
"""ruby
|
125
|
+
class Nothing
|
126
|
+
def valid?
|
127
|
+
false
|
128
|
+
end
|
129
|
+
|
130
|
+
def has_items?
|
131
|
+
false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
require "./send_usage"
|
136
|
+
p FetchItemCommand.new.call(Nothing.new)
|
137
|
+
"""
|
138
|
+
When I run `ruby nothing.rb`
|
139
|
+
Then output should contain:
|
140
|
+
"""
|
141
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
142
|
+
Expected: (a value that returns true for all of [:valid?, :has_items?]),
|
143
|
+
"""
|
144
|
+
And output should contain:
|
145
|
+
"""
|
146
|
+
Actual: #<Nothing
|
147
|
+
"""
|
@@ -0,0 +1 @@
|
|
1
|
+
Feature: SetOf (TODO)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
Feature: Xor
|
2
|
+
|
3
|
+
Takes a variable number of contracts. The contract passes if one and only one
|
4
|
+
of the contracts pass.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
Contract C::Xor[Float, C::Neg] => String
|
8
|
+
```
|
9
|
+
|
10
|
+
This example will validate first argument of a method and accept either
|
11
|
+
`Float` or natural integer, but not both.
|
12
|
+
|
13
|
+
Background:
|
14
|
+
Given a file named "xor_usage.rb" with:
|
15
|
+
"""ruby
|
16
|
+
require "contracts"
|
17
|
+
C = Contracts
|
18
|
+
|
19
|
+
class Example
|
20
|
+
include Contracts::Core
|
21
|
+
|
22
|
+
Contract C::Xor[Float, C::Neg] => String
|
23
|
+
def strange_number(number)
|
24
|
+
number.to_i.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: Accepts float
|
30
|
+
Given a file named "accepts_float.rb" with:
|
31
|
+
"""ruby
|
32
|
+
require "./xor_usage"
|
33
|
+
puts Example.new.strange_number(3.7)
|
34
|
+
"""
|
35
|
+
When I run `ruby accepts_float.rb`
|
36
|
+
Then output should contain:
|
37
|
+
"""
|
38
|
+
3
|
39
|
+
"""
|
40
|
+
|
41
|
+
Scenario: Accepts negative integer
|
42
|
+
Given a file named "accepts_negative_integer.rb" with:
|
43
|
+
"""ruby
|
44
|
+
require "./xor_usage"
|
45
|
+
puts Example.new.strange_number(-7)
|
46
|
+
"""
|
47
|
+
When I run `ruby accepts_negative_integer.rb`
|
48
|
+
Then output should contain:
|
49
|
+
"""
|
50
|
+
-7
|
51
|
+
"""
|
52
|
+
|
53
|
+
Scenario: Rejects negative float
|
54
|
+
Given a file named "rejects_negative_float.rb" with:
|
55
|
+
"""ruby
|
56
|
+
require "./xor_usage"
|
57
|
+
puts Example.new.strange_number(-3.5)
|
58
|
+
"""
|
59
|
+
When I run `ruby rejects_negative_float.rb`
|
60
|
+
Then output should contain:
|
61
|
+
"""
|
62
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
63
|
+
Expected: (Float xor Neg),
|
64
|
+
Actual: -3.5
|
65
|
+
Value guarded in: Example::strange_number
|
66
|
+
With Contract: Xor => String
|
67
|
+
"""
|
68
|
+
|
69
|
+
Scenario: Rejects positive integer
|
70
|
+
Given a file named "rejects_positive_integer.rb" with:
|
71
|
+
"""ruby
|
72
|
+
require "./xor_usage"
|
73
|
+
puts Example.new.strange_number(9)
|
74
|
+
"""
|
75
|
+
When I run `ruby rejects_positive_integer.rb`
|
76
|
+
Then output should contain:
|
77
|
+
"""
|
78
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
79
|
+
Expected: (Float xor Neg),
|
80
|
+
Actual: 9
|
81
|
+
Value guarded in: Example::strange_number
|
82
|
+
With Contract: Xor => String
|
83
|
+
"""
|
84
|
+
|
85
|
+
Scenario: Rejects other values
|
86
|
+
Given a file named "rejects_other.rb" with:
|
87
|
+
"""ruby
|
88
|
+
require "./xor_usage"
|
89
|
+
puts Example.new.strange_number(:foo)
|
90
|
+
"""
|
91
|
+
When I run `ruby rejects_other.rb`
|
92
|
+
Then output should contain:
|
93
|
+
"""
|
94
|
+
: Contract violation for argument 1 of 1: (ParamContractError)
|
95
|
+
Expected: (Float xor Neg),
|
96
|
+
Actual: :foo
|
97
|
+
Value guarded in: Example::strange_number
|
98
|
+
With Contract: Xor => String
|
99
|
+
"""
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Contracts
|
2
|
+
module Attrs
|
3
|
+
def attr_reader_with_contract(*names, contract)
|
4
|
+
names.each do |name|
|
5
|
+
Contract Contracts::None => contract
|
6
|
+
attr_reader(name)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def attr_writer_with_contract(*names, contract)
|
11
|
+
names.each do |name|
|
12
|
+
Contract contract => contract
|
13
|
+
attr_writer(name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def attr_accessor_with_contract(*names, contract)
|
18
|
+
attr_reader_with_contract(*names, contract)
|
19
|
+
attr_writer_with_contract(*names, contract)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
include Attrs
|
24
|
+
end
|