hypothesis-specs 0.2.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ceb7e5a7e7c564c26e971e6e5aacce7599ef8c3b810b879141c8ea9e97f2b7f
4
- data.tar.gz: f5de9db4207eea15c790475cc43540faf30d69e5587be623dedf6b954b556f04
3
+ metadata.gz: a79509b16d94eae8514d1601878d3fb5a1ba1885f385ae7caf27673874508a51
4
+ data.tar.gz: ebc2a3661f7a1d9b82c839faed66006de0f95357e4615645788cbe3fd074674d
5
5
  SHA512:
6
- metadata.gz: 79c6389fefaca46af95d01f1b285a6e2cc1f9dc30c185da5efd6363e65b00f00794a9ca21ee5b551e6bb06df235c10b00777b0a8d27b3c09d8e10cdf834944ff
7
- data.tar.gz: 5129459dbc559cb3b08354e3c0e36f691a2f9aea7f58dacf01a69760bcd9d6b06d7a7e905ac19b768b31d285ce30a7c587ab8dab54a546eb600e5e14b42d069c
6
+ metadata.gz: dba3693d2d2ad38d5efa17ffecf2c70148b6cc1a5e5e2c8e7c89673a42efb183bd1fb374f2129cd81cffe974da90514a8f44d73e4c46602596e4910d98bc3340
7
+ data.tar.gz: 7dd4894162024a4bfc45df2de1b2aa72803d835f5e4f90f87b8cf5397e88ac48d9e6806440622f5f89b4a4cb9eea60429568404b7c965a099733c5d8d008e2a3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,41 @@
1
+ # Hypothesis for Ruby 0.6.1 (2021-02-01)
2
+
3
+ This patch contains minor performance improvements for `HypothesisCoreIntegers` class instantiation.
4
+
5
+ # Hypothesis for Ruby 0.6.0 (2021-01-27)
6
+
7
+ Adds support for skipping shrinking. While shrinking is extremely helpful and important in general, it has the potential to be quite time consuming. It can be useful to observe a raw failure before choosing to allow the engine to try to shrink. [hypothesis-python](https://hypothesis.readthedocs.io/en/latest/settings.html#phases) already provides the ability to skip shrinking, so there is precedent for this being useful. While `hypothesis-ruby` does not have the concept of other "Phases" yet, we can still start off the API by using this concept.
8
+
9
+ Usage:
10
+
11
+ ```
12
+ hypothesis(phases: Phase.excluding(:shrink)) do
13
+ # Failures here will be displayed directly and shrinking will be avoided
14
+ end
15
+ ```
16
+
17
+ # Hypothesis for Ruby 0.5.0 (2021-01-25)
18
+
19
+ Adds support for skipping shrinking. While shrinking is extremely helpful and important in general, it has the potential to be quite time consuming. It can be useful to observe a raw failure before choosing to allow the engine to try to shrink. [hypothesis-python](https://hypothesis.readthedocs.io/en/latest/settings.html#phases) already provides the ability to skip shrinking, so there is precedent for this being useful. While `hypothesis-ruby` does not have the concept of other "Phases" yet, we can still start off the API by using this concept.
20
+
21
+ Usage:
22
+
23
+ ```
24
+ hypothesis(phases: Phase.excluding(:shrink)) do
25
+ # Failures here will be displayed directly and shrinking will be avoided
26
+ end
27
+ ```
28
+
29
+ # Hypothesis for Ruby 0.4.0 (2021-01-12)
30
+
31
+ This removes hypothesis-ruby's dependence on RSpec. Now, it can be used with any Ruby test runner.
32
+
33
+ # Hypothesis for Ruby 0.3.0 (2021-01-08)
34
+
35
+ This release converts Hypothesis for Ruby to use [RuTie](https://github.com/danielpclark/rutie)
36
+ instead of the deprecated [Helix](https://github.com/tildeio/helix), restoring compatibility
37
+ with recent versions of Rust. Thanks to Alex Weisberger for taking this on!
38
+
1
39
  # Hypothesis for Ruby 0.2.0 (2018-10-24)
2
40
 
3
41
  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 Weisberger <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
- helix = '0.7.5'
11
+ rutie = {version="0.8.1"}
12
+ lazy_static = "1.4.0"
11
13
  rand = '0.3'
12
- conjecture = '0.4.0'
14
+ conjecture = '0.7.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 http://mozilla.org/MPL/2.0/.
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 ws duplicated in the list.
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
@@ -71,7 +71,7 @@ Right now this is really more to allow you to try it out and provide feedback th
71
71
  The more feedback we get, the sooner it will get there!
72
72
 
73
73
  Note that in order to use Hypothesis for Ruby, you will need a rust toolchain installed.
74
- Please go to [https://www.rustup.rs](https://www.rustup.rs) and follow the instructions if you do not already have one.
74
+ Please go to [https://www.rustup.rs](https://www.rustup.rs) and follow the instructions if you do not already have one. You will most likely need to compile your Ruby executable with the `--enable-shared` option. See [here](https://github.com/danielpclark/rutie#dynamic-vs-static-builds).
75
75
 
76
76
  ## Project Status
77
77
 
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
+ sh('cargo build --release')
9
+ end
10
+
8
11
  begin
9
12
  require 'rspec/core/rake_task'
10
13
  RSpec::Core::RakeTask.new(:spec)
@@ -17,10 +20,24 @@ begin
17
20
  end
18
21
 
19
22
  task test: %i[build spec minitests]
23
+ task rspec: %i[build spec]
24
+ task minitest: %i[build without_rspec] do
25
+ begin
26
+ Rake::Task['minitests'].execute
27
+ ensure
28
+ Rake::Task['with_rspec'].execute
29
+ end
30
+ end
20
31
  rescue LoadError
21
32
  end
22
33
 
23
- HelixRuntime::BuildTask.new
34
+ task :without_rspec do
35
+ sh('bundle config set without rspec')
36
+ end
37
+
38
+ task :with_rspec do
39
+ sh('bundle config unset without')
40
+ end
24
41
 
25
42
  def rubocop(fix:)
26
43
  sh "bundle exec rubocop #{'-a' if fix} lib spec minitests " \
data/lib/hypothesis.rb CHANGED
@@ -7,6 +7,28 @@ require_relative 'hypothesis/testcase'
7
7
  require_relative 'hypothesis/engine'
8
8
  require_relative 'hypothesis/world'
9
9
 
10
+ module Phase
11
+ SHRINK = :shrink
12
+
13
+ module_function
14
+
15
+ def all
16
+ [SHRINK]
17
+ end
18
+
19
+ def excluding(*phases)
20
+ unknown_phases = phases.reject { |phase| Phase.all.include?(phase) }
21
+ unless unknown_phases.empty?
22
+ raise(
23
+ ArgumentError,
24
+ "Attempting to exclude unknown phases: #{unknown_phases}"
25
+ )
26
+ end
27
+
28
+ all - phases
29
+ end
30
+ end
31
+
10
32
  # This is the main module for using Hypothesis.
11
33
  # It is expected that you will include this in your
12
34
  # tests, but its methods are also available on the
@@ -19,6 +41,23 @@ require_relative 'hypothesis/world'
19
41
  module Hypothesis
20
42
  # @!visibility private
21
43
  HYPOTHESIS_LOCATION = File.dirname(__FILE__)
44
+ # rubocop:disable ClassVars
45
+ @@setup_called = false
46
+ # rubocop:enable RuleByName
47
+
48
+ def self.setup_called
49
+ @@setup_called == true
50
+ end
51
+
52
+ def self.included(*)
53
+ if setup_called == false
54
+ Rutie.new(:hypothesis_ruby_core).init(
55
+ 'Init_rutie_hypothesis_core',
56
+ __dir__
57
+ )
58
+ end
59
+ @@setup_called = true
60
+ end
22
61
 
23
62
  # @!visibility private
24
63
  def hypothesis_stable_identifier
@@ -184,14 +223,21 @@ module Hypothesis
184
223
  # should store previously failing test cases. If it is nil, Hypothesis
185
224
  # will use a default of .hypothesis/examples in the current directory.
186
225
  # May also be set to false to disable the database functionality.
187
- def hypothesis(max_valid_test_cases: 200, database: nil, &block)
226
+ def hypothesis(
227
+ max_valid_test_cases: 200,
228
+ phases: Phase.all,
229
+ database: nil,
230
+ &block
231
+ )
188
232
  unless World.current_engine.nil?
189
233
  raise UsageError, 'Cannot nest hypothesis calls'
190
234
  end
235
+
191
236
  begin
192
237
  World.current_engine = Engine.new(
193
238
  hypothesis_stable_identifier,
194
239
  max_examples: max_valid_test_cases,
240
+ phases: phases,
195
241
  database: database
196
242
  )
197
243
  World.current_engine.run(&block)
@@ -1,17 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'helix_runtime'
4
-
5
- require_relative '../hypothesis-ruby/native'
6
-
7
- require 'rspec/expectations'
3
+ require 'rutie'
8
4
 
9
5
  module Hypothesis
10
6
  DEFAULT_DATABASE_PATH = File.join(Dir.pwd, '.hypothesis', 'examples')
11
7
 
12
8
  class Engine
13
- include RSpec::Matchers
14
-
15
9
  attr_reader :current_source
16
10
  attr_accessor :is_find
17
11
 
@@ -25,7 +19,11 @@ module Hypothesis
25
19
  database = nil if database == false
26
20
 
27
21
  @core_engine = HypothesisCoreEngine.new(
28
- name, database, seed, options.fetch(:max_examples)
22
+ name,
23
+ database,
24
+ seed,
25
+ options.fetch(:max_examples),
26
+ options.fetch(:phases)
29
27
  )
30
28
 
31
29
  @exceptions_to_tags = Hash.new { |h, k| h[k] = h.size }
data/src/lib.rs CHANGED
@@ -1,190 +1,492 @@
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 helix;
10
- extern crate rand;
2
+ extern crate rutie;
3
+ #[macro_use]
4
+ extern crate lazy_static;
11
5
  extern crate conjecture;
12
6
 
7
+ use std::convert::TryFrom;
13
8
  use std::mem;
14
9
 
10
+ use rutie::{
11
+ AnyException, AnyObject, Array, Boolean, Class, Exception, Float, Integer, NilClass, Object,
12
+ RString, Symbol, VM,
13
+ };
14
+
15
15
  use conjecture::data::{DataSource, Status, TestResult};
16
- use conjecture::distributions::Repeat;
16
+ use conjecture::database::{BoxedDatabase, DirectoryDatabase, NoDatabase};
17
17
  use conjecture::distributions;
18
- use conjecture::engine::Engine;
19
- use conjecture::database::{BoxedDatabase, NoDatabase, DirectoryDatabase};
18
+ use conjecture::distributions::Repeat;
19
+ use conjecture::engine::{Engine, Phase};
20
+
21
+ pub struct HypothesisCoreDataSourceStruct {
22
+ source: Option<DataSource>,
23
+ }
20
24
 
21
- ruby! {
22
- class HypothesisCoreDataSource {
23
- struct {
24
- source: Option<DataSource>,
25
+ impl HypothesisCoreDataSourceStruct {
26
+ fn new(engine: &mut HypothesisCoreEngineStruct) -> HypothesisCoreDataSourceStruct {
27
+ HypothesisCoreDataSourceStruct {
28
+ source: mem::take(&mut engine.pending),
29
+ }
25
30
  }
26
31
 
27
- def initialize(helix, engine: &mut HypothesisCoreEngine){
28
- let mut result = HypothesisCoreDataSource{helix, source: None};
29
- mem::swap(&mut result.source, &mut engine.pending);
30
- return result;
32
+ fn start_draw(&mut self) {
33
+ if let Some(ref mut source) = self.source {
34
+ source.start_draw();
35
+ }
31
36
  }
32
37
 
33
- def start_draw(&mut self){
34
- if let &mut Some(ref mut source) = &mut self.source {
35
- source.start_draw();
36
- }
38
+ fn stop_draw(&mut self) {
39
+ if let Some(ref mut source) = self.source {
40
+ source.stop_draw();
41
+ }
37
42
  }
43
+ }
38
44
 
39
- def stop_draw(&mut self){
40
- if let &mut Some(ref mut source) = &mut self.source {
41
- source.stop_draw();
42
- }
45
+ wrappable_struct!(
46
+ HypothesisCoreDataSourceStruct,
47
+ HypothesisCoreDataSourceStructWrapper,
48
+ HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER
49
+ );
50
+
51
+ class!(HypothesisCoreDataSource);
52
+
53
+ #[rustfmt::skip]
54
+ methods!(
55
+ HypothesisCoreDataSource,
56
+ itself,
57
+ fn ruby_hypothesis_core_data_source_start_draw() -> NilClass {
58
+ itself
59
+ .get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER)
60
+ .start_draw();
61
+
62
+ NilClass::new()
43
63
  }
44
- }
64
+ fn ruby_hypothesis_core_data_source_stop_draw() -> NilClass {
65
+ itself
66
+ .get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER)
67
+ .stop_draw();
45
68
 
46
- class HypothesisCoreEngine {
47
- struct {
48
- engine: Engine,
49
- pending: Option<DataSource>,
50
- interesting_examples: Vec<TestResult>,
69
+ NilClass::new()
51
70
  }
71
+ );
72
+
73
+ pub struct HypothesisCoreEngineStruct {
74
+ engine: Engine,
75
+ pending: Option<DataSource>,
76
+ interesting_examples: Vec<TestResult>,
77
+ }
52
78
 
53
- def initialize(helix, name: String, database_path: Option<String>, seed: u64, max_examples: u64){
54
- let xs: [u32; 2] = [seed as u32, (seed >> 32) as u32];
55
- let db: BoxedDatabase = match database_path {
56
- None => Box::new(NoDatabase),
57
- Some(path) => Box::new(DirectoryDatabase::new(path)),
58
- };
79
+ impl HypothesisCoreEngineStruct {
80
+ fn new(
81
+ name: String,
82
+ database_path: Option<String>,
83
+ seed: u64,
84
+ max_examples: u64,
85
+ phases: Vec<Phase>,
86
+ ) -> HypothesisCoreEngineStruct {
87
+ let xs: [u32; 2] = [seed as u32, (seed >> 32) as u32];
88
+ let db: BoxedDatabase = match database_path {
89
+ None => Box::new(NoDatabase),
90
+ Some(path) => Box::new(DirectoryDatabase::new(path)),
91
+ };
59
92
 
60
- HypothesisCoreEngine{
61
- helix,
62
- engine: Engine::new(name, max_examples, &xs, db),
63
- pending: None,
64
- interesting_examples: Vec::new(),
65
- }
93
+ HypothesisCoreEngineStruct {
94
+ engine: Engine::new(name, max_examples, phases, &xs, db),
95
+ pending: None,
96
+ interesting_examples: Vec::new(),
97
+ }
66
98
  }
67
99
 
68
- def new_source(&mut self) -> Option<HypothesisCoreDataSource> {
69
- match self.engine.next_source() {
70
- None => {
71
- self.interesting_examples = self.engine.list_minimized_examples();
72
- None
73
- },
74
- Some(source) => {
75
- self.pending = Some(source);
76
- Some(HypothesisCoreDataSource::new(self))
77
- },
78
- }
100
+ fn new_source(&mut self) -> Option<HypothesisCoreDataSourceStruct> {
101
+ match self.engine.next_source() {
102
+ None => {
103
+ self.interesting_examples = self.engine.list_minimized_examples();
104
+ None
105
+ }
106
+ Some(source) => {
107
+ self.pending = Some(source);
108
+ Some(HypothesisCoreDataSourceStruct::new(self))
109
+ }
110
+ }
79
111
  }
80
112
 
81
- def count_failing_examples(&self) -> usize {
82
- self.interesting_examples.len()
113
+ fn count_failing_examples(&self) -> usize {
114
+ self.interesting_examples.len()
83
115
  }
84
116
 
85
- def failing_example(&mut self, i: usize) -> HypothesisCoreDataSource {
86
- self.pending = Some(
87
- DataSource::from_vec(self.interesting_examples[i].record.clone())
88
- );
89
- HypothesisCoreDataSource::new(self)
117
+ fn failing_example(&mut self, i: usize) -> HypothesisCoreDataSourceStruct {
118
+ self.pending = Some(DataSource::from_vec(
119
+ self.interesting_examples[i].record.clone(),
120
+ ));
121
+ HypothesisCoreDataSourceStruct::new(self)
90
122
  }
91
123
 
92
- def was_unsatisfiable(&mut self) -> bool {
93
- self.engine.was_unsatisfiable()
124
+ fn was_unsatisfiable(&mut self) -> bool {
125
+ self.engine.was_unsatisfiable()
94
126
  }
95
127
 
96
- def finish_overflow(&mut self, child: &mut HypothesisCoreDataSource){
97
- mark_child_status(&mut self.engine, child, Status::Overflow);
128
+ fn finish_overflow(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
129
+ mark_child_status(&mut self.engine, child, Status::Overflow);
98
130
  }
99
131
 
100
- def finish_invalid(&mut self, child: &mut HypothesisCoreDataSource){
101
- mark_child_status(&mut self.engine, child, Status::Invalid);
132
+ fn finish_valid(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
133
+ mark_child_status(&mut self.engine, child, Status::Valid);
102
134
  }
103
135
 
104
- def finish_interesting(&mut self, child: &mut HypothesisCoreDataSource, label: u64){
105
- mark_child_status(&mut self.engine, child, Status::Interesting(label));
136
+ fn finish_invalid(&mut self, child: &mut HypothesisCoreDataSourceStruct) {
137
+ mark_child_status(&mut self.engine, child, Status::Invalid);
106
138
  }
107
139
 
108
- def finish_valid(&mut self, child: &mut HypothesisCoreDataSource){
109
- mark_child_status(&mut self.engine, child, Status::Valid);
140
+ fn finish_interesting(&mut self, child: &mut HypothesisCoreDataSourceStruct, label: u64) {
141
+ mark_child_status(&mut self.engine, child, Status::Interesting(label));
110
142
  }
111
- }
143
+ }
144
+
145
+ wrappable_struct!(
146
+ HypothesisCoreEngineStruct,
147
+ HypothesisCoreEngineStructWrapper,
148
+ HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER
149
+ );
150
+
151
+ class!(HypothesisCoreEngine);
152
+
153
+ #[rustfmt::skip]
154
+ methods!(
155
+ HypothesisCoreEngine,
156
+ itself,
157
+ fn ruby_hypothesis_core_engine_new(
158
+ name: RString,
159
+ database_path: RString,
160
+ seed: Integer,
161
+ max_example: Integer,
162
+ phases: Array
163
+ ) -> AnyObject {
164
+ let rust_phases = safe_access(phases)
165
+ .into_iter()
166
+ .map(|ruby_phase| {
167
+ let phase_sym = safe_access(ruby_phase.try_convert_to::<Symbol>());
168
+ let phase = Phase::try_from(phase_sym.to_str())
169
+ .map_err(|e| AnyException::new("ArgumentError", Some(&e)));
112
170
 
113
- class HypothesisCoreBitPossible{
114
- struct {
115
- n_bits: u64,
171
+ safe_access(phase)
172
+ })
173
+ .collect();
174
+
175
+ let core_engine = HypothesisCoreEngineStruct::new(
176
+ safe_access(name).to_string(),
177
+ database_path.ok().map(|p| p.to_string()),
178
+ safe_access(seed).to_u64(),
179
+ safe_access(max_example).to_u64(),
180
+ rust_phases,
181
+ );
182
+
183
+ Class::from_existing("HypothesisCoreEngine")
184
+ .wrap_data(core_engine, &*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER)
185
+ }
186
+ fn ruby_hypothesis_core_engine_new_source() -> AnyObject {
187
+ match itself
188
+ .get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER)
189
+ .new_source()
190
+ {
191
+ Some(ds) => Class::from_existing("HypothesisCoreDataSource")
192
+ .wrap_data(ds, &*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER),
193
+ None => NilClass::new().into(),
194
+ }
116
195
  }
196
+ fn ruby_hypothesis_core_engine_finish_overflow(child: AnyObject) -> NilClass {
197
+ let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
198
+ let mut rdata_source = safe_access(child);
199
+ let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
117
200
 
118
- def initialize(helix, n_bits: u64){
119
- return HypothesisCoreBitPossible{helix, n_bits: n_bits};
201
+ core_engine.finish_overflow(data_source);
202
+
203
+ NilClass::new()
120
204
  }
205
+ fn ruby_hypothesis_core_engine_finish_valid(child: AnyObject) -> NilClass {
206
+ let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
207
+ let mut rdata_source = safe_access(child);
208
+ let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
209
+
210
+ core_engine.finish_valid(data_source);
121
211
 
122
- def provide(&mut self, data: &mut HypothesisCoreDataSource) -> Option<u64>{
123
- match &mut data.source {
124
- &mut None => None,
125
- &mut Some(ref mut source) => source.bits(self.n_bits).ok(),
126
- }
212
+ NilClass::new()
127
213
  }
128
- }
214
+ fn ruby_hypothesis_core_engine_finish_invalid(child: AnyObject) -> NilClass {
215
+ let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
216
+ let mut rdata_source = safe_access(child);
217
+ let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
129
218
 
130
- class HypothesisCoreRepeatValues{
131
- struct {
132
- repeat: Repeat,
219
+ core_engine.finish_invalid(data_source);
220
+
221
+ NilClass::new()
133
222
  }
223
+ fn ruby_hypothesis_core_engine_finish_interesting(
224
+ child: AnyObject,
225
+ label: Integer
226
+ ) -> NilClass {
227
+ let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
228
+ let mut rdata_source = safe_access(child);
229
+ let data_source = rdata_source.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
230
+
231
+ core_engine.finish_interesting(data_source, safe_access(label).to_u64());
134
232
 
135
- def initialize(helix, min_count: u64, max_count: u64, expected_count: f64){
136
- return HypothesisCoreRepeatValues{
137
- helix, repeat: Repeat::new(min_count, max_count, expected_count)
138
- }
233
+ NilClass::new()
139
234
  }
235
+ fn ruby_hypothesis_core_engine_count_failing_examples() -> Integer {
236
+ let core_engine = itself.get_data(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
140
237
 
141
- def _should_continue(&mut self, data: &mut HypothesisCoreDataSource) -> Option<bool>{
142
- return data.source.as_mut().and_then(|ref mut source| {
143
- self.repeat.should_continue(source).ok()
144
- })
238
+ Integer::new(core_engine.count_failing_examples() as i64)
145
239
  }
240
+ fn ruby_hypothesis_core_failing_example(i: Integer) -> AnyObject {
241
+ let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
242
+ let int = safe_access(i).to_u64() as usize;
146
243
 
147
- def reject(&mut self){
148
- self.repeat.reject();
244
+ let data_source = core_engine.failing_example(int);
245
+
246
+ Class::from_existing("HypothesisCoreDataSource")
247
+ .wrap_data(data_source, &*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER)
149
248
  }
150
- }
249
+ fn ruby_hypothesis_core_engine_was_unsatisfiable() -> Boolean {
250
+ let core_engine = itself.get_data_mut(&*HYPOTHESIS_CORE_ENGINE_STRUCT_WRAPPER);
151
251
 
152
- class HypothesisCoreIntegers{
153
- struct {
154
- bitlengths: distributions::Sampler,
252
+ Boolean::new(core_engine.was_unsatisfiable())
155
253
  }
156
- def initialize(helix){
157
- return HypothesisCoreIntegers{helix,bitlengths: distributions::good_bitlengths()};
254
+ );
255
+
256
+ pub struct HypothesisCoreIntegersStruct {
257
+ bitlengths: distributions::Sampler,
258
+ }
259
+
260
+ impl HypothesisCoreIntegersStruct {
261
+ fn new() -> HypothesisCoreIntegersStruct {
262
+ HypothesisCoreIntegersStruct {
263
+ bitlengths: distributions::good_bitlengths(),
264
+ }
158
265
  }
159
- def provide(&mut self, data: &mut HypothesisCoreDataSource) -> Option<i64>{
160
- data.source.as_mut().and_then(|ref mut source| {
161
- distributions::integer_from_bitlengths(source, &self.bitlengths).ok()
162
- })
266
+
267
+ fn provide(&mut self, data: &mut HypothesisCoreDataSourceStruct) -> Option<i64> {
268
+ data.source.as_mut().and_then(|ref mut source| {
269
+ distributions::integer_from_bitlengths(source, &self.bitlengths).ok()
270
+ })
163
271
  }
164
- }
272
+ }
273
+
274
+ wrappable_struct!(
275
+ HypothesisCoreIntegersStruct,
276
+ HypothesisCoreIntegersStructWrapper,
277
+ HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER
278
+ );
165
279
 
166
- class HypothesisCoreBoundedIntegers{
167
- struct {
168
- max_value: u64,
280
+ class!(HypothesisCoreIntegers);
281
+
282
+ #[rustfmt::skip]
283
+ methods!(
284
+ HypothesisCoreIntegers,
285
+ itself,
286
+ fn ruby_hypothesis_core_integers_new() -> AnyObject {
287
+ let core_integers = HypothesisCoreIntegersStruct::new();
288
+
289
+ Class::from_existing("HypothesisCoreIntegers")
290
+ .wrap_data(core_integers, &*HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER)
169
291
  }
170
- def initialize(helix, max_value: u64){
171
- return HypothesisCoreBoundedIntegers{helix, max_value: max_value};
292
+ fn ruby_hypothesis_core_integers_provide(data: AnyObject) -> AnyObject {
293
+ let core_integers = itself.get_data_mut(&*HYPOTHESIS_CORE_INTEGERS_STRUCT_WRAPPER);
294
+ let mut rdata = safe_access(data);
295
+ let data_source = rdata.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
296
+
297
+ match core_integers.provide(data_source) {
298
+ Some(i) => Integer::new(i).into(),
299
+ None => NilClass::new().into(),
300
+ }
172
301
  }
302
+ );
173
303
 
174
- def provide(&mut self, data: &mut HypothesisCoreDataSource) -> Option<u64>{
175
- data.source.as_mut().and_then(|ref mut source| {
176
- distributions::bounded_int(source, self.max_value).ok()
177
- })
304
+ pub struct HypothesisCoreRepeatValuesStruct {
305
+ repeat: Repeat,
306
+ }
307
+
308
+ impl HypothesisCoreRepeatValuesStruct {
309
+ fn new(
310
+ min_count: u64,
311
+ max_count: u64,
312
+ expected_count: f64,
313
+ ) -> HypothesisCoreRepeatValuesStruct {
314
+ HypothesisCoreRepeatValuesStruct {
315
+ repeat: Repeat::new(min_count, max_count, expected_count),
316
+ }
317
+ }
318
+
319
+ fn _should_continue(&mut self, data: &mut HypothesisCoreDataSourceStruct) -> Option<bool> {
320
+ return data
321
+ .source
322
+ .as_mut()
323
+ .and_then(|ref mut source| self.repeat.should_continue(source).ok());
324
+ }
325
+
326
+ fn reject(&mut self) {
327
+ self.repeat.reject();
178
328
  }
179
- }
180
329
  }
181
330
 
182
- fn mark_child_status(engine: &mut Engine, child: &mut HypothesisCoreDataSource, status: Status) {
183
- let mut replacement = None;
184
- mem::swap(&mut replacement, &mut child.source);
331
+ wrappable_struct!(
332
+ HypothesisCoreRepeatValuesStruct,
333
+ HypothesisCoreRepeatValuesStructWrapper,
334
+ HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER
335
+ );
336
+
337
+ class!(HypothesisCoreRepeatValues);
338
+
339
+ #[rustfmt::skip]
340
+ methods!(
341
+ HypothesisCoreRepeatValues,
342
+ itself,
343
+ fn ruby_hypothesis_core_repeat_values_new(
344
+ min_count: Integer,
345
+ max_count: Integer,
346
+ expected_count: Float
347
+ ) -> AnyObject {
348
+ let repeat_values = HypothesisCoreRepeatValuesStruct::new(
349
+ safe_access(min_count).to_u64(),
350
+ safe_access(max_count).to_u64(),
351
+ safe_access(expected_count).to_f64(),
352
+ );
353
+
354
+ Class::from_existing("HypothesisCoreRepeatValues").wrap_data(
355
+ repeat_values,
356
+ &*HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER,
357
+ )
358
+ }
359
+ fn ruby_hypothesis_core_repeat_values_should_continue(data: AnyObject) -> AnyObject {
360
+ let mut rdata = safe_access(data);
361
+ let mut data_source = rdata.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
362
+
363
+ let should_continue = itself
364
+ .get_data_mut(&*HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER)
365
+ ._should_continue(data_source);
185
366
 
186
- match replacement {
187
- Some(source) => engine.mark_finished(source, status),
188
- None => (),
367
+ match should_continue {
368
+ Some(b) => Boolean::new(b).into(),
369
+ None => NilClass::new().into(),
370
+ }
189
371
  }
372
+ fn ruby_hypothesis_core_repeat_values_reject() -> NilClass {
373
+ let repeat_values = itself.get_data_mut(&*HYPOTHESIS_CORE_REPEAT_VALUES_STRUCT_WRAPPER);
374
+
375
+ repeat_values.reject();
376
+
377
+ NilClass::new()
378
+ }
379
+ );
380
+
381
+ pub struct HypothesisCoreBoundedIntegersStruct {
382
+ max_value: u64,
383
+ }
384
+
385
+ impl HypothesisCoreBoundedIntegersStruct {
386
+ fn provide(&mut self, data: &mut HypothesisCoreDataSourceStruct) -> Option<u64> {
387
+ data.source
388
+ .as_mut()
389
+ .and_then(|ref mut source| distributions::bounded_int(source, self.max_value).ok())
390
+ }
391
+ }
392
+
393
+ wrappable_struct!(
394
+ HypothesisCoreBoundedIntegersStruct,
395
+ HypothesisCoreBoundedIntegersStructWrapper,
396
+ HYPOTHESIS_CORE_BOUNDED_INTEGERS_STRUCT_WRAPPER
397
+ );
398
+
399
+ class!(HypothesisCoreBoundedIntegers);
400
+
401
+ #[rustfmt::skip]
402
+ methods!(
403
+ HypothesisCoreBoundedIntegers,
404
+ itself,
405
+ fn ruby_hypothesis_core_bounded_integers_new(max_value: Integer) -> AnyObject {
406
+ let bounded_integers = HypothesisCoreBoundedIntegersStruct {
407
+ max_value: safe_access(max_value).to_u64(),
408
+ };
409
+
410
+ Class::from_existing("HypothesisCoreBoundedIntegers").wrap_data(
411
+ bounded_integers,
412
+ &*HYPOTHESIS_CORE_BOUNDED_INTEGERS_STRUCT_WRAPPER,
413
+ )
414
+ }
415
+ fn ruby_hypothesis_core_bounded_integers_provide(data: AnyObject) -> AnyObject {
416
+ let mut rdata = safe_access(data);
417
+ let data_source = rdata.get_data_mut(&*HYPOTHESIS_CORE_DATA_SOURCE_STRUCT_WRAPPER);
418
+ let bounded_integers =
419
+ itself.get_data_mut(&*HYPOTHESIS_CORE_BOUNDED_INTEGERS_STRUCT_WRAPPER);
420
+
421
+ match bounded_integers.provide(data_source) {
422
+ Some(i) => Integer::from(i).into(),
423
+ None => NilClass::new().into(),
424
+ }
425
+ }
426
+ );
427
+
428
+ #[allow(non_snake_case)]
429
+ #[no_mangle]
430
+ pub extern "C" fn Init_rutie_hypothesis_core() {
431
+ Class::new("HypothesisCoreEngine", None).define(|klass| {
432
+ klass.def_self("new", ruby_hypothesis_core_engine_new);
433
+ klass.def("new_source", ruby_hypothesis_core_engine_new_source);
434
+ klass.def(
435
+ "count_failing_examples",
436
+ ruby_hypothesis_core_engine_count_failing_examples,
437
+ );
438
+ klass.def("failing_example", ruby_hypothesis_core_failing_example);
439
+ klass.def(
440
+ "was_unsatisfiable",
441
+ ruby_hypothesis_core_engine_was_unsatisfiable,
442
+ );
443
+ klass.def(
444
+ "finish_overflow",
445
+ ruby_hypothesis_core_engine_finish_overflow,
446
+ );
447
+ klass.def("finish_valid", ruby_hypothesis_core_engine_finish_valid);
448
+ klass.def("finish_invalid", ruby_hypothesis_core_engine_finish_invalid);
449
+ klass.def(
450
+ "finish_interesting",
451
+ ruby_hypothesis_core_engine_finish_interesting,
452
+ );
453
+ });
454
+
455
+ Class::new("HypothesisCoreDataSource", None).define(|klass| {
456
+ klass.def("start_draw", ruby_hypothesis_core_data_source_start_draw);
457
+ klass.def("stop_draw", ruby_hypothesis_core_data_source_stop_draw);
458
+ });
459
+
460
+ Class::new("HypothesisCoreIntegers", None).define(|klass| {
461
+ klass.def_self("new", ruby_hypothesis_core_integers_new);
462
+ klass.def("provide", ruby_hypothesis_core_integers_provide);
463
+ });
464
+
465
+ Class::new("HypothesisCoreRepeatValues", None).define(|klass| {
466
+ klass.def_self("new", ruby_hypothesis_core_repeat_values_new);
467
+ klass.def(
468
+ "_should_continue",
469
+ ruby_hypothesis_core_repeat_values_should_continue,
470
+ );
471
+ klass.def("reject", ruby_hypothesis_core_repeat_values_reject);
472
+ });
473
+
474
+ Class::new("HypothesisCoreBoundedIntegers", None).define(|klass| {
475
+ klass.def_self("new", ruby_hypothesis_core_bounded_integers_new);
476
+ klass.def("provide", ruby_hypothesis_core_bounded_integers_provide);
477
+ });
478
+ }
479
+
480
+ fn mark_child_status(
481
+ engine: &mut Engine,
482
+ child: &mut HypothesisCoreDataSourceStruct,
483
+ status: Status,
484
+ ) {
485
+ if let Some(source) = mem::take(&mut child.source) {
486
+ engine.mark_finished(source, status)
487
+ }
488
+ }
489
+
490
+ fn safe_access<T>(value: Result<T, AnyException>) -> T {
491
+ value.map_err(VM::raise_ex).unwrap()
190
492
  }
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.2.0
4
+ version: 0.6.1
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: 2018-10-24 00:00:00.000000000 Z
12
+ date: 2021-02-01 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: helix_runtime
15
+ name: rutie
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
18
  - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: 0.7.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.7.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
- rubyforge_project:
92
- rubygems_version: 2.7.6
92
+ rubygems_version: 3.2.7
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