hypothesis-specs 0.0.15 → 0.3.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/CHANGELOG.md +31 -0
- data/Cargo.toml +5 -3
- data/LICENSE.txt +1 -1
- data/README.markdown +1 -1
- data/Rakefile +4 -3
- data/lib/hypothesis.rb +46 -11
- data/lib/hypothesis/engine.rb +58 -34
- data/lib/hypothesis/errors.rb +33 -0
- data/lib/hypothesis/junkdrawer.rb +31 -0
- data/lib/hypothesis/possible.rb +7 -6
- data/src/lib.rs +408 -119
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77c742dcfc65dfcab8e0eac24498eff24b10461abf17f502961ac9fc30bd1810
|
4
|
+
data.tar.gz: 6a73fbe38f860e2b2b9f9fd68cde16a33657eb05d0117a3a2e78ab5dfa8e2226
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b0da0f3b0820c93b32af05eb040fd6d88e86748a8fd99c38609a204944a84b773f2e53bf757c103c0c0f5a6e66097fd65c839ca95c0ec8360c9ac1ae1814153
|
7
|
+
data.tar.gz: 0a2d28a1fbc0e3b87fa96452a6028d0f0f8e00d223eb1440f1daf86eb3e40ec33c25c21222c9a2fc585d053dcca63e9de6d9d0e96ca7eb277e452e0baa77c2ac
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
# Hypothesis for Ruby 0.3.0 (2021-01-08)
|
2
|
+
|
3
|
+
This release converts Hypothesis for Ruby to use [RuTie](https://github.com/danielpclark/rutie)
|
4
|
+
instead of the deprecated [Helix](https://github.com/tildeio/helix), restoring compatibility
|
5
|
+
with recent versions of Rust. Thanks to Alex Weisberger for taking this on!
|
6
|
+
|
7
|
+
# Hypothesis for Ruby 0.2.0 (2018-10-24)
|
8
|
+
|
9
|
+
This release adds an example database to Hypothesis for Ruby. This means that when a test fails,
|
10
|
+
it will automatically reuse the previously shown example when you rerun it, without having to
|
11
|
+
manually pass a seed.
|
12
|
+
|
13
|
+
# Hypothesis for Ruby 0.1.2 (2018-09-24)
|
14
|
+
|
15
|
+
This release makes the code useable via a direct require.
|
16
|
+
I.e. no need for rubygems or any special LOAD_PATH.
|
17
|
+
|
18
|
+
For example, if the base directory were in /opt, you'd just say:
|
19
|
+
require "/opt/hypothesis/hypothesis-ruby/lib/hypothesis"
|
20
|
+
|
21
|
+
# Hypothesis for Ruby 0.1.1 (2018-08-31)
|
22
|
+
|
23
|
+
This release fixes minor documentation issues.
|
24
|
+
|
25
|
+
Thanks to Tessa Bradbury for this contribution.
|
26
|
+
|
27
|
+
# Hypothesis for Ruby 0.1.0 (2018-07-16)
|
28
|
+
|
29
|
+
This release adds support for reporting multiple exceptions when Hypothesis
|
30
|
+
finds more than one way for the test to fail.
|
31
|
+
|
1
32
|
# Hypothesis for Ruby 0.0.15 (2018-06-25)
|
2
33
|
|
3
34
|
This release fixes an occasional `RuntimeError` that could occur
|
data/Cargo.toml
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
[package]
|
2
2
|
name = "hypothesis-ruby"
|
3
3
|
version = "0.1.0"
|
4
|
-
authors = ["David R. MacIver <david@drmaciver.com>"]
|
4
|
+
authors = ["David R. MacIver <david@drmaciver.com>", "Alex Wiesberger <alex.m.weisberger@gmail.com>"]
|
5
5
|
|
6
6
|
[lib]
|
7
|
+
name="hypothesis_ruby_core"
|
7
8
|
crate-type = ["cdylib"]
|
8
9
|
|
9
10
|
[dependencies]
|
10
|
-
|
11
|
+
rutie = {version="0.8.1"}
|
12
|
+
lazy_static = "1.4.0"
|
11
13
|
rand = '0.3'
|
12
|
-
conjecture = '0.
|
14
|
+
conjecture = '0.4.0'
|
data/LICENSE.txt
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Copyright (c) 2018, David R. MacIver
|
2
2
|
|
3
3
|
All code in this repository except where explicitly noted otherwise is released
|
4
|
-
under the Mozilla Public License v 2.0. You can obtain a copy at
|
4
|
+
under the Mozilla Public License v 2.0. You can obtain a copy at https://mozilla.org/MPL/2.0/.
|
5
5
|
|
6
6
|
Some code in this repository may come from other projects. Where applicable, the
|
7
7
|
original copyright and license are noted and any modifications made are released
|
data/README.markdown
CHANGED
@@ -32,7 +32,7 @@ RSpec.describe "removing an element from a list" do
|
|
32
32
|
|
33
33
|
values.delete_at(values.index(to_remove))
|
34
34
|
|
35
|
-
# Will fail if the value
|
35
|
+
# Will fail if the value was duplicated in the list.
|
36
36
|
expect(values.include?(to_remove)).to be false
|
37
37
|
|
38
38
|
end
|
data/Rakefile
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
require 'helix_runtime/build_task'
|
5
4
|
require 'date'
|
6
5
|
require 'open3'
|
7
6
|
|
7
|
+
task :build do
|
8
|
+
system('cargo build --release')
|
9
|
+
end
|
10
|
+
|
8
11
|
begin
|
9
12
|
require 'rspec/core/rake_task'
|
10
13
|
RSpec::Core::RakeTask.new(:spec)
|
@@ -20,8 +23,6 @@ begin
|
|
20
23
|
rescue LoadError
|
21
24
|
end
|
22
25
|
|
23
|
-
HelixRuntime::BuildTask.new
|
24
|
-
|
25
26
|
def rubocop(fix:)
|
26
27
|
sh "bundle exec rubocop #{'-a' if fix} lib spec minitests " \
|
27
28
|
'Rakefile hypothesis-specs.gemspec'
|
data/lib/hypothesis.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
require_relative 'hypothesis/junkdrawer'
|
4
|
+
require_relative 'hypothesis/errors'
|
5
|
+
require_relative 'hypothesis/possible'
|
6
|
+
require_relative 'hypothesis/testcase'
|
7
|
+
require_relative 'hypothesis/engine'
|
8
|
+
require_relative 'hypothesis/world'
|
8
9
|
|
9
10
|
# This is the main module for using Hypothesis.
|
10
11
|
# It is expected that you will include this in your
|
@@ -18,6 +19,23 @@ require 'hypothesis/world'
|
|
18
19
|
module Hypothesis
|
19
20
|
# @!visibility private
|
20
21
|
HYPOTHESIS_LOCATION = File.dirname(__FILE__)
|
22
|
+
# rubocop:disable ClassVars
|
23
|
+
@@setup_called = false
|
24
|
+
# rubocop:enable RuleByName
|
25
|
+
|
26
|
+
def self.setup_called
|
27
|
+
@@setup_called == true
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.included(*)
|
31
|
+
if setup_called == false
|
32
|
+
Rutie.new(:hypothesis_ruby_core).init(
|
33
|
+
'Init_rutie_hypothesis_core',
|
34
|
+
__dir__
|
35
|
+
)
|
36
|
+
end
|
37
|
+
@@setup_called = true
|
38
|
+
end
|
21
39
|
|
22
40
|
# @!visibility private
|
23
41
|
def hypothesis_stable_identifier
|
@@ -121,7 +139,7 @@ module Hypothesis
|
|
121
139
|
# of the block is a *test case*.
|
122
140
|
# A test case has three important features:
|
123
141
|
#
|
124
|
-
# * *givens* are the result of a call to self.
|
142
|
+
# * *givens* are the result of a call to self.any, and are the
|
125
143
|
# values that make up the test case. These might be values such
|
126
144
|
# as strings, integers, etc. or they might be values specific to
|
127
145
|
# your application such as a User object.
|
@@ -139,12 +157,21 @@ module Hypothesis
|
|
139
157
|
#
|
140
158
|
# A call to hypothesis does the following:
|
141
159
|
#
|
142
|
-
# 1. It tries to *
|
143
|
-
# 2. If
|
144
|
-
#
|
160
|
+
# 1. It first tries to *reuse* failing test cases for previous runs.
|
161
|
+
# 2. If there were no previous failing test cases then it tries to
|
162
|
+
# *generate* new failing test cases.
|
163
|
+
# 3. If either of the first two phases found failing test cases then
|
164
|
+
# it will *shrink* those failing test cases.
|
165
|
+
# 4. Finally, it will *display* the shrunk failing test case by
|
145
166
|
# the error from its failing assertion, modified to show the
|
146
167
|
# givens of the test case.
|
147
168
|
#
|
169
|
+
# Reuse uses an internal representation of the test case, so examples
|
170
|
+
# from previous runs will obey all of the usual invariants of generation.
|
171
|
+
# However, this means that if you change your test then reuse may not
|
172
|
+
# work. Test cases that have become invalid or passing will be cleaned
|
173
|
+
# up automatically.
|
174
|
+
#
|
148
175
|
# Generation consists of randomly trying test cases until one of
|
149
176
|
# three things has happened:
|
150
177
|
#
|
@@ -169,13 +196,21 @@ module Hypothesis
|
|
169
196
|
#
|
170
197
|
# @param max_valid_test_cases [Integer] The maximum number of valid test
|
171
198
|
# cases to run without finding a failing test case before stopping.
|
172
|
-
|
199
|
+
#
|
200
|
+
# @param database [String, nil, false] A path to a directory where Hypothesis
|
201
|
+
# should store previously failing test cases. If it is nil, Hypothesis
|
202
|
+
# will use a default of .hypothesis/examples in the current directory.
|
203
|
+
# May also be set to false to disable the database functionality.
|
204
|
+
def hypothesis(max_valid_test_cases: 200, database: nil, &block)
|
173
205
|
unless World.current_engine.nil?
|
174
206
|
raise UsageError, 'Cannot nest hypothesis calls'
|
175
207
|
end
|
208
|
+
|
176
209
|
begin
|
177
210
|
World.current_engine = Engine.new(
|
178
|
-
|
211
|
+
hypothesis_stable_identifier,
|
212
|
+
max_examples: max_valid_test_cases,
|
213
|
+
database: database
|
179
214
|
)
|
180
215
|
World.current_engine.run(&block)
|
181
216
|
ensure
|
data/lib/hypothesis/engine.rb
CHANGED
@@ -1,18 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
3
|
+
require 'rutie'
|
4
|
+
|
5
|
+
require 'rspec/expectations'
|
5
6
|
|
6
7
|
module Hypothesis
|
8
|
+
DEFAULT_DATABASE_PATH = File.join(Dir.pwd, '.hypothesis', 'examples')
|
9
|
+
|
7
10
|
class Engine
|
11
|
+
include RSpec::Matchers
|
12
|
+
|
8
13
|
attr_reader :current_source
|
9
14
|
attr_accessor :is_find
|
10
15
|
|
11
|
-
def initialize(options)
|
16
|
+
def initialize(name, options)
|
12
17
|
seed = Random.rand(2**64 - 1)
|
18
|
+
|
19
|
+
database = options.fetch(:database, nil)
|
20
|
+
|
21
|
+
database = DEFAULT_DATABASE_PATH if database.nil?
|
22
|
+
|
23
|
+
database = nil if database == false
|
24
|
+
|
13
25
|
@core_engine = HypothesisCoreEngine.new(
|
14
|
-
seed, options.fetch(:max_examples)
|
26
|
+
name, database, seed, options.fetch(:max_examples)
|
15
27
|
)
|
28
|
+
|
29
|
+
@exceptions_to_tags = Hash.new { |h, k| h[k] = h.size }
|
16
30
|
end
|
17
31
|
|
18
32
|
def run
|
@@ -23,7 +37,7 @@ module Hypothesis
|
|
23
37
|
begin
|
24
38
|
result = yield(@current_source)
|
25
39
|
if is_find && result
|
26
|
-
@core_engine.finish_interesting(core)
|
40
|
+
@core_engine.finish_interesting(core, 0)
|
27
41
|
else
|
28
42
|
@core_engine.finish_valid(core)
|
29
43
|
end
|
@@ -31,54 +45,64 @@ module Hypothesis
|
|
31
45
|
@core_engine.finish_invalid(core)
|
32
46
|
rescue DataOverflow
|
33
47
|
@core_engine.finish_overflow(core)
|
34
|
-
rescue Exception
|
48
|
+
rescue Exception => e
|
35
49
|
raise if is_find
|
36
|
-
|
50
|
+
key = [
|
51
|
+
e.class,
|
52
|
+
HypothesisJunkDrawer.find_first_relevant_line(e.backtrace)
|
53
|
+
]
|
54
|
+
@core_engine.finish_interesting(core, @exceptions_to_tags[key])
|
37
55
|
end
|
38
56
|
end
|
39
|
-
@
|
40
|
-
core = @core_engine.failing_example
|
41
|
-
if core.nil?
|
57
|
+
if @core_engine.count_failing_examples.zero?
|
42
58
|
raise Unsatisfiable if @core_engine.was_unsatisfiable
|
59
|
+
@current_source = nil
|
43
60
|
return
|
44
61
|
end
|
45
62
|
|
46
63
|
if is_find
|
64
|
+
core = @core_engine.failing_example(0)
|
47
65
|
@current_source = TestCase.new(core, record_draws: true)
|
48
66
|
yield @current_source
|
49
67
|
else
|
50
|
-
|
68
|
+
exceptions = []
|
69
|
+
(0...@core_engine.count_failing_examples).each do |example|
|
70
|
+
core = @core_engine.failing_example(example)
|
71
|
+
@current_source = TestCase.new(core, print_draws: true)
|
51
72
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
if e.respond_to? :hypothesis_data
|
62
|
-
e.hypothesis_data[0] = given_str
|
63
|
-
else
|
64
|
-
original_to_s = e.to_s
|
65
|
-
original_inspect = e.inspect
|
73
|
+
begin
|
74
|
+
yield @current_source
|
75
|
+
rescue Exception => e
|
76
|
+
givens = @current_source.print_log
|
77
|
+
given_str = givens.each_with_index.map do |(name, s), i|
|
78
|
+
name = "##{i + 1}" if name.nil?
|
79
|
+
"Given #{name}: #{s}"
|
80
|
+
end.to_a
|
66
81
|
|
67
|
-
|
68
|
-
|
82
|
+
if e.respond_to? :hypothesis_data
|
83
|
+
e.hypothesis_data[0] = given_str
|
84
|
+
else
|
85
|
+
original_to_s = e.to_s
|
86
|
+
original_inspect = e.inspect
|
69
87
|
|
70
|
-
|
71
|
-
|
72
|
-
|
88
|
+
class <<e
|
89
|
+
attr_accessor :hypothesis_data
|
90
|
+
|
91
|
+
def to_s
|
92
|
+
['', hypothesis_data[0], '', hypothesis_data[1]].join("\n")
|
93
|
+
end
|
73
94
|
|
74
|
-
|
75
|
-
|
95
|
+
def inspect
|
96
|
+
['', hypothesis_data[0], '', hypothesis_data[2]].join("\n")
|
97
|
+
end
|
76
98
|
end
|
99
|
+
e.hypothesis_data = [given_str, original_to_s, original_inspect]
|
77
100
|
end
|
78
|
-
e
|
101
|
+
raise e if @core_engine.count_failing_examples == 1
|
102
|
+
exceptions.push(e)
|
79
103
|
end
|
80
|
-
raise e
|
81
104
|
end
|
105
|
+
raise Hypothesis::MultipleExceptionError.new(*exceptions)
|
82
106
|
end
|
83
107
|
end
|
84
108
|
end
|
data/lib/hypothesis/errors.rb
CHANGED
@@ -25,4 +25,37 @@ module Hypothesis
|
|
25
25
|
# @!visibility private
|
26
26
|
class DataOverflow < HypothesisError
|
27
27
|
end
|
28
|
+
|
29
|
+
if defined?(RSpec::Core::MultipleExceptionError)
|
30
|
+
MultipleExceptionErrorParent = RSpec::Core::MultipleExceptionError
|
31
|
+
# :nocov:
|
32
|
+
else
|
33
|
+
class MultipleExceptionErrorParent < StandardError
|
34
|
+
def initialize(*exceptions)
|
35
|
+
super()
|
36
|
+
|
37
|
+
@all_exceptions = exceptions.to_a
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :all_exceptions
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class MultipleExceptionError < MultipleExceptionErrorParent
|
45
|
+
def message
|
46
|
+
jd = HypothesisJunkDrawer
|
47
|
+
"Test raised #{all_exceptions.length} distinct errors:\n\n" +
|
48
|
+
all_exceptions.map do |e|
|
49
|
+
location = jd.find_first_relevant_line(e.backtrace).sub(/:in.+$/, '')
|
50
|
+
backtrace = jd.prune_backtrace(e.backtrace)
|
51
|
+
"#{e.class} at #{location}:\n" \
|
52
|
+
"#{e.message}\n#{backtrace.map { |s| ' ' + s }
|
53
|
+
.join("\n")}"
|
54
|
+
end.join("\n\n")
|
55
|
+
end
|
56
|
+
|
57
|
+
def backtrace
|
58
|
+
[]
|
59
|
+
end
|
60
|
+
end
|
28
61
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hypothesis
|
4
|
+
# @!visibility private
|
5
|
+
module HypothesisJunkDrawer
|
6
|
+
HYPOTHESIS_ROOT = File.absolute_path(File.dirname(__FILE__))
|
7
|
+
|
8
|
+
def self.prune_backtrace(backtrace)
|
9
|
+
result = []
|
10
|
+
seen_hypothesis = false
|
11
|
+
backtrace.each do |b|
|
12
|
+
if b.start_with?(HYPOTHESIS_ROOT)
|
13
|
+
seen_hypothesis = true
|
14
|
+
else
|
15
|
+
result.push(b)
|
16
|
+
break if seen_hypothesis
|
17
|
+
end
|
18
|
+
end
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.find_first_relevant_line(backtrace)
|
23
|
+
backtrace.each do |b|
|
24
|
+
next if b.include?('minitest/assertions.rb')
|
25
|
+
next if b.start_with?(HYPOTHESIS_ROOT)
|
26
|
+
return b
|
27
|
+
end
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/hypothesis/possible.rb
CHANGED
@@ -111,7 +111,7 @@ module Hypothesis
|
|
111
111
|
# two names: A singular and a plural name. These are
|
112
112
|
# simply aliases and are identical in every way, but are
|
113
113
|
# provided to improve readability. For example
|
114
|
-
# `any integer` reads better than `
|
114
|
+
# `any integer` reads better than `any integers`
|
115
115
|
# but `arrays(of: integers)` reads better than
|
116
116
|
# `arrays(of: integer)`.
|
117
117
|
module Possibilities
|
@@ -124,7 +124,7 @@ module Hypothesis
|
|
124
124
|
# built_as lets you chain multiple Possible values together,
|
125
125
|
# by providing whatever value results from its block.
|
126
126
|
#
|
127
|
-
# For example the following provides
|
127
|
+
# For example the following provides an array plus some
|
128
128
|
# element from that array:
|
129
129
|
#
|
130
130
|
# ```ruby
|
@@ -135,6 +135,7 @@ module Hypothesis
|
|
135
135
|
# assume ls.size > 0
|
136
136
|
# i = any element_of(ls)
|
137
137
|
# [ls, i]
|
138
|
+
# end
|
138
139
|
# ```
|
139
140
|
#
|
140
141
|
# @return [Possible] A Possible whose possible values are
|
@@ -177,7 +178,7 @@ module Hypothesis
|
|
177
178
|
# valid.
|
178
179
|
# @param min_size [Integer] The smallest valid length for a
|
179
180
|
# provided string
|
180
|
-
# @param max_size [Integer] The
|
181
|
+
# @param max_size [Integer] The largest valid length for a
|
181
182
|
# provided string
|
182
183
|
def strings(codepoints: nil, min_size: 0, max_size: 10)
|
183
184
|
codepoints = self.codepoints if codepoints.nil?
|
@@ -263,9 +264,9 @@ module Hypothesis
|
|
263
264
|
alias array_of_shape arrays_of_shape
|
264
265
|
|
265
266
|
# A Possible Array of variable shape.
|
266
|
-
# This is used for arrays where
|
267
|
-
#
|
268
|
-
# For example, arrays(booleans) might provide [false, true, false].
|
267
|
+
# This is used for arrays where the size may vary and the same values
|
268
|
+
# are possible at any position.
|
269
|
+
# For example, arrays(of: booleans) might provide [false, true, false].
|
269
270
|
# @return [Possible]
|
270
271
|
# @param of [Possible] The possible elements of the array.
|
271
272
|
# @param min_size [Integer] The smallest valid size of a provided array
|
data/src/lib.rs
CHANGED
@@ -1,180 +1,469 @@
|
|
1
|
-
// "Bridging" root code that exists exclusively to provide
|
2
|
-
// a ruby -> Hypothesis engine binding. Long term the code
|
3
|
-
// in here is the only code that is going to stay in this
|
4
|
-
// crate, and everything else is going to get factored out
|
5
|
-
// into its own.
|
6
|
-
|
7
|
-
#![recursion_limit = "256"]
|
8
|
-
#![deny(warnings, missing_debug_implementations)]
|
9
|
-
|
10
|
-
extern crate core;
|
11
1
|
#[macro_use]
|
12
|
-
extern crate
|
13
|
-
|
2
|
+
extern crate rutie;
|
3
|
+
#[macro_use]
|
4
|
+
extern crate lazy_static;
|
14
5
|
extern crate conjecture;
|
15
6
|
|
16
7
|
use std::mem;
|
17
8
|
|
18
|
-
use
|
19
|
-
|
9
|
+
use rutie::{AnyException, AnyObject, Boolean, Class, Float, Integer, NilClass, Object, RString, VM};
|
10
|
+
|
11
|
+
use conjecture::data::{DataSource, Status, TestResult};
|
12
|
+
use conjecture::database::{BoxedDatabase, DirectoryDatabase, NoDatabase};
|
20
13
|
use conjecture::distributions;
|
14
|
+
use conjecture::distributions::Repeat;
|
21
15
|
use conjecture::engine::Engine;
|
22
16
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
pub struct HypothesisCoreDataSourceStruct {
|
18
|
+
source: Option<DataSource>,
|
19
|
+
}
|
20
|
+
|
21
|
+
impl HypothesisCoreDataSourceStruct {
|
22
|
+
fn new(engine: &mut HypothesisCoreEngineStruct) -> HypothesisCoreDataSourceStruct {
|
23
|
+
HypothesisCoreDataSourceStruct {
|
24
|
+
source: mem::take(&mut engine.pending),
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
fn start_draw(&mut self) {
|
29
|
+
if let Some(ref mut source) = self.source {
|
30
|
+
source.start_draw();
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
fn stop_draw(&mut self) {
|
35
|
+
if let Some(ref mut source) = self.source {
|
36
|
+
source.stop_draw();
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
wrappable_struct!(
|
42
|
+
HypothesisCoreDataSourceStruct,
|
43
|
+
HypothesisCoreDataSourceStructWrapper,
|
44
|
+
HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER
|
45
|
+
);
|
46
|
+
|
47
|
+
class!(HypothesisCoreDataSource);
|
48
|
+
|
49
|
+
methods!(
|
50
|
+
HypothesisCoreDataSource,
|
51
|
+
itself,
|
52
|
+
fn ruby_hypothesis_core_data_source_start_draw() -> NilClass {
|
53
|
+
itself
|
54
|
+
.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER)
|
55
|
+
.start_draw();
|
56
|
+
|
57
|
+
NilClass::new()
|
27
58
|
}
|
59
|
+
fn ruby_hypothesis_core_data_source_stop_draw() -> NilClass {
|
60
|
+
itself
|
61
|
+
.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER)
|
62
|
+
.stop_draw();
|
28
63
|
|
29
|
-
|
30
|
-
let mut result = HypothesisCoreDataSource{helix, source: None};
|
31
|
-
mem::swap(&mut result.source, &mut engine.pending);
|
32
|
-
return result;
|
64
|
+
NilClass::new()
|
33
65
|
}
|
66
|
+
);
|
34
67
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
68
|
+
pub struct HypothesisCoreEngineStruct {
|
69
|
+
engine: Engine,
|
70
|
+
pending: Option<DataSource>,
|
71
|
+
interesting_examples: Vec<TestResult>,
|
72
|
+
}
|
73
|
+
|
74
|
+
impl HypothesisCoreEngineStruct {
|
75
|
+
fn new(
|
76
|
+
name: String,
|
77
|
+
database_path: Option<String>,
|
78
|
+
seed: u64,
|
79
|
+
max_examples: u64,
|
80
|
+
) -> HypothesisCoreEngineStruct {
|
81
|
+
let xs: [u32; 2] = [seed as u32, (seed >> 32) as u32];
|
82
|
+
let db: BoxedDatabase = match database_path {
|
83
|
+
None => Box::new(NoDatabase),
|
84
|
+
Some(path) => Box::new(DirectoryDatabase::new(path)),
|
85
|
+
};
|
86
|
+
|
87
|
+
HypothesisCoreEngineStruct {
|
88
|
+
engine: Engine::new(name, max_examples, &xs, db),
|
89
|
+
pending: None,
|
90
|
+
interesting_examples: Vec::new(),
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
fn new_source(&mut self) -> Option<HypothesisCoreDataSourceStruct> {
|
95
|
+
match self.engine.next_source() {
|
96
|
+
None => {
|
97
|
+
self.interesting_examples = self.engine.list_minimized_examples();
|
98
|
+
None
|
99
|
+
}
|
100
|
+
Some(source) => {
|
101
|
+
self.pending = Some(source);
|
102
|
+
Some(HypothesisCoreDataSourceStruct::new(self))
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
fn count_failing_examples(&self) -> usize {
|
108
|
+
self.interesting_examples.len()
|
109
|
+
}
|
110
|
+
|
111
|
+
fn failing_example(&mut self, i: usize) -> HypothesisCoreDataSourceStruct {
|
112
|
+
self.pending = Some(DataSource::from_vec(
|
113
|
+
self.interesting_examples[i].record.clone(),
|
114
|
+
));
|
115
|
+
HypothesisCoreDataSourceStruct::new(self)
|
39
116
|
}
|
40
117
|
|
41
|
-
|
42
|
-
|
43
|
-
source.stop_draw();
|
44
|
-
}
|
118
|
+
fn was_unsatisfiable(&mut self) -> bool {
|
119
|
+
self.engine.was_unsatisfiable()
|
45
120
|
}
|
46
|
-
}
|
47
121
|
|
48
|
-
|
49
|
-
|
50
|
-
engine: Engine,
|
51
|
-
pending: Option<DataSource>,
|
122
|
+
fn finish_overflow(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
|
123
|
+
mark_child_status(&mut self.engine, child, Status::Overflow);
|
52
124
|
}
|
53
125
|
|
54
|
-
|
55
|
-
|
56
|
-
HypothesisCoreEngine{
|
57
|
-
helix,
|
58
|
-
engine: Engine::new(max_examples, &xs),
|
59
|
-
pending: None,
|
60
|
-
}
|
126
|
+
fn finish_valid(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
|
127
|
+
mark_child_status(&mut self.engine, child, Status::Valid);
|
61
128
|
}
|
62
129
|
|
63
|
-
|
64
|
-
|
65
|
-
None => None,
|
66
|
-
Some(source) => {
|
67
|
-
self.pending = Some(source);
|
68
|
-
Some(HypothesisCoreDataSource::new(self))
|
69
|
-
},
|
70
|
-
}
|
130
|
+
fn finish_invalid(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
|
131
|
+
mark_child_status(&mut self.engine, child, Status::Invalid);
|
71
132
|
}
|
72
133
|
|
73
|
-
|
74
|
-
|
75
|
-
self.pending = Some(source);
|
76
|
-
return Some(HypothesisCoreDataSource::new(self));
|
77
|
-
} else {
|
78
|
-
return None;
|
79
|
-
}
|
134
|
+
fn finish_interesting(&mut self, child: &mut HypothesisCoreDataSourceStruct, label: u64) {
|
135
|
+
mark_child_status(&mut self.engine, child, Status::Interesting(label));
|
80
136
|
}
|
137
|
+
}
|
138
|
+
|
139
|
+
wrappable_struct!(
|
140
|
+
HypothesisCoreEngineStruct,
|
141
|
+
HypothesisCoreEngineStructWrapper,
|
142
|
+
HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER
|
143
|
+
);
|
144
|
+
|
145
|
+
class!(HypothesisCoreEngine);
|
81
146
|
|
82
|
-
|
83
|
-
|
147
|
+
methods!(
|
148
|
+
HypothesisCoreEngine,
|
149
|
+
itself,
|
150
|
+
fn ruby_hypothesis_core_engine_new(
|
151
|
+
name: RString,
|
152
|
+
database_path: RString,
|
153
|
+
seed: Integer,
|
154
|
+
max_example: Integer
|
155
|
+
) -> AnyObject {
|
156
|
+
let core_engine = HypothesisCoreEngineStruct::new(
|
157
|
+
safe_access(name).to_string(),
|
158
|
+
database_path.ok().map(|p| p.to_string()),
|
159
|
+
safe_access(seed).to_u64(),
|
160
|
+
safe_access(max_example).to_u64(),
|
161
|
+
);
|
162
|
+
|
163
|
+
Class::from_existing("HypothesisCoreEngine")
|
164
|
+
.wrap_data(core_engine, &*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER)
|
165
|
+
}
|
166
|
+
fn ruby_hypothesis_core_engine_new_source() -> AnyObject {
|
167
|
+
match itself
|
168
|
+
.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER)
|
169
|
+
.new_source()
|
170
|
+
{
|
171
|
+
Some(ds) => Class::from_existing("HypothesisCoreDataSource")
|
172
|
+
.wrap_data(ds, &*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER),
|
173
|
+
None => NilClass::new().into(),
|
174
|
+
}
|
84
175
|
}
|
176
|
+
fn ruby_hypothesis_core_engine_finish_overflow(child: AnyObject) -> NilClass {
|
177
|
+
let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
178
|
+
let mut rdata_source = safe_access(child);
|
179
|
+
let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
|
180
|
+
|
181
|
+
core_engine.finish_overflow(data_source);
|
182
|
+
|
183
|
+
NilClass::new()
|
184
|
+
}
|
185
|
+
fn ruby_hypothesis_core_engine_finish_valid(child: AnyObject) -> NilClass {
|
186
|
+
let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
187
|
+
let mut rdata_source = safe_access(child);
|
188
|
+
let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
|
189
|
+
|
190
|
+
core_engine.finish_valid(data_source);
|
85
191
|
|
86
|
-
|
87
|
-
mark_child_status(&mut self.engine, child, Status::Overflow);
|
192
|
+
NilClass::new()
|
88
193
|
}
|
194
|
+
fn ruby_hypothesis_core_engine_finish_invalid(child: AnyObject) -> NilClass {
|
195
|
+
let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
196
|
+
let mut rdata_source = safe_access(child);
|
197
|
+
let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
|
89
198
|
|
90
|
-
|
91
|
-
|
199
|
+
core_engine.finish_invalid(data_source);
|
200
|
+
|
201
|
+
NilClass::new()
|
92
202
|
}
|
203
|
+
fn ruby_hypothesis_core_engine_finish_interesting(
|
204
|
+
child: AnyObject,
|
205
|
+
label: Integer
|
206
|
+
) -> NilClass {
|
207
|
+
let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
208
|
+
let mut rdata_source = safe_access(child);
|
209
|
+
let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
|
210
|
+
|
211
|
+
core_engine.finish_interesting(data_source, safe_access(label).to_u64());
|
93
212
|
|
94
|
-
|
95
|
-
mark_child_status(&mut self.engine, child, Status::Interesting);
|
213
|
+
NilClass::new()
|
96
214
|
}
|
215
|
+
fn ruby_hypothesis_core_engine_count_failing_examples() -> Integer {
|
216
|
+
let core_engine = itself.get_data(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
97
217
|
|
98
|
-
|
99
|
-
mark_child_status(&mut self.engine, child, Status::Valid);
|
218
|
+
Integer::new(core_engine.count_failing_examples() as i64)
|
100
219
|
}
|
101
|
-
|
220
|
+
fn ruby_hypothesis_core_failing_example(i: Integer) -> AnyObject {
|
221
|
+
let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
222
|
+
let int = safe_access(i).to_u64() as usize;
|
223
|
+
|
224
|
+
let data_source = core_engine.failing_example(int);
|
102
225
|
|
103
|
-
|
104
|
-
|
105
|
-
n_bits: u64,
|
226
|
+
Class::from_existing("HypothesisCoreDataSource")
|
227
|
+
.wrap_data(data_source, &*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER)
|
106
228
|
}
|
229
|
+
fn ruby_hypothesis_core_engine_was_unsatisfiable() -> Boolean {
|
230
|
+
let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
107
231
|
|
108
|
-
|
109
|
-
return HypothesisCoreBitPossible{helix, n_bits: n_bits};
|
232
|
+
Boolean::new(core_engine.was_unsatisfiable())
|
110
233
|
}
|
234
|
+
);
|
235
|
+
|
236
|
+
pub struct HypothesisCoreIntegersStruct {
|
237
|
+
bitlengths: distributions::Sampler,
|
238
|
+
}
|
111
239
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
240
|
+
impl HypothesisCoreIntegersStruct {
|
241
|
+
fn new() -> HypothesisCoreIntegersStruct {
|
242
|
+
HypothesisCoreIntegersStruct {
|
243
|
+
bitlengths: distributions::good_bitlengths(),
|
244
|
+
}
|
117
245
|
}
|
118
|
-
}
|
119
246
|
|
120
|
-
|
121
|
-
|
122
|
-
|
247
|
+
fn provide(&mut self, data: &mut HypothesisCoreDataSourceStruct) -> Option<i64> {
|
248
|
+
data.source.as_mut().and_then(|ref mut source| {
|
249
|
+
distributions::integer_from_bitlengths(source, &self.bitlengths).ok()
|
250
|
+
})
|
123
251
|
}
|
252
|
+
}
|
253
|
+
|
254
|
+
wrappable_struct!(
|
255
|
+
HypothesisCoreIntegersStruct,
|
256
|
+
HypothesisCoreIntegersStructWrapper,
|
257
|
+
HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER
|
258
|
+
);
|
259
|
+
|
260
|
+
class!(HypothesisCoreIntegers);
|
261
|
+
|
262
|
+
methods!(
|
263
|
+
HypothesisCoreIntegers,
|
264
|
+
itself,
|
265
|
+
fn ruby_hypothesis_core_integers_new() -> AnyObject {
|
266
|
+
let core_integers = HypothesisCoreIntegersStruct::new();
|
124
267
|
|
125
|
-
|
126
|
-
|
127
|
-
helix, repeat: Repeat::new(min_count, max_count, expected_count)
|
128
|
-
}
|
268
|
+
Class::from_existing("HypothesisCoreIntegers")
|
269
|
+
.wrap_data(core_integers, &*HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER)
|
129
270
|
}
|
271
|
+
fn ruby_hypothesis_core_integers_provide(data: AnyObject) -> AnyObject {
|
272
|
+
let core_integers = itself.get_data_mut(&*HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER);
|
273
|
+
let mut rdata = safe_access(data);
|
274
|
+
let data_source = rdata.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
|
130
275
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
276
|
+
match core_integers.provide(data_source) {
|
277
|
+
Some(i) => Integer::new(i).into(),
|
278
|
+
None => NilClass::new().into(),
|
279
|
+
}
|
135
280
|
}
|
281
|
+
);
|
136
282
|
|
137
|
-
|
138
|
-
|
283
|
+
pub struct HypothesisCoreRepeatValuesStruct {
|
284
|
+
repeat: Repeat,
|
285
|
+
}
|
286
|
+
|
287
|
+
impl HypothesisCoreRepeatValuesStruct {
|
288
|
+
fn new(
|
289
|
+
min_count: u64,
|
290
|
+
max_count: u64,
|
291
|
+
expected_count: f64,
|
292
|
+
) -> HypothesisCoreRepeatValuesStruct {
|
293
|
+
HypothesisCoreRepeatValuesStruct {
|
294
|
+
repeat: Repeat::new(min_count, max_count, expected_count),
|
295
|
+
}
|
139
296
|
}
|
140
|
-
}
|
141
297
|
|
142
|
-
|
143
|
-
|
144
|
-
|
298
|
+
fn _should_continue(&mut self, data: &mut HypothesisCoreDataSourceStruct) -> Option<bool> {
|
299
|
+
return data
|
300
|
+
.source
|
301
|
+
.as_mut()
|
302
|
+
.and_then(|ref mut source| self.repeat.should_continue(source).ok());
|
145
303
|
}
|
146
|
-
|
147
|
-
|
304
|
+
|
305
|
+
fn reject(&mut self) {
|
306
|
+
self.repeat.reject();
|
148
307
|
}
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
308
|
+
}
|
309
|
+
|
310
|
+
wrappable_struct!(
|
311
|
+
HypothesisCoreRepeatValuesStruct,
|
312
|
+
HypothesisCoreRepeatValuesStructWrapper,
|
313
|
+
HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER
|
314
|
+
);
|
315
|
+
|
316
|
+
class!(HypothesisCoreRepeatValues);
|
317
|
+
|
318
|
+
methods!(
|
319
|
+
HypothesisCoreRepeatValues,
|
320
|
+
itself,
|
321
|
+
fn ruby_hypothesis_core_repeat_values_new(
|
322
|
+
min_count: Integer,
|
323
|
+
max_count: Integer,
|
324
|
+
expected_count: Float
|
325
|
+
) -> AnyObject {
|
326
|
+
let repeat_values = HypothesisCoreRepeatValuesStruct::new(
|
327
|
+
safe_access(min_count).to_u64(),
|
328
|
+
safe_access(max_count).to_u64(),
|
329
|
+
safe_access(expected_count).to_f64(),
|
330
|
+
);
|
331
|
+
|
332
|
+
Class::from_existing("HypothesisCoreRepeatValues").wrap_data(
|
333
|
+
repeat_values,
|
334
|
+
&*HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER,
|
335
|
+
)
|
153
336
|
}
|
154
|
-
|
337
|
+
fn ruby_hypothesis_core_repeat_values_should_continue(data: AnyObject) -> AnyObject {
|
338
|
+
let mut rdata = safe_access(data);
|
339
|
+
let mut data_source = rdata.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
|
340
|
+
|
341
|
+
let should_continue = itself
|
342
|
+
.get_data_mut(&*HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER)
|
343
|
+
._should_continue(data_source);
|
155
344
|
|
156
|
-
|
157
|
-
|
158
|
-
|
345
|
+
match should_continue {
|
346
|
+
Some(b) => Boolean::new(b).into(),
|
347
|
+
None => NilClass::new().into(),
|
348
|
+
}
|
159
349
|
}
|
160
|
-
|
161
|
-
|
350
|
+
fn ruby_hypothesis_core_repeat_values_reject() -> NilClass {
|
351
|
+
let repeat_values = itself.get_data_mut(&*HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER);
|
352
|
+
|
353
|
+
repeat_values.reject();
|
354
|
+
|
355
|
+
NilClass::new()
|
162
356
|
}
|
357
|
+
);
|
163
358
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
359
|
+
pub struct HypothesisCoreBoundedIntegersStruct {
|
360
|
+
max_value: u64,
|
361
|
+
}
|
362
|
+
|
363
|
+
impl HypothesisCoreBoundedIntegersStruct {
|
364
|
+
fn provide(&mut self, data: &mut HypothesisCoreDataSourceStruct) -> Option<u64> {
|
365
|
+
data.source
|
366
|
+
.as_mut()
|
367
|
+
.and_then(|ref mut source| distributions::bounded_int(source, self.max_value).ok())
|
168
368
|
}
|
169
|
-
}
|
170
369
|
}
|
171
370
|
|
172
|
-
|
173
|
-
|
174
|
-
|
371
|
+
wrappable_struct!(
|
372
|
+
HypothesisCoreBoundedIntegersStruct,
|
373
|
+
HypothesisCoreBoundedIntegersStructWrapper,
|
374
|
+
HYPOTHESIS_CORE_BOUNDED_INTEGERS_STRUCT_WRAPPER
|
375
|
+
);
|
376
|
+
|
377
|
+
class!(HypothesisCoreBoundedIntegers);
|
378
|
+
|
379
|
+
methods!(
|
380
|
+
HypothesisCoreBoundedIntegers,
|
381
|
+
itself,
|
382
|
+
fn ruby_hypothesis_core_bounded_integers_new(max_value: Integer) -> AnyObject {
|
383
|
+
let bounded_integers = HypothesisCoreBoundedIntegersStruct {
|
384
|
+
max_value: safe_access(max_value).to_u64(),
|
385
|
+
};
|
386
|
+
|
387
|
+
Class::from_existing("HypothesisCoreBoundedIntegers").wrap_data(
|
388
|
+
bounded_integers,
|
389
|
+
&*HYPOTHESIS_CORE_BOUNDED_INTEGERS_STRUCT_WRAPPER,
|
390
|
+
)
|
391
|
+
}
|
392
|
+
fn ruby_hypothesis_core_bounded_integers_provide(data: AnyObject) -> AnyObject {
|
393
|
+
let mut rdata = safe_access(data);
|
394
|
+
let data_source = rdata.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
|
395
|
+
let bounded_integers =
|
396
|
+
itself.get_data_mut(&*HYPOTHESIS_CORE_BOUNDED_INTEGERS_STRUCT_WRAPPER);
|
397
|
+
|
398
|
+
match bounded_integers.provide(data_source) {
|
399
|
+
Some(i) => Integer::from(i).into(),
|
400
|
+
None => NilClass::new().into(),
|
401
|
+
}
|
402
|
+
}
|
403
|
+
);
|
404
|
+
|
405
|
+
#[allow(non_snake_case)]
|
406
|
+
#[no_mangle]
|
407
|
+
pub extern "C" fn Init_rutie_hypothesis_core() {
|
408
|
+
Class::new("HypothesisCoreEngine", None).define(|klass| {
|
409
|
+
klass.def_self("new", ruby_hypothesis_core_engine_new);
|
410
|
+
klass.def("new_source", ruby_hypothesis_core_engine_new_source);
|
411
|
+
klass.def(
|
412
|
+
"count_failing_examples",
|
413
|
+
ruby_hypothesis_core_engine_count_failing_examples,
|
414
|
+
);
|
415
|
+
klass.def("failing_example", ruby_hypothesis_core_failing_example);
|
416
|
+
klass.def(
|
417
|
+
"was_unsatisfiable",
|
418
|
+
ruby_hypothesis_core_engine_was_unsatisfiable,
|
419
|
+
);
|
420
|
+
klass.def(
|
421
|
+
"finish_overflow",
|
422
|
+
ruby_hypothesis_core_engine_finish_overflow,
|
423
|
+
);
|
424
|
+
klass.def("finish_valid", ruby_hypothesis_core_engine_finish_valid);
|
425
|
+
klass.def("finish_invalid", ruby_hypothesis_core_engine_finish_invalid);
|
426
|
+
klass.def(
|
427
|
+
"finish_interesting",
|
428
|
+
ruby_hypothesis_core_engine_finish_interesting,
|
429
|
+
);
|
430
|
+
});
|
431
|
+
|
432
|
+
Class::new("HypothesisCoreDataSource", None).define(|klass| {
|
433
|
+
klass.def("start_draw", ruby_hypothesis_core_data_source_start_draw);
|
434
|
+
klass.def("stop_draw", ruby_hypothesis_core_data_source_stop_draw);
|
435
|
+
});
|
436
|
+
|
437
|
+
Class::new("HypothesisCoreIntegers", None).define(|klass| {
|
438
|
+
klass.def_self("new", ruby_hypothesis_core_integers_new);
|
439
|
+
klass.def("provide", ruby_hypothesis_core_integers_provide);
|
440
|
+
});
|
441
|
+
|
442
|
+
Class::new("HypothesisCoreRepeatValues", None).define(|klass| {
|
443
|
+
klass.def_self("new", ruby_hypothesis_core_repeat_values_new);
|
444
|
+
klass.def(
|
445
|
+
"_should_continue",
|
446
|
+
ruby_hypothesis_core_repeat_values_should_continue,
|
447
|
+
);
|
448
|
+
klass.def("reject", ruby_hypothesis_core_repeat_values_reject);
|
449
|
+
});
|
175
450
|
|
176
|
-
|
177
|
-
|
178
|
-
|
451
|
+
Class::new("HypothesisCoreBoundedIntegers", None).define(|klass| {
|
452
|
+
klass.def_self("new", ruby_hypothesis_core_bounded_integers_new);
|
453
|
+
klass.def("provide", ruby_hypothesis_core_bounded_integers_provide);
|
454
|
+
});
|
455
|
+
}
|
456
|
+
|
457
|
+
fn mark_child_status(
|
458
|
+
engine: &mut Engine,
|
459
|
+
child: &mut HypothesisCoreDataSourceStruct,
|
460
|
+
status: Status,
|
461
|
+
) {
|
462
|
+
if let Some(source) = mem::take(&mut child.source) {
|
463
|
+
engine.mark_finished(source, status)
|
179
464
|
}
|
180
465
|
}
|
466
|
+
|
467
|
+
fn safe_access<T>(value: Result<T, AnyException>) -> T {
|
468
|
+
value.map_err(VM::raise_ex).unwrap()
|
469
|
+
}
|
metadata
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hypothesis-specs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David R. Maciver
|
8
|
+
- Alex Weisberger
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2021-01-08 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: rutie
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
18
|
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
20
|
+
version: 0.0.3
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
25
|
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
27
|
+
version: 0.0.3
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
29
|
name: rake
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,6 +65,7 @@ files:
|
|
64
65
|
- lib/hypothesis.rb
|
65
66
|
- lib/hypothesis/engine.rb
|
66
67
|
- lib/hypothesis/errors.rb
|
68
|
+
- lib/hypothesis/junkdrawer.rb
|
67
69
|
- lib/hypothesis/possible.rb
|
68
70
|
- lib/hypothesis/testcase.rb
|
69
71
|
- lib/hypothesis/world.rb
|
@@ -87,8 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
89
|
- !ruby/object:Gem::Version
|
88
90
|
version: '0'
|
89
91
|
requirements: []
|
90
|
-
|
91
|
-
rubygems_version: 2.7.6
|
92
|
+
rubygems_version: 3.2.4
|
92
93
|
signing_key:
|
93
94
|
specification_version: 4
|
94
95
|
summary: Hypothesis is a powerful, flexible, and easy to use library for property-based
|