prop_check 0.16.0 → 0.17.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 +3 -0
- data/README.md +1 -1
- data/lib/prop_check/generators.rb +70 -0
- data/lib/prop_check/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e59cf670bcc8cf9720d6278e984925c50e75ca65023459174f8b511d6421fb71
|
4
|
+
data.tar.gz: '088e0eb8d2d301bc3c03cc63bf68196969e8653cad37ff0b9d5d10f9b417a1ae'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de5808bced970e0c474367bf125837ac0eefa4aa752acb31cd74e884fea858b98fb518e9fe15493c81f8238e5e0490f3cbc855eda3a9b687196ca7830daad0aa
|
7
|
+
data.tar.gz: 312957d1ab0f990985f43ae7e4b0793df583ff2d3d8bb95573c11fe3e4d9c5f964d91050fe9bafb98ceb92dd6790d2ffce04257b02b0c152d75d9b4772b7423a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -64,7 +64,7 @@ Before releasing v1.0, we want to finish the following:
|
|
64
64
|
- [x] Builtin generation of `Set`s
|
65
65
|
- [x] Builtin generation of `Date`s, `Time`s and `DateTime`s.
|
66
66
|
- [x] Configuration option to resize all generators given to a particular Property instance.
|
67
|
-
- [
|
67
|
+
- [x] A simple way to create recursive generators
|
68
68
|
- [ ] A usage guide.
|
69
69
|
|
70
70
|
## Nice-to-haves
|
@@ -872,5 +872,75 @@ module PropCheck
|
|
872
872
|
end
|
873
873
|
end
|
874
874
|
end
|
875
|
+
|
876
|
+
##
|
877
|
+
# Helper to build recursive generators
|
878
|
+
#
|
879
|
+
# Given a `leaf_generator`
|
880
|
+
# and a block which:
|
881
|
+
# - is given a generator that generates subtrees.
|
882
|
+
# - it should return the generator for intermediate tree nodes.
|
883
|
+
#
|
884
|
+
# This is best explained with an example.
|
885
|
+
# Say we want to generate a binary tree of integers.
|
886
|
+
#
|
887
|
+
# If we have a struct representing internal nodes:
|
888
|
+
# ```ruby
|
889
|
+
# Branch = Struct.new(:left, :right, keyword_init: true)
|
890
|
+
# ```
|
891
|
+
# we can generate trees like so:
|
892
|
+
# ```ruby
|
893
|
+
# Generators.tree(Generators.integer) do |subtree_gen|
|
894
|
+
# G.instance(Branch, left: subtree_gen, right: subtree_gen)
|
895
|
+
# end
|
896
|
+
# ```
|
897
|
+
#
|
898
|
+
# As another example, consider generating lists of integers:
|
899
|
+
#
|
900
|
+
# >> G = PropCheck::Generators
|
901
|
+
# >> G.tree(G.integer) {|child_gen| G.array(child_gen) }.sample(5, size: 37, rng: Random.new(42))
|
902
|
+
# => [[7, [2, 3], -10], [[-2], [-2, [3]], [[2, 3]]], [], [0, [-2, -3]], [[1], -19, [], [1, -1], [1], [-1, -1], [1]]]
|
903
|
+
#
|
904
|
+
# And finally, here is how one could create a simple generator for parsed JSON data:
|
905
|
+
#
|
906
|
+
# ```ruby`
|
907
|
+
# G = PropCheck::Generators
|
908
|
+
# def json
|
909
|
+
# G.tree(G.one_of(G.boolean, G.real_float, G.ascii_string)) do |json_gen|
|
910
|
+
# G.one_of(G.array(json_gen), G.hash_of(G.ascii_string, json_gen))
|
911
|
+
# end
|
912
|
+
# end
|
913
|
+
# ```
|
914
|
+
#
|
915
|
+
def tree(leaf_generator, &block)
|
916
|
+
# Implementation is based on
|
917
|
+
# https://hexdocs.pm/stream_data/StreamData.html#tree/2
|
918
|
+
Generator.new do |size:, rng:, **other_kwargs|
|
919
|
+
nodes_on_each_level = random_pseudofactors(size.pow(1.1).to_i, rng)
|
920
|
+
result = nodes_on_each_level.reduce(leaf_generator) do |subtree_generator, nodes_on_this_level|
|
921
|
+
frequency(1 => subtree_generator,
|
922
|
+
2 => block.call(subtree_generator).resize { |_size| nodes_on_this_level })
|
923
|
+
end
|
924
|
+
|
925
|
+
result.generate(size: size, rng: rng, **other_kwargs)
|
926
|
+
end
|
927
|
+
end
|
928
|
+
|
929
|
+
private def random_pseudofactors(size, rng)
|
930
|
+
return [size].to_enum if size < 2
|
931
|
+
|
932
|
+
Enumerator.new do |yielder|
|
933
|
+
loop do
|
934
|
+
factor = rng.rand(1..(Math.log2(size).to_i))
|
935
|
+
if factor == 1
|
936
|
+
yielder << size
|
937
|
+
break
|
938
|
+
else
|
939
|
+
yielder << factor
|
940
|
+
size /= factor
|
941
|
+
end
|
942
|
+
end
|
943
|
+
end
|
944
|
+
end
|
875
945
|
end
|
876
946
|
end
|
data/lib/prop_check/version.rb
CHANGED