contracts 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,276 @@
1
+ include Contracts
2
+
3
+ class A
4
+
5
+ Contract Num => Num
6
+ def self.a_class_method x
7
+ x + 1
8
+ end
9
+
10
+ def good
11
+ true
12
+ end
13
+
14
+ Contract Num => Num
15
+ def triple x
16
+ x * 3
17
+ end
18
+
19
+ Contract Num => Num
20
+ def instance_and_class_method x
21
+ x * 2
22
+ end
23
+
24
+ Contract String => String
25
+ def self.instance_and_class_method x
26
+ x * 2
27
+ end
28
+ end
29
+
30
+ class B
31
+ def bad
32
+ false
33
+ end
34
+
35
+ Contract String => String
36
+ def triple x
37
+ x * 3
38
+ end
39
+ end
40
+
41
+ class C
42
+ def good
43
+ false
44
+ end
45
+ def bad
46
+ true
47
+ end
48
+ end
49
+
50
+ public # we need this otherwise all these methods will automatically be marked private
51
+ Contract Num => Num
52
+ def Object.a_class_method x
53
+ x + 1
54
+ end
55
+
56
+ Contract Num => nil
57
+ def bad_double(x)
58
+ x * 2
59
+ end
60
+
61
+ Contract Num => Num
62
+ def double(x)
63
+ x * 2
64
+ end
65
+
66
+ Contract String => nil
67
+ def hello(name)
68
+ end
69
+
70
+ Contract lambda { |x| x.is_a? Numeric } => Num
71
+ def square(x)
72
+ x ** 2
73
+ end
74
+
75
+ Contract [Num, Num, Num] => Num
76
+ def sum_three(vals)
77
+ vals.inject(0) do |acc, x|
78
+ acc + x
79
+ end
80
+ end
81
+
82
+ Contract ({:name => String, :age => Fixnum}) => nil
83
+ def person(data)
84
+ end
85
+
86
+ Contract Proc => Any
87
+ def do_call(&blk)
88
+ blk.call
89
+ end
90
+
91
+ Contract Args[Num] => Num
92
+ def sum(*vals)
93
+ vals.inject(0) do |acc, val|
94
+ acc + val
95
+ end
96
+ end
97
+
98
+ Contract Pos => nil
99
+ def pos_test(x)
100
+ end
101
+
102
+ Contract Neg => nil
103
+ def neg_test(x)
104
+ end
105
+
106
+ Contract Any => nil
107
+ def show(x)
108
+ end
109
+
110
+ Contract None => nil
111
+ def fail_all(x)
112
+ end
113
+
114
+ Contract Or[Num, String] => nil
115
+ def num_or_string(x)
116
+ end
117
+
118
+ Contract Xor[RespondTo[:good], RespondTo[:bad]] => nil
119
+ def xor_test(x)
120
+ end
121
+
122
+ Contract And[A, RespondTo[:good]] => nil
123
+ def and_test(x)
124
+ end
125
+
126
+ Contract RespondTo[:good] => nil
127
+ def responds_test(x)
128
+ end
129
+
130
+ Contract Send[:good] => nil
131
+ def send_test(x)
132
+ end
133
+
134
+ Contract Not[nil] => nil
135
+ def not_nil(x)
136
+ end
137
+
138
+ Contract ArrayOf[Num] => Num
139
+ def product(vals)
140
+ vals.inject(1) do |acc, x|
141
+ acc * x
142
+ end
143
+ end
144
+
145
+ Contract Bool => nil
146
+ def bool_test(x)
147
+ end
148
+
149
+ Contract nil => Num
150
+ def no_args
151
+ 1
152
+ end
153
+
154
+ Contract ArrayOf[Num], Func[Num => Num] => ArrayOf[Num]
155
+ def map(arr, func)
156
+ ret = []
157
+ arr.each do |x|
158
+ ret << func[x]
159
+ end
160
+ ret
161
+ end
162
+
163
+ Contract Num => Num
164
+ def default_args(x = 1)
165
+ 2
166
+ end
167
+
168
+ Contract Maybe[Num] => Maybe[Num]
169
+ def maybe_double x
170
+ if x.nil?
171
+ nil
172
+ else
173
+ x * 2
174
+ end
175
+ end
176
+
177
+ Contract HashOf[Symbol, Num] => Num
178
+ def gives_max_value(hash)
179
+ hash.values.max
180
+ end
181
+
182
+ Contract nil => String
183
+ def a_private_method
184
+ "works"
185
+ end
186
+ private :a_private_method
187
+
188
+ # for testing inheritance
189
+ class Parent
190
+ Contract Num => Num
191
+ def double x
192
+ x * 2
193
+ end
194
+ end
195
+
196
+ class Child < Parent
197
+ end
198
+
199
+ Contract Parent => Parent
200
+ def id_ a
201
+ a
202
+ end
203
+
204
+ Contract Exactly[Parent] => nil
205
+ def exactly_test(x)
206
+ end
207
+
208
+ # pattern matching example with possible deep contract violation
209
+ class PatternMatchingExample
210
+ class Success < Struct.new(:request)
211
+ end
212
+
213
+ class Failure
214
+ end
215
+
216
+ Response = Or[Success, Failure]
217
+
218
+ class StringWithHello
219
+ def self.valid?(string)
220
+ String === string && !!string.match(/hello/i)
221
+ end
222
+ end
223
+
224
+ Contract Success => Response
225
+ def process_request(status)
226
+ Success[decorated_request(status.request)]
227
+ end
228
+
229
+ Contract Failure => Response
230
+ def process_request(status)
231
+ Failure.new
232
+ end
233
+
234
+ Contract StringWithHello => String
235
+ def decorated_request(request)
236
+ request + "!"
237
+ end
238
+ end
239
+
240
+ # invariant example (silliest implementation ever)
241
+ class MyBirthday < Struct.new(:day, :month)
242
+ include Contracts
243
+ include Contracts::Invariants
244
+
245
+ Invariant(:day) { 1 <= day && day <= 31 }
246
+ Invariant(:month) { 1 <= month && month <= 12 }
247
+
248
+ Contract None => Fixnum
249
+ def silly_next_day!
250
+ self.day += 1
251
+ end
252
+
253
+ Contract None => Fixnum
254
+ def silly_next_month!
255
+ self.month += 1
256
+ end
257
+
258
+ Contract None => Fixnum
259
+ def clever_next_day!
260
+ return clever_next_month! if day == 31
261
+ self.day += 1
262
+ end
263
+
264
+ Contract None => Fixnum
265
+ def clever_next_month!
266
+ return next_year! if month == 12
267
+ self.month += 1
268
+ self.day = 1
269
+ end
270
+
271
+ Contract None => Fixnum
272
+ def next_year!
273
+ self.month = 1
274
+ self.day = 1
275
+ end
276
+ end
@@ -0,0 +1,19 @@
1
+ module Contracts
2
+ RSpec.describe Invariants do
3
+
4
+ def new_subject
5
+ MyBirthday.new(31, 12)
6
+ end
7
+
8
+ it "works when all invariants are holding" do
9
+ expect { new_subject.clever_next_day! }.not_to raise_error
10
+ expect { new_subject.clever_next_month! }.not_to raise_error
11
+ end
12
+
13
+ it "raises invariant violation error when any of invariants are not holding" do
14
+ expect { new_subject.silly_next_day! }.to raise_error(InvariantError, /day condition to be true/)
15
+ expect { new_subject.silly_next_month! }.to raise_error(InvariantError, /month condition to be true/)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Mod
2
+ include Contracts
3
+ Contract Num => Num
4
+ def self.a_module_method a
5
+ a + 1
6
+ end
7
+ end
8
+
9
+ RSpec.describe "module methods" do
10
+ it "should pass for correct input" do
11
+ expect { Mod.a_module_method(2) }.to_not raise_error
12
+ end
13
+
14
+ it "should fail for incorrect input" do
15
+ expect { Mod.a_module_method("bad") }.to raise_error
16
+ end
17
+ end
@@ -0,0 +1,94 @@
1
+ require "contracts"
2
+ require File.expand_path(File.join(__FILE__, "../fixtures/fixtures"))
3
+
4
+ # This file was generated by the `rspec --init` command. Conventionally, all
5
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
6
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
7
+ # file to always be loaded, without a need to explicitly require it in any files.
8
+ #
9
+ # Given that it is always loaded, you are encouraged to keep this file as
10
+ # light-weight as possible. Requiring heavyweight dependencies from this file
11
+ # will add to the boot time of your test suite on EVERY test run, even for an
12
+ # individual file that may not need all of that loaded. Instead, consider making
13
+ # a separate helper file that requires the additional dependencies and performs
14
+ # the additional setup, and require it from the spec files that actually need it.
15
+ #
16
+ # The `.rspec` file also contains a few flags that are not defaults but that
17
+ # users commonly want.
18
+ #
19
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
20
+ RSpec.configure do |config|
21
+ # rspec-expectations config goes here. You can use an alternate
22
+ # assertion/expectation library such as wrong or the stdlib/minitest
23
+ # assertions if you prefer.
24
+ config.expect_with :rspec do |expectations|
25
+ # This option will default to `true` in RSpec 4. It makes the `description`
26
+ # and `failure_message` of custom matchers include text for helper methods
27
+ # defined using `chain`, e.g.:
28
+ # be_bigger_than(2).and_smaller_than(4).description
29
+ # # => "be bigger than 2 and smaller than 4"
30
+ # ...rather than:
31
+ # # => "be bigger than 2"
32
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
33
+ end
34
+
35
+ # rspec-mocks config goes here. You can use an alternate test double
36
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
37
+ config.mock_with :rspec do |mocks|
38
+ # Prevents you from mocking or stubbing a method that does not exist on
39
+ # a real object. This is generally recommended, and will default to
40
+ # `true` in RSpec 4.
41
+ mocks.verify_partial_doubles = true
42
+ end
43
+
44
+ # These two settings work together to allow you to limit a spec run
45
+ # to individual examples or groups you care about by tagging them with
46
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
47
+ # get run.
48
+ config.filter_run :focus
49
+ config.run_all_when_everything_filtered = true
50
+
51
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
52
+ # For more details, see:
53
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
54
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
55
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
56
+ config.disable_monkey_patching!
57
+
58
+ # This setting enables warnings. It's recommended, but in some cases may
59
+ # be too noisy due to issues in dependencies.
60
+ #config.warnings = true
61
+
62
+ # Many RSpec users commonly either run the entire suite or an individual
63
+ # file, and it's useful to allow more verbose output when running an
64
+ # individual spec file.
65
+ if config.files_to_run.one?
66
+ # Use the documentation formatter for detailed output,
67
+ # unless a formatter has already been configured
68
+ # (e.g. via a command-line flag).
69
+ config.default_formatter = 'doc'
70
+ end
71
+
72
+ # Print the 10 slowest examples and example groups at the
73
+ # end of the spec run, to help surface which specs are running
74
+ # particularly slow.
75
+ config.profile_examples = 10
76
+
77
+ # Run specs in random order to surface order dependencies. If you find an
78
+ # order dependency and want to debug it, you can fix the order by providing
79
+ # the seed, which is printed after each run.
80
+ # --seed 1234
81
+ # Unable to use it now
82
+ config.order = :random
83
+
84
+ # Seed global randomization in this process using the `--seed` CLI option.
85
+ # Setting this allows you to use `--seed` to deterministically reproduce
86
+ # test failures related to randomization by passing the same `--seed` value
87
+ # as the one that triggered the failure.
88
+ Kernel.srand config.seed
89
+
90
+ # Callbacks
91
+ config.after :each do
92
+ ::Contract.restore_failure_callback
93
+ end
94
+ end
metadata CHANGED
@@ -1,67 +1,69 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: contracts
3
- version: !ruby/object:Gem::Version
4
- hash: 3
5
- prerelease:
6
- segments:
7
- - 0
8
- - 4
9
- version: "0.4"
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.5'
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Aditya Bhargava
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2014-05-08 00:00:00 Z
11
+ date: 2014-05-08 00:00:00.000000000 Z
18
12
  dependencies: []
19
-
20
- description: This library provides contracts for Ruby. Contracts let you clearly express how your code behaves, and free you from writing tons of boilerplate, defensive code.
13
+ description: This library provides contracts for Ruby. Contracts let you clearly express
14
+ how your code behaves, and free you from writing tons of boilerplate, defensive
15
+ code.
21
16
  email: bluemangroupie@gmail.com
22
17
  executables: []
23
-
24
18
  extensions: []
25
-
26
19
  extra_rdoc_files: []
27
-
28
- files:
29
- - lib/builtin_contracts.rb
20
+ files:
21
+ - ".gitignore"
22
+ - ".rspec"
23
+ - ".travis.yml"
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - README.md
27
+ - TODO.markdown
28
+ - TUTORIAL.md
29
+ - benchmarks/bench.rb
30
+ - benchmarks/invariants.rb
31
+ - benchmarks/wrap_test.rb
32
+ - contracts.gemspec
30
33
  - lib/contracts.rb
31
- - lib/decorators.rb
32
- - lib/testable.rb
34
+ - lib/contracts/builtin_contracts.rb
35
+ - lib/contracts/decorators.rb
36
+ - lib/contracts/invariants.rb
37
+ - lib/contracts/support.rb
38
+ - lib/contracts/testable.rb
39
+ - lib/contracts/version.rb
40
+ - spec/builtin_contracts_spec.rb
41
+ - spec/contracts_spec.rb
42
+ - spec/fixtures/fixtures.rb
43
+ - spec/invariants_spec.rb
44
+ - spec/module_spec.rb
45
+ - spec/spec_helper.rb
33
46
  homepage: http://github.com/egonSchiele/contracts.ruby
34
47
  licenses: []
35
-
48
+ metadata: {}
36
49
  post_install_message:
37
50
  rdoc_options: []
38
-
39
- require_paths:
51
+ require_paths:
40
52
  - lib
41
- required_ruby_version: !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
44
55
  - - ">="
45
- - !ruby/object:Gem::Version
46
- hash: 3
47
- segments:
48
- - 0
49
- version: "0"
50
- required_rubygems_version: !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
53
60
  - - ">="
54
- - !ruby/object:Gem::Version
55
- hash: 3
56
- segments:
57
- - 0
58
- version: "0"
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
59
63
  requirements: []
60
-
61
64
  rubyforge_project:
62
- rubygems_version: 1.8.25
65
+ rubygems_version: 2.2.2
63
66
  signing_key:
64
- specification_version: 3
67
+ specification_version: 4
65
68
  summary: Contracts for Ruby.
66
69
  test_files: []
67
-