lib/prop_check/generators.rb in prop_check-0.10.4 vs lib/prop_check/generators.rb in prop_check-0.11.0

- old
+ new

@@ -225,34 +225,60 @@ ## # Generates an array of elements, where each of the elements # is generated by `element_generator`. # # Shrinks to shorter arrays (with shrunken elements). + # Accepted keyword arguments: # + # `empty:` When false, behaves the same as `min: 1` + # `min:` Ensures at least this many elements are generated. (default: 0) + # `max:` Ensures at most this many elements are generated. When nil, an arbitrary count is used instead. (default: nil) + # + # + # >> Generators.array(Generators.positive_integer).sample(5, size: 1, rng: Random.new(42)) + # => [[2], [2], [2], [1], [2]] # >> Generators.array(Generators.positive_integer).sample(5, size: 10, rng: Random.new(42)) # => [[10, 5, 1, 4], [5, 9, 1, 1, 11, 8, 4, 9, 11, 10], [6], [11, 11, 2, 2, 7, 2, 6, 5, 5], [2, 10, 9, 7, 9, 5, 11, 3]] - def array(element_generator) - nonnegative_integer.bind do |generator| - generators = (0...generator).map do + # + # >> Generators.array(Generators.positive_integer, empty: true).sample(5, size: 1, rng: Random.new(1)) + # => [[], [2], [], [], [2]] + # >> Generators.array(Generators.positive_integer, empty: false).sample(5, size: 1, rng: Random.new(1)) + # => [[2], [1], [2], [1], [1]] + + + def array(element_generator, min: 0, max: nil, empty: true) + min = 1 if min.zero? && !empty + + res = proc do |count| + count = min + 1 if count < min + count += 1 if count == min && min != 0 + generators = (min...count).map do element_generator.clone end tuple(*generators) end + + if max.nil? + nonnegative_integer.bind(&res) + else + proc.call(max) + end end + ## # Generates a hash of key->values, # where each of the keys is made using the `key_generator` # and each of the values using the `value_generator`. # # Shrinks to hashes with less key/value pairs. # # >> Generators.hash(Generators.printable_ascii_string, Generators.positive_integer).sample(5, size: 3, rng: Random.new(42)) # => [{""=>2, "g\\4"=>4, "rv"=>2}, {"7"=>2}, {"!"=>1, "E!"=>1}, {"kY5"=>2}, {}] - def hash(key_generator, value_generator) - array(tuple(key_generator, value_generator)) + def hash(key_generator, value_generator, **kwargs) + array(tuple(key_generator, value_generator), **kwargs) .map(&:to_h) end @alphanumeric_chars = [('a'..'z'), ('A'..'Z'), ('0'..'9')].flat_map(&:to_a).freeze @@ -274,12 +300,12 @@ # # Shrinks towards fewer characters, and towards lowercase 'a'. # # >> Generators.alphanumeric_string.sample(5, size: 10, rng: Random.new(42)) # => ["ZCoQ", "8uM", "wkkx0JNx", "v0bxRDLb", "Gl5v8RyWA6"] - def alphanumeric_string - array(alphanumeric_char).map(&:join) + def alphanumeric_string(**kwargs) + array(alphanumeric_char, **kwargs).map(&:join) end @printable_ascii_chars = (' '..'~').to_a.freeze ## @@ -300,12 +326,12 @@ # # Shrinks towards fewer characters, and towards ' '. # # >> Generators.printable_ascii_string.sample(5, size: 10, rng: Random.new(42)) # => ["S|.g", "rvjjw7\"5T!", "=", "!_[4@", "Y"] - def printable_ascii_string - array(printable_ascii_char).map(&:join) + def printable_ascii_string(**kwargs) + array(printable_ascii_char, **kwargs).map(&:join) end @ascii_chars = [ @printable_ascii_chars, [ @@ -339,12 +365,12 @@ # # Shrinks towards fewer characters, and towards '\n'. # # >> Generators.ascii_string.sample(5, size: 10, rng: Random.new(42)) # => ["S|.g", "drvjjw\b\a7\"", "!w=E!_[4@k", "x", "zZI{[o"] - def ascii_string - array(ascii_char).map(&:join) + def ascii_string(**kwargs) + array(ascii_char, **kwargs).map(&:join) end @printable_chars = [ @ascii_chars, "\u{A0}".."\u{D7FF}", @@ -370,12 +396,12 @@ # # Shrinks towards shorter strings, and towards characters with lower codepoints, e.g. ASCII # # >> Generators.printable_string.sample(5, size: 10, rng: Random.new(42)) # => ["", "Ȍ", "𐁂", "Ȕ", ""] - def printable_string - array(printable_char).map(&:join) + def printable_string(**kwargs) + array(printable_char, **kwargs).map(&:join) end ## # Generates a single unicode character # (both printable and non-printable). @@ -396,11 +422,11 @@ # # Shrinks towards characters with lower codepoints, e.g. ASCII # # >> Generators.string.sample(5, size: 10, rng: Random.new(42)) # => ["\u{A3DB3}𠍜\u{3F46A}\u{1AEBC}", "􍙦𡡹󴇒\u{DED74}𪱣\u{43E97}ꂂ\u{50695}􏴴\u{C0301}", "\u{4FD9D}", "\u{C14BF}\u{193BB}𭇋󱣼\u{76B58}", "𦐺\u{9FDDB}\u{80ABB}\u{9E3CF}𐂽\u{14AAE}"] - def string - array(char).map(&:join) + def string(**kwargs) + array(char, **kwargs).map(&:join) end ## # Generates either `true` or `false` #