entitlements 0.1.8 → 0.2.0
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.
- 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,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Contracts
|
|
4
|
+
module Attrs
|
|
5
|
+
def attr_reader_with_contract(*names, contract)
|
|
6
|
+
names.each do |name|
|
|
7
|
+
Contract Contracts::None => contract
|
|
8
|
+
attr_reader(name)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def attr_writer_with_contract(*names, contract)
|
|
13
|
+
names.each do |name|
|
|
14
|
+
Contract contract => contract
|
|
15
|
+
attr_writer(name)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def attr_accessor_with_contract(*names, contract)
|
|
20
|
+
attr_reader_with_contract(*names, contract)
|
|
21
|
+
attr_writer_with_contract(*names, contract)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
include Attrs
|
|
26
|
+
end
|