prop_check 0.10.0 → 0.10.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: aaa23e40547bec5672e806d62c567947cd596e1c11ed2bc80fbe6912cd75a777
4
- data.tar.gz: a0263cddf3efb8ee55f29395004915c38b6e78c7fc7bbf2c1b456f344013b8da
3
+ metadata.gz: 5b0170f4c948f3ffb903842c33204d4a9d5f74dd4f1d29313a60dec638670623
4
+ data.tar.gz: 447b87275c1e379502694d96591a871a527535e290daf3cc255476965752e1d2
5
5
  SHA512:
6
- metadata.gz: b7976fb344d4c7135cd858ca86606beb97cd9e9f57c40e2bb322a3c76287de46491d4feb1dd3a65158ffef8ea98894490edc7eb9bc506d80ddb110b2f026de8d
7
- data.tar.gz: f80bffd3b08d1a1cf120a70645b548c2f70b540ae5be317b7635f7416cc4e7be94d3a1bfca10acd117166e08fd0a0c6cd8ab08bf68097182fc064519600cfb55
6
+ metadata.gz: 533aae467c23eb1ecc974e842e735b49f3cfdef7ae51090ef11ad86e95f90f81660a6617565df4aab6470d2c2ae9ff5978826b48ed2686a727ac53b7c065a7b1
7
+ data.tar.gz: 4d6cc50716b03427a0aba7c4617a2970cc791c524d6aa427d22a63870853118cd72c6eca469fcd1e42ce2288f42a63b7fc577b248aea47a2892f324d94377db8
data/Gemfile CHANGED
@@ -4,8 +4,10 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  gem "bundler", "~> 2.0"
7
- gem "rake", "~> 12.3", require: false, group: :test
8
- gem "rspec", "~> 3.0", require: false, group: :test
9
- gem "doctest-rspec", require: false, group: :test
10
- gem "simplecov", require: false, group: :test
11
7
 
8
+ group :test do
9
+ gem "rake", "~> 12.3", require: false
10
+ gem "rspec", "~> 3.0", require: false
11
+ gem "doctest-rspec", require: false
12
+ gem "simplecov", require: false
13
+ end
@@ -23,5 +23,13 @@ module PropCheck
23
23
  end
24
24
  end.lazy
25
25
  end
26
+
27
+ ##
28
+ # allow lazy appending of two (potentially lazy) enumerators:
29
+ # >> PropCheck::Helper::LazyAppend.lazy_append([1,2,3],[4,5.6]).to_a
30
+ # => [1,2,3,4,5,6]
31
+ def lazy_append(this_enumerator, other_enumerator)
32
+ [this_enumerator, other_enumerator].lazy.flat_map(&:lazy)
33
+ end
26
34
  end
27
35
  end
@@ -1,18 +1,18 @@
1
- module PropCheck
2
- module Helper
3
- ##
4
- # A refinement for enumerators
5
- # to allow lazy appending of two (potentially lazy) enumerators:
6
- # >> [1,2,3].lazy_append([4,5.6]).to_a
7
- # => [1,2,3,4,5,6]
8
- module LazyAppend
9
- refine Enumerable do
10
- ## >> [1,2,3].lazy_append([4,5.6]).to_a
11
- ## => [1,2,3,4,5,6]
12
- def lazy_append(other_enumerator)
13
- [self, other_enumerator].lazy.flat_map(&:lazy)
14
- end
15
- end
16
- end
17
- end
18
- end
1
+ # module PropCheck
2
+ # module Helper
3
+ # ##
4
+ # # A refinement for enumerators
5
+ # # to allow lazy appending of two (potentially lazy) enumerators:
6
+ # # >> [1,2,3].lazy_append([4,5.6]).to_a
7
+ # # => [1,2,3,4,5,6]
8
+ # module LazyAppend
9
+ # refine Enumerable do
10
+ # ## >> [1,2,3].lazy_append([4,5.6]).to_a
11
+ # ## => [1,2,3,4,5,6]
12
+ # def lazy_append(other_enumerator)
13
+ # [self, other_enumerator].lazy.flat_map(&:lazy)
14
+ # end
15
+ # end
16
+ # end
17
+ # end
18
+ # end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ##
4
+ # @api private
4
5
  # Contains the logic to combine potentially many before/after/around hooks
5
6
  # into a single pair of procedures called `before` and `after`.
6
7
  #
@@ -89,6 +90,7 @@ class PropCheck::Hooks
89
90
  end
90
91
 
91
92
  ##
93
+ # @api private
92
94
  # Wraps enumerable `inner` with a `PropCheck::Hooks` object
93
95
  # such that the before/after/around hooks are called
94
96
  # before/after/around each element that is fetched from `inner`.
@@ -1,13 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'prop_check/helper/lazy_append'
4
-
5
3
  module PropCheck
6
4
  ##
7
5
  # A Rose tree with the root being eager,
8
6
  # and the children computed lazily, on demand.
9
7
  class LazyTree
10
- using PropCheck::Helper::LazyAppend
8
+ require 'prop_check/helper'
11
9
 
12
10
  attr_accessor :root, :children
13
11
  def initialize(root, children = [].lazy)
@@ -38,7 +36,7 @@ module PropCheck
38
36
  # root_children = root_tree.children
39
37
  # flattened_children = children.map(&:flatten)
40
38
 
41
- # combined_children = root_children.lazy_append(flattened_children)
39
+ # combined_children = PropCheck::Helper.lazy_append(root_children, flattened_children)
42
40
 
43
41
  # LazyTree.new(root_root, combined_children)
44
42
  # end
@@ -53,7 +51,7 @@ module PropCheck
53
51
  inner_children = inner_tree.children
54
52
  mapped_children = children.map { |child| child.bind(&fun) }
55
53
 
56
- combined_children = inner_children.lazy_append(mapped_children)
54
+ combined_children = PropCheck::Helper.lazy_append(inner_children, mapped_children)
57
55
 
58
56
  LazyTree.new(inner_root, combined_children)
59
57
  end
@@ -70,7 +68,7 @@ module PropCheck
70
68
  def each(&block)
71
69
  squish = lambda do |tree, list|
72
70
  new_children = tree.children.reduce(list) { |acc, elem| squish.call(elem, acc) }
73
- [tree.root].lazy_append(new_children)
71
+ PropCheck::Helper.lazy_append([tree.root], new_children)
74
72
  end
75
73
 
76
74
  squish
@@ -78,7 +76,7 @@ module PropCheck
78
76
 
79
77
  # base = [root]
80
78
  # recursive = children.map(&:each)
81
- # res = base.lazy_append(recursive)
79
+ # res = PropCheck::Helper.lazy_append(base, recursive)
82
80
 
83
81
  # return res.each(&block) if block_given?
84
82
 
@@ -2,6 +2,8 @@ require 'stringio'
2
2
  require "awesome_print"
3
3
 
4
4
  require 'prop_check/property/configuration'
5
+ require 'prop_check/property/output_formatter'
6
+ require 'prop_check/property/shrinker'
5
7
  require 'prop_check/hooks'
6
8
  module PropCheck
7
9
  ##
@@ -112,16 +114,39 @@ module PropCheck
112
114
  self
113
115
  end
114
116
 
117
+ ##
118
+ # Calls `hook` before each time a check is run with new data.
119
+ #
120
+ # This is useful to add setup logic
121
+ # When called multiple times, earlier-added hooks will be called _before_ `hook` is called.
115
122
  def before(&hook)
116
123
  @hooks.add_before(&hook)
117
124
  self
118
125
  end
119
126
 
127
+ ##
128
+ # Calls `hook` after each time a check is run with new data.
129
+ #
130
+ # This is useful to add teardown logic
131
+ # When called multiple times, earlier-added hooks will be called _after_ `hook` is called.
120
132
  def after(&hook)
121
133
  @hooks.add_after(&hook)
122
134
  self
123
135
  end
124
136
 
137
+ ##
138
+ # Calls `hook` around each time a check is run with new data.
139
+ #
140
+ # `hook` should `yield` to the passed block.
141
+ #
142
+ # When called multiple times, earlier-added hooks will be wrapped _around_ `hook`.
143
+ #
144
+ # Around hooks will be called after all `#before` hooks
145
+ # and before all `#after` hooks.
146
+ #
147
+ # Note that if the block passed to `hook` raises an exception,
148
+ # it is possible for the code after `yield` not to be called.
149
+ # So make sure that cleanup logic is wrapped with the `ensure` keyword.
125
150
  def around(&hook)
126
151
  @hooks.add_around(&hook)
127
152
  self
@@ -223,83 +248,15 @@ module PropCheck
223
248
 
224
249
  private def show_problem_output(problem, generator_results, n_successful, &block)
225
250
  output = @config.verbose ? STDOUT : StringIO.new
226
- output = pre_output(output, n_successful, generator_results.root, problem)
251
+ output = PropCheck::Property::OutputFormatter.pre_output(output, n_successful, generator_results.root, problem)
227
252
  shrunken_result, shrunken_exception, n_shrink_steps = shrink(generator_results, output, &block)
228
- output = post_output(output, n_shrink_steps, shrunken_result, shrunken_exception)
253
+ output = PropCheck::Property::OutputFormatter.post_output(output, n_shrink_steps, shrunken_result, shrunken_exception)
229
254
 
230
255
  [output, shrunken_result, shrunken_exception, n_shrink_steps]
231
256
  end
232
257
 
233
- private def pre_output(output, n_successful, generated_root, problem)
234
- output.puts ""
235
- output.puts "(after #{n_successful} successful property test runs)"
236
- output.puts "Failed on: "
237
- output.puts "`#{print_roots(generated_root)}`"
238
- output.puts ""
239
- output.puts "Exception message:\n---\n#{problem}"
240
- output.puts "---"
241
- output.puts ""
242
-
243
- output
244
- end
245
-
246
- private def post_output(output, n_shrink_steps, shrunken_result, shrunken_exception)
247
- if n_shrink_steps == 0
248
- output.puts '(shrinking impossible)'
249
- else
250
- output.puts ''
251
- output.puts "Shrunken input (after #{n_shrink_steps} shrink steps):"
252
- output.puts "`#{print_roots(shrunken_result)}`"
253
- output.puts ""
254
- output.puts "Shrunken exception:\n---\n#{shrunken_exception}"
255
- output.puts "---"
256
- output.puts ""
257
- end
258
- output
259
- end
260
-
261
- private def print_roots(lazy_tree_val)
262
- if lazy_tree_val.is_a?(Array) && lazy_tree_val.length == 1 && lazy_tree_val[0].is_a?(Hash)
263
- lazy_tree_val[0].ai
264
- else
265
- lazy_tree_val.ai
266
- end
267
- end
268
-
269
258
  private def shrink(bindings_tree, io, &block)
270
- io.puts 'Shrinking...' if @config.verbose
271
- problem_child = bindings_tree
272
- siblings = problem_child.children.lazy
273
- parent_siblings = nil
274
- problem_exception = nil
275
- shrink_steps = 0
276
- @hooks.wrap_enum(0..@config.max_shrink_steps).lazy.each do
277
- begin
278
- sibling = siblings.next
279
- rescue StopIteration
280
- break if parent_siblings.nil?
281
-
282
- siblings = parent_siblings.lazy
283
- parent_siblings = nil
284
- next
285
- end
286
-
287
- shrink_steps += 1
288
- io.print '.' if @config.verbose
289
-
290
- begin
291
- block.call(*sibling.root)
292
- rescue Exception => e
293
- problem_child = sibling
294
- parent_siblings = siblings
295
- siblings = problem_child.children.lazy
296
- problem_exception = e
297
- end
298
- end
299
-
300
- io.puts "(Note: Exceeded #{@config.max_shrink_steps} shrinking steps, the maximum.)" if shrink_steps >= @config.max_shrink_steps
301
-
302
- [problem_child.root, problem_exception, shrink_steps]
259
+ PropCheck::Property::Shrinker.call(bindings_tree, io, @hooks, @config, &block)
303
260
  end
304
261
  end
305
262
  end
@@ -0,0 +1,41 @@
1
+ ##
2
+ # @api private
3
+ module PropCheck::Property::OutputFormatter
4
+ extend self
5
+
6
+ def pre_output(output, n_successful, generated_root, problem)
7
+ output.puts ""
8
+ output.puts "(after #{n_successful} successful property test runs)"
9
+ output.puts "Failed on: "
10
+ output.puts "`#{print_roots(generated_root)}`"
11
+ output.puts ""
12
+ output.puts "Exception message:\n---\n#{problem}"
13
+ output.puts "---"
14
+ output.puts ""
15
+
16
+ output
17
+ end
18
+
19
+ def post_output(output, n_shrink_steps, shrunken_result, shrunken_exception)
20
+ if n_shrink_steps == 0
21
+ output.puts '(shrinking impossible)'
22
+ else
23
+ output.puts ''
24
+ output.puts "Shrunken input (after #{n_shrink_steps} shrink steps):"
25
+ output.puts "`#{print_roots(shrunken_result)}`"
26
+ output.puts ""
27
+ output.puts "Shrunken exception:\n---\n#{shrunken_exception}"
28
+ output.puts "---"
29
+ output.puts ""
30
+ end
31
+ output
32
+ end
33
+
34
+ def print_roots(lazy_tree_val)
35
+ if lazy_tree_val.is_a?(Array) && lazy_tree_val.length == 1 && lazy_tree_val[0].is_a?(Hash)
36
+ lazy_tree_val[0].ai
37
+ else
38
+ lazy_tree_val.ai
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,79 @@
1
+ class PropCheck::Property::Shrinker
2
+ def initialize(bindings_tree, io, hooks, config)
3
+ @problem_child = bindings_tree
4
+ @io = io
5
+ @siblings = @problem_child.children.lazy
6
+ @parent_siblings = nil
7
+ @problem_exception = nil
8
+ @shrink_steps = 0
9
+ @hooks = hooks
10
+ @config = config
11
+ end
12
+
13
+ def self.call(bindings_tree, io, hooks, config, &block)
14
+ self
15
+ .new(bindings_tree, io, hooks, config)
16
+ .call(&block)
17
+ end
18
+
19
+ def call(&block)
20
+ @io.puts 'Shrinking...' if @config.verbose
21
+
22
+ shrink(&block)
23
+
24
+ print_shrinking_exceeded_message if @shrink_steps >= @config.max_shrink_steps
25
+
26
+ [@problem_child.root, @problem_exception, @shrink_steps]
27
+ end
28
+
29
+ private def shrink(&block)
30
+ wrapped_enum.each do
31
+ instruction, sibling = safe_read_sibling
32
+ break if instruction == :break
33
+ next if instruction == :next
34
+
35
+ inc_shrink_step
36
+
37
+ safe_call_block(sibling, &block)
38
+ end
39
+ end
40
+
41
+ private def wrapped_enum
42
+ @hooks.wrap_enum(0..@config.max_shrink_steps).lazy
43
+ end
44
+
45
+ private def inc_shrink_step
46
+ @shrink_steps += 1
47
+ @io.print '.' if @config.verbose
48
+ end
49
+
50
+ private def safe_read_sibling
51
+ begin
52
+ sibling = @siblings.next
53
+ [:continue, sibling]
54
+ rescue StopIteration
55
+ return [:break, nil] if @parent_siblings.nil?
56
+
57
+ @siblings = @parent_siblings.lazy
58
+ @parent_siblings = nil
59
+ [:next, nil]
60
+ end
61
+ end
62
+
63
+ private def safe_call_block(sibling, &block)
64
+ begin
65
+ block.call(*sibling.root)
66
+ # It is correct that we want to rescue _all_ Exceptions
67
+ # not only 'StandardError's
68
+ rescue Exception => e
69
+ @problem_child = sibling
70
+ @parent_siblings = @siblings
71
+ @siblings = @problem_child.children.lazy
72
+ @problem_exception = e
73
+ end
74
+ end
75
+
76
+ private def print_shrinking_exceeded_message
77
+ @io.puts "(Note: Exceeded #{@config.max_shrink_steps} shrinking steps, the maximum.)"
78
+ end
79
+ end
@@ -1,3 +1,3 @@
1
1
  module PropCheck
2
- VERSION = '0.10.0'
2
+ VERSION = '0.10.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prop_check
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Qqwy/Wiebe-Marten Wijnja
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-29 00:00:00.000000000 Z
11
+ date: 2020-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
@@ -57,6 +57,8 @@ files:
57
57
  - lib/prop_check/lazy_tree.rb
58
58
  - lib/prop_check/property.rb
59
59
  - lib/prop_check/property/configuration.rb
60
+ - lib/prop_check/property/output_formatter.rb
61
+ - lib/prop_check/property/shrinker.rb
60
62
  - lib/prop_check/version.rb
61
63
  - prop_check.gemspec
62
64
  homepage: https://github.com/Qqwy/ruby-prop_check/