hypothesis-specs 0.2.0 → 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 +6 -0
- data/Cargo.toml +4 -2
- data/LICENSE.txt +1 -1
- data/README.markdown +1 -1
- data/Rakefile +4 -3
- data/lib/hypothesis.rb +18 -0
- data/lib/hypothesis/engine.rb +1 -3
- data/src/lib.rs +404 -125
- metadata +7 -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,9 @@
|
|
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
|
+
|
1
7
|
# Hypothesis for Ruby 0.2.0 (2018-10-24)
|
2
8
|
|
3
9
|
This release adds an example database to Hypothesis for Ruby. This means that when a test fails,
|
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
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
@@ -19,6 +19,23 @@ require_relative 'hypothesis/world'
|
|
19
19
|
module Hypothesis
|
20
20
|
# @!visibility private
|
21
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
|
22
39
|
|
23
40
|
# @!visibility private
|
24
41
|
def hypothesis_stable_identifier
|
@@ -188,6 +205,7 @@ module Hypothesis
|
|
188
205
|
unless World.current_engine.nil?
|
189
206
|
raise UsageError, 'Cannot nest hypothesis calls'
|
190
207
|
end
|
208
|
+
|
191
209
|
begin
|
192
210
|
World.current_engine = Engine.new(
|
193
211
|
hypothesis_stable_identifier,
|
data/lib/hypothesis/engine.rb
CHANGED
data/src/lib.rs
CHANGED
@@ -1,190 +1,469 @@
|
|
1
|
-
// "Bridging" root code that exists exclusively to provide
|
2
|
-
// a ruby -> Hypothesis engine binding.
|
3
|
-
|
4
|
-
#![recursion_limit = "256"]
|
5
|
-
#![deny(warnings, missing_debug_implementations)]
|
6
|
-
|
7
|
-
extern crate core;
|
8
1
|
#[macro_use]
|
9
|
-
extern crate
|
10
|
-
|
2
|
+
extern crate rutie;
|
3
|
+
#[macro_use]
|
4
|
+
extern crate lazy_static;
|
11
5
|
extern crate conjecture;
|
12
6
|
|
13
7
|
use std::mem;
|
14
8
|
|
9
|
+
use rutie::{AnyException, AnyObject, Boolean, Class, Float, Integer, NilClass, Object, RString, VM};
|
10
|
+
|
15
11
|
use conjecture::data::{DataSource, Status, TestResult};
|
16
|
-
use conjecture::
|
12
|
+
use conjecture::database::{BoxedDatabase, DirectoryDatabase, NoDatabase};
|
17
13
|
use conjecture::distributions;
|
14
|
+
use conjecture::distributions::Repeat;
|
18
15
|
use conjecture::engine::Engine;
|
19
|
-
use conjecture::database::{BoxedDatabase, NoDatabase, DirectoryDatabase};
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
+
}
|
25
26
|
}
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
fn start_draw(&mut self) {
|
29
|
+
if let Some(ref mut source) = self.source {
|
30
|
+
source.start_draw();
|
31
|
+
}
|
31
32
|
}
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
fn stop_draw(&mut self) {
|
35
|
+
if let Some(ref mut source) = self.source {
|
36
|
+
source.stop_draw();
|
37
|
+
}
|
37
38
|
}
|
39
|
+
}
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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()
|
43
58
|
}
|
44
|
-
|
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();
|
45
63
|
|
46
|
-
|
47
|
-
struct {
|
48
|
-
engine: Engine,
|
49
|
-
pending: Option<DataSource>,
|
50
|
-
interesting_examples: Vec<TestResult>,
|
64
|
+
NilClass::new()
|
51
65
|
}
|
66
|
+
);
|
67
|
+
|
68
|
+
pub struct HypothesisCoreEngineStruct {
|
69
|
+
engine: Engine,
|
70
|
+
pending: Option<DataSource>,
|
71
|
+
interesting_examples: Vec<TestResult>,
|
72
|
+
}
|
52
73
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
+
};
|
59
86
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
}
|
87
|
+
HypothesisCoreEngineStruct {
|
88
|
+
engine: Engine::new(name, max_examples, &xs, db),
|
89
|
+
pending: None,
|
90
|
+
interesting_examples: Vec::new(),
|
91
|
+
}
|
66
92
|
}
|
67
93
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
+
}
|
79
105
|
}
|
80
106
|
|
81
|
-
|
82
|
-
|
107
|
+
fn count_failing_examples(&self) -> usize {
|
108
|
+
self.interesting_examples.len()
|
83
109
|
}
|
84
110
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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)
|
90
116
|
}
|
91
117
|
|
92
|
-
|
93
|
-
|
118
|
+
fn was_unsatisfiable(&mut self) -> bool {
|
119
|
+
self.engine.was_unsatisfiable()
|
94
120
|
}
|
95
121
|
|
96
|
-
|
97
|
-
|
122
|
+
fn finish_overflow(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
|
123
|
+
mark_child_status(&mut self.engine, child, Status::Overflow);
|
98
124
|
}
|
99
125
|
|
100
|
-
|
101
|
-
|
126
|
+
fn finish_valid(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
|
127
|
+
mark_child_status(&mut self.engine, child, Status::Valid);
|
102
128
|
}
|
103
129
|
|
104
|
-
|
105
|
-
|
130
|
+
fn finish_invalid(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
|
131
|
+
mark_child_status(&mut self.engine, child, Status::Invalid);
|
106
132
|
}
|
107
133
|
|
108
|
-
|
109
|
-
|
134
|
+
fn finish_interesting(&mut self, child: &mut HypothesisCoreDataSourceStruct, label: u64) {
|
135
|
+
mark_child_status(&mut self.engine, child, Status::Interesting(label));
|
110
136
|
}
|
111
|
-
|
137
|
+
}
|
138
|
+
|
139
|
+
wrappable_struct!(
|
140
|
+
HypothesisCoreEngineStruct,
|
141
|
+
HypothesisCoreEngineStructWrapper,
|
142
|
+
HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER
|
143
|
+
);
|
144
|
+
|
145
|
+
class!(HypothesisCoreEngine);
|
146
|
+
|
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
|
+
);
|
112
162
|
|
113
|
-
|
114
|
-
|
115
|
-
n_bits: u64,
|
163
|
+
Class::from_existing("HypothesisCoreEngine")
|
164
|
+
.wrap_data(core_engine, &*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER)
|
116
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
|
+
}
|
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);
|
117
182
|
|
118
|
-
|
119
|
-
return HypothesisCoreBitPossible{helix, n_bits: n_bits};
|
183
|
+
NilClass::new()
|
120
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);
|
121
191
|
|
122
|
-
|
123
|
-
match &mut data.source {
|
124
|
-
&mut None => None,
|
125
|
-
&mut Some(ref mut source) => source.bits(self.n_bits).ok(),
|
126
|
-
}
|
192
|
+
NilClass::new()
|
127
193
|
}
|
128
|
-
|
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);
|
129
198
|
|
130
|
-
|
131
|
-
|
132
|
-
|
199
|
+
core_engine.finish_invalid(data_source);
|
200
|
+
|
201
|
+
NilClass::new()
|
133
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());
|
134
212
|
|
135
|
-
|
136
|
-
return HypothesisCoreRepeatValues{
|
137
|
-
helix, repeat: Repeat::new(min_count, max_count, expected_count)
|
138
|
-
}
|
213
|
+
NilClass::new()
|
139
214
|
}
|
215
|
+
fn ruby_hypothesis_core_engine_count_failing_examples() -> Integer {
|
216
|
+
let core_engine = itself.get_data(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
140
217
|
|
141
|
-
|
142
|
-
return data.source.as_mut().and_then(|ref mut source| {
|
143
|
-
self.repeat.should_continue(source).ok()
|
144
|
-
})
|
218
|
+
Integer::new(core_engine.count_failing_examples() as i64)
|
145
219
|
}
|
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;
|
146
223
|
|
147
|
-
|
148
|
-
|
224
|
+
let data_source = core_engine.failing_example(int);
|
225
|
+
|
226
|
+
Class::from_existing("HypothesisCoreDataSource")
|
227
|
+
.wrap_data(data_source, &*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER)
|
149
228
|
}
|
150
|
-
|
229
|
+
fn ruby_hypothesis_core_engine_was_unsatisfiable() -> Boolean {
|
230
|
+
let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
|
151
231
|
|
152
|
-
|
153
|
-
struct {
|
154
|
-
bitlengths: distributions::Sampler,
|
232
|
+
Boolean::new(core_engine.was_unsatisfiable())
|
155
233
|
}
|
156
|
-
|
157
|
-
|
234
|
+
);
|
235
|
+
|
236
|
+
pub struct HypothesisCoreIntegersStruct {
|
237
|
+
bitlengths: distributions::Sampler,
|
238
|
+
}
|
239
|
+
|
240
|
+
impl HypothesisCoreIntegersStruct {
|
241
|
+
fn new() -> HypothesisCoreIntegersStruct {
|
242
|
+
HypothesisCoreIntegersStruct {
|
243
|
+
bitlengths: distributions::good_bitlengths(),
|
244
|
+
}
|
158
245
|
}
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
246
|
+
|
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
|
+
})
|
163
251
|
}
|
164
|
-
|
252
|
+
}
|
253
|
+
|
254
|
+
wrappable_struct!(
|
255
|
+
HypothesisCoreIntegersStruct,
|
256
|
+
HypothesisCoreIntegersStructWrapper,
|
257
|
+
HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER
|
258
|
+
);
|
259
|
+
|
260
|
+
class!(HypothesisCoreIntegers);
|
165
261
|
|
166
|
-
|
167
|
-
|
168
|
-
|
262
|
+
methods!(
|
263
|
+
HypothesisCoreIntegers,
|
264
|
+
itself,
|
265
|
+
fn ruby_hypothesis_core_integers_new() -> AnyObject {
|
266
|
+
let core_integers = HypothesisCoreIntegersStruct::new();
|
267
|
+
|
268
|
+
Class::from_existing("HypothesisCoreIntegers")
|
269
|
+
.wrap_data(core_integers, &*HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER)
|
169
270
|
}
|
170
|
-
|
171
|
-
|
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);
|
275
|
+
|
276
|
+
match core_integers.provide(data_source) {
|
277
|
+
Some(i) => Integer::new(i).into(),
|
278
|
+
None => NilClass::new().into(),
|
279
|
+
}
|
172
280
|
}
|
281
|
+
);
|
282
|
+
|
283
|
+
pub struct HypothesisCoreRepeatValuesStruct {
|
284
|
+
repeat: Repeat,
|
285
|
+
}
|
173
286
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
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
|
+
}
|
178
296
|
}
|
179
|
-
|
297
|
+
|
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());
|
303
|
+
}
|
304
|
+
|
305
|
+
fn reject(&mut self) {
|
306
|
+
self.repeat.reject();
|
307
|
+
}
|
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
|
+
)
|
336
|
+
}
|
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);
|
344
|
+
|
345
|
+
match should_continue {
|
346
|
+
Some(b) => Boolean::new(b).into(),
|
347
|
+
None => NilClass::new().into(),
|
348
|
+
}
|
349
|
+
}
|
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()
|
356
|
+
}
|
357
|
+
);
|
358
|
+
|
359
|
+
pub struct HypothesisCoreBoundedIntegersStruct {
|
360
|
+
max_value: u64,
|
180
361
|
}
|
181
362
|
|
182
|
-
|
183
|
-
|
184
|
-
|
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())
|
368
|
+
}
|
369
|
+
}
|
370
|
+
|
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
|
+
};
|
185
386
|
|
186
|
-
|
187
|
-
|
188
|
-
|
387
|
+
Class::from_existing("HypothesisCoreBoundedIntegers").wrap_data(
|
388
|
+
bounded_integers,
|
389
|
+
&*HYPOTHESIS_CORE_BOUNDED_INTEGERS_STRUCT_WRAPPER,
|
390
|
+
)
|
189
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
|
+
});
|
450
|
+
|
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)
|
464
|
+
}
|
465
|
+
}
|
466
|
+
|
467
|
+
fn safe_access<T>(value: Result<T, AnyException>) -> T {
|
468
|
+
value.map_err(VM::raise_ex).unwrap()
|
190
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.
|
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
|
@@ -88,8 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
89
|
- !ruby/object:Gem::Version
|
89
90
|
version: '0'
|
90
91
|
requirements: []
|
91
|
-
|
92
|
-
rubygems_version: 2.7.6
|
92
|
+
rubygems_version: 3.2.4
|
93
93
|
signing_key:
|
94
94
|
specification_version: 4
|
95
95
|
summary: Hypothesis is a powerful, flexible, and easy to use library for property-based
|