Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d3beee9
add bytes gen and Co
n-osborne Jun 8, 2022
f2fa083
Update src/core/QCheck.mli
n-osborne Jun 9, 2022
dec48c8
add tests for bytes
n-osborne Jun 9, 2022
1584cf3
add bytes to QCheck2
n-osborne Jun 9, 2022
b3ee03e
Update src/core/QCheck2.mli
n-osborne Jun 10, 2022
ea3ce08
Update src/core/QCheck2.mli
n-osborne Jun 10, 2022
4d61e56
no optional gen in QCheck2
n-osborne Jun 10, 2022
712830c
Revert "no optional gen in QCheck2"
n-osborne Jun 14, 2022
96abba4
reverse fix on Eq.float (other PR)
n-osborne Jun 20, 2022
49c1335
naming consistency
n-osborne Jun 20, 2022
659a2b6
small_string no longer takes optional argument
n-osborne Jun 20, 2022
d955522
Iter.map version of bytes shrinker
n-osborne Jun 20, 2022
b4b7a89
smaller diff
n-osborne Jun 22, 2022
b7ca0da
expose missing string arbitrary
n-osborne Sep 13, 2022
c15418c
Update documentation for string arbitraries synomyms.
n-osborne Oct 26, 2022
0d6b8f8
Fix shrinker for QCheck.bytes_printable.
n-osborne Oct 26, 2022
2b41106
fix CHANGELOG and restore Float.equal
n-osborne Oct 28, 2022
f96b160
Merge branch 'bytes' of github.com:n-osborne/qcheck into n-osborne-bytes
jmid Nov 2, 2022
abf86cd
consistent QCheck.Gen.{bytes,string}_small{,_of} combinators
jmid Nov 2, 2022
fb1ea0e
consistent QCheck.{bytes,string}_of combinators
jmid Nov 2, 2022
d1cb85e
add consistent QCheck2.Gen.small_{bytes,string}{,_of} combinators
jmid Nov 2, 2022
c587c88
fix comment for QCheck2.Gen.bytes
jmid Nov 2, 2022
41ceeae
update CHANGELOG
jmid Nov 2, 2022
37d8d8a
add QCheck.{bytes,string}_small_of for consistency
jmid Nov 2, 2022
a14a767
update CHANGELOG
jmid Nov 2, 2022
b32cce6
update expected 32-bit output
jmid Nov 2, 2022
d4eba37
use 'synonym for' consistently
jmid Nov 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## 0.20

- add several new `bytes` combinators:
- `{QCheck,QCheck2}.Gen.{bytes_size,bytes,bytes_of,bytes_printable,bytes_small,bytes_small_of}`
- `QCheck.{Print,Shrink,Observable}.bytes`
- `QCheck2.{Print,Shrink}.bytes`
- `QCheck.{bytes_gen_of_size,bytes_of,bytes,bytes_small,bytes_small_of,bytes_of_size,bytes_printable}`
- add new `string` combinators and aliases:
- `{QCheck,QCheck2}.Gen.{string_small,string_small_of}`
- `QCheck.{string_small,string_small_of,string_of,string_printable,string_printable_of_size,string_small_printable,string_numeral,string_numeral_of_size}`
- `QCheck2.small_string` character generator argument is no more optional
- add an optional argument with conservative default to `Shrink.string`
- fix shrinkers in `QCheck.{printable_string,printable_string_of_size,small_printable_string,numeral_string,numeral_string_of_size}` [#257](https://github.com/c-cube/qcheck/issues/257)
- add `QCheck2.Gen.set_shrink` to modify the generator's shrinker
Expand Down
50 changes: 46 additions & 4 deletions src/core/QCheck.ml
Original file line number Diff line number Diff line change
Expand Up @@ -365,19 +365,31 @@ module Gen = struct
let printable st = printable_chars.[RS.int st (String.length printable_chars)]
let numeral st = char_of_int (48 + RS.int st 10)

let string_size ?(gen = char) size st =
let bytes_size ?(gen = char) size st =
let s = Bytes.create (size st) in
for i = 0 to Bytes.length s - 1 do
Bytes.set s i (gen st)
done;
s

let string_size ?(gen = char) size st =
let s = bytes_size ~gen size st in
Bytes.unsafe_to_string s

let bytes ?gen st = bytes_size ?gen nat st
let string ?gen st = string_size ?gen nat st
let bytes_of gen = bytes_size ~gen nat
let string_of gen = string_size ~gen nat
let bytes_printable = bytes_size ~gen:printable nat
let string_printable = string_size ~gen:printable nat
let string_readable = string_printable
let bytes_small st = bytes_size small_nat st
let bytes_small_of gen st = bytes_size ~gen small_nat st
let small_string ?gen st = string_size ?gen small_nat st
let small_list gen = list_size small_nat gen
let small_array gen = array_size small_nat gen
let string_small st = string_size small_nat st
let string_small_of gen st = string_size ~gen small_nat st

let join g st = (g st) st

Expand Down Expand Up @@ -462,6 +474,7 @@ module Print = struct
let int = string_of_int
let bool = string_of_bool
let float = string_of_float
let bytes = Bytes.to_string
let string s = s
let char c = String.make 1 c

Expand Down Expand Up @@ -780,6 +793,8 @@ module Shrink = struct
Buffer.clear buf;
yield s)

let bytes ?(shrink = char) b = Iter.map Bytes.of_string (string ~shrink (Bytes.to_string b))

let pair a b (x,y) yield =
a x (fun x' -> yield (x',y));
b y (fun y' -> yield (x,y'))
Expand Down Expand Up @@ -940,6 +955,7 @@ module Observable = struct
let int i = i land max_int
let bool b = if b then 1 else 2
let char x = Char.code x
let bytes (x:bytes) = Hashtbl.hash x
let string (x:string) = Hashtbl.hash x
let opt f = function
| None -> 42
Expand All @@ -953,6 +969,7 @@ module Observable = struct
type 'a t = 'a -> 'a -> bool

let int : int t = (=)
let bytes : bytes t = (=)
let string : string t = (=)
let bool : bool t = (=)
let float = Float.equal
Expand Down Expand Up @@ -986,6 +1003,7 @@ module Observable = struct
let bool : bool t = make ~hash:H.bool ~eq:Eq.bool Print.bool
let int : int t = make ~hash:H.int ~eq:Eq.int Print.int
let float : float t = make ~eq:Eq.float Print.float
let bytes = make ~hash:H.bytes ~eq:Eq.bytes Print.bytes
let string = make ~hash:H.string ~eq:Eq.string Print.string
let char = make ~hash:H.char ~eq:Eq.char Print.char

Expand Down Expand Up @@ -1109,16 +1127,34 @@ let printable_char =
let numeral_char =
make ~print:(sprintf "%C") ~small:(small_char '0') ~shrink:Shrink.char_numeral Gen.numeral

let bytes_gen_of_size size gen =
make ~shrink:Shrink.bytes ~small:Bytes.length
~print:(Print.bytes) (Gen.bytes_size ~gen size)
let bytes_of gen =
make ~shrink:Shrink.bytes ~small:Bytes.length
~print:(Print.bytes) (Gen.bytes ~gen)

let bytes = bytes_of Gen.char
let bytes_of_size size = bytes_gen_of_size size Gen.char
let bytes_small = bytes_gen_of_size Gen.small_nat Gen.char
let bytes_small_of gen = bytes_gen_of_size Gen.small_nat gen
let bytes_printable =
make ~shrink:(Shrink.bytes ~shrink:Shrink.char_printable) ~small:Bytes.length
~print:(Print.bytes) (Gen.bytes ~gen:Gen.printable)

let string_gen_of_size size gen =
make ~shrink:Shrink.string ~small:String.length
~print:(sprintf "%S") (Gen.string_size ~gen size)
let string_gen gen =
let string_of gen =
make ~shrink:Shrink.string ~small:String.length
~print:(sprintf "%S") (Gen.string ~gen)

let string = string_gen Gen.char
let string = string_of Gen.char
let string_of_size size = string_gen_of_size size Gen.char
let small_string = string_gen_of_size Gen.small_nat Gen.char
let string_small = string_gen_of_size Gen.small_nat Gen.char
let string_small_of gen = string_gen_of_size Gen.small_nat gen
let small_string = string_small
let string_gen = string_of

let printable_string =
make ~shrink:(Shrink.string ~shrink:Shrink.char_printable) ~small:String.length
Expand All @@ -1140,6 +1176,12 @@ let numeral_string_of_size size =
make ~shrink:(Shrink.string ~shrink:Shrink.char_numeral) ~small:String.length
~print:(sprintf "%S") (Gen.string_size ~gen:Gen.numeral size)

let string_printable = printable_string
let string_printable_of_size = printable_string_of_size
let string_small_printable = small_printable_string
let string_numeral = numeral_string
let string_numeral_of_size = numeral_string_of_size

let list_sum_ f l = List.fold_left (fun acc x-> f x+acc) 0 l

let mk_list a gen =
Expand Down
110 changes: 107 additions & 3 deletions src/core/QCheck.mli
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ module Gen : sig
(** All corner cases for int.
@since 0.6 *)

val (--) : int -> int -> int t (** Synonym to {!int_range}. *)
val (--) : int -> int -> int t (** Synonym for {!int_range}. *)

val ui32 : int32 t (** Generates (unsigned) [int32] values. *)

Expand Down Expand Up @@ -397,6 +397,34 @@ module Gen : sig
Example: [char_range 'a' 'z'] for all lower case ascii letters.
@since 0.13 *)

val bytes_size : ?gen:char t -> int t -> bytes t
(** Builds a bytes generator from a (non-negative) size generator.
Accepts an optional character generator (the default is {!char}).
@since NEXT_RELEASE *)

val bytes : ?gen:char t -> bytes t
(** Builds a bytes generator. Bytes size is generated by {!nat}.
Accepts an optional character generator (the default is {!char}).
See also {!bytes_of} and {!bytes_readable} for versions without
optional parameters.
@since NEXT_RELEASE *)

val bytes_of : char t -> bytes t
(** Builds a bytes generator using the given character generator.
@since NEXT_RELEASE *)

val bytes_printable : bytes t
(** Generator using the {!printable} character generator.
@since NEXT_RELEASE *)

val bytes_small : bytes t
(** Builds a bytes generator using the {!char} character generator, length is {!small_nat}
@since NEXT_RELEASE *)

val bytes_small_of : char t -> bytes t
(** Builds a bytes generator using the given character generator, length is {!small_nat}.
@since NEXT_RELEASE *)

val string_size : ?gen:char t -> int t -> string t
(** Builds a string generator from a (non-negative) size generator.
Accepts an optional character generator (the default is {!char}). *)
Expand Down Expand Up @@ -425,6 +453,14 @@ module Gen : sig
(** Builds a string generator, length is {!small_nat}
Accepts an optional character generator (the default is {!char}). *)

val string_small : string t
(** Builds a string generator using the {!char} character generator, length is {!small_nat}
@since NEXT_RELEASE *)

val string_small_of : char t -> string t
(** Builds a string generator using the given character generator, length is {!small_nat}.
@since NEXT_RELEASE *)

val small_list : 'a t -> 'a list t
(** Generates lists of small size (see {!small_nat}).
@since 0.5.3 *)
Expand Down Expand Up @@ -577,6 +613,8 @@ module Print : sig

val char : char t (** Character printer. *)

val bytes : bytes t (** Bytes printer. @since NEXT_RELEASE *)

val string : string t (** String printer. *)

val option : 'a t -> 'a option t (** Option printer. *)
Expand Down Expand Up @@ -645,7 +683,7 @@ module Iter : sig
val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val append : 'a t -> 'a t -> 'a t
val (<+>) : 'a t -> 'a t -> 'a t (** Synonym to {!append}. *)
val (<+>) : 'a t -> 'a t -> 'a t (** Synonym for {!append}. *)

val of_list : 'a list -> 'a t
val of_array : 'a array -> 'a t
Expand Down Expand Up @@ -709,6 +747,9 @@ module Shrink : sig

val option : 'a t -> 'a option t

val bytes : ?shrink:(char t) -> bytes t
(** @since NEXT_RELEASE *)

val string : ?shrink:(char t) -> string t

val filter : ('a -> bool) -> 'a t -> 'a t
Expand Down Expand Up @@ -811,6 +852,7 @@ module Observable : sig
val int : int t
val float : float t
val string : string t
val bytes : bytes t (** @since NEXT_RELEASE *)
val char : char t

val make :
Expand Down Expand Up @@ -1207,7 +1249,7 @@ val small_signed_int : int arbitrary
@since 0.5.2 *)

val (--) : int -> int -> int arbitrary
(** Synonym to {!int_range}. *)
(** Synonym for {!int_range}. *)

val int32 : int32 arbitrary
(** Int32 generator. Uniformly distributed. *)
Expand Down Expand Up @@ -1241,19 +1283,61 @@ val printable_char : char arbitrary
val numeral_char : char arbitrary
(** Uniformly distributed over ['0'..'9']. *)

val bytes_gen_of_size : int Gen.t -> char Gen.t -> bytes arbitrary
(** Builds a bytes generator from a (non-negative) size generator and a character generator.
@since NEXT_RELEASE *)

val bytes_of : char Gen.t -> bytes arbitrary
(** Generates bytes with a distribution of length of {!Gen.nat}.
@since NEXT_RELEASE *)

val bytes : bytes arbitrary
(** Generates bytes with a distribution of length of {!Gen.nat}
and distribution of characters of [char].
@since NEXT_RELEASE *)

val bytes_small : bytes arbitrary
(** Same as {!bytes} but with a small length (ie {!Gen.small_nat} ).
@since NEXT_RELEASE *)

val bytes_small_of : char Gen.t -> bytes arbitrary
(** Same as {!bytes_of} but with a small length (ie {!Gen.small_nat} ).
@since NEXT_RELEASE *)

val bytes_of_size : int Gen.t -> bytes arbitrary
(** Generates bytes with distribution of characters of [char].
@since NEXT_RELEASE *)

val bytes_printable : bytes arbitrary
(** Generates bytes with a distribution of length of {!Gen.nat}
and distribution of characters of [printable_char].
@since NEXT_RELEASE *)

val string_gen_of_size : int Gen.t -> char Gen.t -> string arbitrary
(** Builds a string generator from a (non-negative) size generator and a character generator. *)

val string_gen : char Gen.t -> string arbitrary
(** Generates strings with a distribution of length of {!Gen.nat}. *)

val string_of : char Gen.t -> string arbitrary
(** Synonym for {!string_gen} added for convenience.
@since NEXT_RELEASE *)

val string : string arbitrary
(** Generates strings with a distribution of length of {!Gen.nat}
and distribution of characters of [char]. *)

val small_string : string arbitrary
(** Same as {!string} but with a small length (ie {!Gen.small_nat} ). *)

val string_small : string arbitrary
(** Synonym for [small_string] added for convenience.
@since NEXT_RELEASE *)

val string_small_of : char Gen.t -> string arbitrary
(** Same as {!string_of} but with a small length (ie {!Gen.small_nat} ).
@since NEXT_RELEASE *)

val small_list : 'a arbitrary -> 'a list arbitrary
(** Generates lists of small size (see {!Gen.small_nat}).
@since 0.5.3 *)
Expand All @@ -1265,20 +1349,40 @@ val printable_string : string arbitrary
(** Generates strings with a distribution of length of {!Gen.nat}
and distribution of characters of [printable_char]. *)

val string_printable : string arbitrary
(** Synonym for [printable_string] added for convenience.
@since NEXT_RELEASE *)

val printable_string_of_size : int Gen.t -> string arbitrary
(** Generates strings with distribution of characters of [printable_char]. *)

val string_printable_of_size : int Gen.t -> string arbitrary
(** Synonym for [printable_string_of_size] added for convenience.
@since NEXT_RELEASE *)

val small_printable_string : string arbitrary
(** Generates strings with a length of [small_nat]
and distribution of characters of [printable_char]. *)

val string_small_printable : string arbitrary
(** Synonym for [small_printable_string] added for convenience.
@since NEXT_RELEASE *)

val numeral_string : string arbitrary
(** Generates strings with a distribution of length of {!Gen.nat}
and distribution of characters of [numeral_char]. *)

val string_numeral : string arbitrary
(** Synonym for [numeral_string] added for convenience.
@since NEXT_RELEASE *)

val numeral_string_of_size : int Gen.t -> string arbitrary
(** Generates strings with a distribution of characters of [numeral_char]. *)

val string_numeral_of_size : int Gen.t -> string arbitrary
(** Synonym for [numeral_string_of_size] added for convenience.
@since NEXT_RELEASE *)

val list : 'a arbitrary -> 'a list arbitrary
(** Generates lists with length generated by {!Gen.nat}. *)

Expand Down
Loading