From d1f87ded880ab320dff502f0c2511b1425fe38e4 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Wed, 15 Sep 2021 15:41:02 +0200 Subject: [PATCH 1/3] Add tup2 to tup9 for Gen --- CHANGELOG.md | 4 + src/core/QCheck.ml | 351 +++++++++++++++++++++++++++++++++++++++++++ src/core/QCheck.mli | 179 ++++++++++++++++++++++ src/core/QCheck2.ml | 136 +++++++++++++++++ src/core/QCheck2.mli | 48 ++++++ 5 files changed, 718 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79419c1a..f7e9e20f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changes +## 0.19 + +- add tup2 to tup9 for generators + ## 0.18 This releases marks the addition of `QCheck2`, a module where generation diff --git a/src/core/QCheck.ml b/src/core/QCheck.ml index aa1b9341..74c3e312 100644 --- a/src/core/QCheck.ml +++ b/src/core/QCheck.ml @@ -42,6 +42,28 @@ let _opt_map_4 ~f a b c d = match a, b, c, d with | Some x, Some y, Some z, Some w -> Some (f x y z w) | _ -> None +let _opt_map_5 ~f a b c d e = match a, b, c, d, e with + | Some x, Some y, Some z, Some u, Some v -> Some (f x y z u v) + | _ -> None + +let _opt_map_6 ~f a b c d e g = match a, b, c, d, e, g with + | Some a, Some b, Some c, Some d, Some e, Some g -> Some (f a b c d e g) + | _ -> None + +let _opt_map_7 ~f a b c d e g h = match a, b, c, d, e, g, h with + | Some a, Some b, Some c, Some d, Some e, Some g, Some h -> Some (f a b c d e g h) + | _ -> None + +let _opt_map_8 ~f a b c d e g h i = match a, b, c, d, e, g, h, i with + | Some a, Some b, Some c, Some d, Some e, Some g, Some h, Some i -> + Some (f a b c d e g h i) + | _ -> None + +let _opt_map_9 ~f a b c d e g h i j = match a, b, c, d, e, g, h, i, j with + | Some a, Some b, Some c, Some d, Some e, Some g, Some h, Some i, Some j -> + Some (f a b c d e g h i j) + | _ -> None + let _opt_sum a b = match a, b with | Some _, _ -> a | None, _ -> b @@ -283,6 +305,27 @@ module Gen = struct let char st = char_of_int (RS.int st 256) + let tup2 = pair + + let tup3 = triple + + let tup4 = quad + + let tup5 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) : ('a * 'b * 'c * 'd * 'e) t = + (fun a b c d e -> (a, b, c, d, e)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 + + let tup6 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) : ('a * 'b * 'c * 'd * 'e * 'f) t = + (fun a b c d e f -> (a, b, c, d, e, f)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 + + let tup7 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) (g7 : 'g t) : ('a * 'b * 'c * 'd * 'e * 'f * 'g) t = + (fun a b c d e f g -> (a, b, c, d, e, f, g)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 <*> g7 + + let tup8 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) (g7 : 'g t) (g8 : 'h t) : ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) t = + (fun a b c d e f g h -> (a, b, c, d, e, f, g, h)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 <*> g7 <*> g8 + + let tup9 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) (g7 : 'g t) (g8 : 'h t) (g9 : 'i t) : ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) t = + (fun a b c d e f g h i -> (a, b, c, d, e, f, g, h, i)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 <*> g7 <*> g8 <*> g9 + let printable_chars = let l = 126-32+1 in let s = Bytes.create l in @@ -404,6 +447,121 @@ module Print = struct let quad a b c d (x,y,z,w) = Printf.sprintf "(%s, %s, %s, %s)" (a x) (b y) (c z) (d w) + let default = fun _ -> "" + + let tup2 p_a p_b (a, b) = + Printf.sprintf "(%s, %s)" (p_a a) (p_b b) + + let tup2_opt p_a p_b (a, b) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + tup2 p_a p_b (a, b) + + let tup3 p_a p_b (p_c) (a, b, c) = + Printf.sprintf "(%s, %s, %s)" (p_a a) (p_b b) (p_c c) + + let tup3_opt p_a p_b p_c (a, b, c) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + tup3 p_a p_b p_c (a, b, c) + + let tup4 p_a p_b p_c p_d (a, b, c, d) = + Printf.sprintf "(%s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + + let tup4_opt p_a p_b p_c p_d (a, b, c, d) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + tup4 p_a p_b p_c p_d (a, b, c, d) + + let tup5 p_a p_b p_c p_d p_e (a, b, c, d, e) = + Printf.sprintf "(%s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) + + let tup5_opt p_a p_b p_c p_d p_e (a, b, c, d, e) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + tup5 p_a p_b p_c p_d p_e (a, b, c, d, e) + + let tup6 p_a p_b p_c p_d p_e p_f (a, b, c, d, e, f) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + + let tup6_opt p_a p_b p_c p_d p_e p_f (a, b, c, d, e, f) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + tup6 p_a p_b p_c p_d p_e p_f (a, b, c, d, e, f) + + let tup7 p_a p_b p_c p_d p_e p_f p_g (a, b, c, d, e, f, g) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + (p_g g) + + let tup7_opt p_a p_b p_c p_d p_e p_f p_g (a, b, c, d, e, f, g) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + let p_g = Option.value ~default p_g in + tup7 p_a p_b p_c p_d p_e p_f p_g (a, b, c, d, e, f, g) + + let tup8 p_a p_b p_c p_d p_e p_f p_g p_h (a, b, c, d, e, f, g, h) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + (p_g g) (p_h h) + + let tup8_opt p_a p_b p_c p_d p_e p_f p_g p_h (a, b, c, d, e, f, g, h) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + let p_g = Option.value ~default p_g in + let p_h = Option.value ~default p_h in + tup8 p_a p_b p_c p_d p_e p_f p_g p_h (a, b, c, d, e, f, g, h) + + let tup9 p_a p_b p_c p_d p_e p_f p_g p_h p_i (a, b, c, d, e, f, g, h, i) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + (p_g g) (p_h h) + (p_i i) + + let tup9_opt p_a p_b p_c p_d p_e p_f p_g p_h p_i (a, b, c, d, e, f, g, h, i) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + let p_g = Option.value ~default p_g in + let p_h = Option.value ~default p_h in + let p_i = Option.value ~default p_i in + tup9 p_a p_b p_c p_d p_e p_f p_g p_h p_i (a, b, c, d, e, f, g, h, i) + let list pp l = let b = Buffer.create 25 in Buffer.add_char b '['; @@ -613,6 +771,127 @@ module Shrink = struct b y (fun y' -> yield (x,y',z,w)); c z (fun z' -> yield (x,y,z',w)); d w (fun w' -> yield (x,y,z,w')) + + let default = nil + + let tup2 = pair + + let tup2_opt a b = + let a = Option.value ~default a in + let b = Option.value ~default b in + tup2 a b + + let tup3 = triple + + let tup3_opt a b c = + let a = Option.value ~default a in + let b = Option.value ~default b in + let c = Option.value ~default c in + tup3 a b c + + let tup4 = quad + + let tup4_opt a b c d = + let a = Option.value ~default a in + let b = Option.value ~default b in + let c = Option.value ~default c in + let d = Option.value ~default d in + tup4 a b c d + + let tup5 a b c d e (a', b', c', d', e') yield = + a a' (fun x -> yield (x,b',c',d',e')); + b b' (fun x -> yield (a',x,c',d',e')); + c c' (fun x -> yield (a',b',x,d',e')); + d d' (fun x -> yield (a',b',c',x,e')); + e e' (fun x -> yield (a',b',c',d',x)) + + let tup5_opt a b c d e = + let a = Option.value ~default a in + let b = Option.value ~default b in + let c = Option.value ~default c in + let d = Option.value ~default d in + let e = Option.value ~default e in + tup5 a b c d e + + let tup6 a b c d e f (a', b', c', d', e', f') yield = + a a' (fun x -> yield (x,b',c',d',e',f')); + b b' (fun x -> yield (a',x,c',d',e',f')); + c c' (fun x -> yield (a',b',x,d',e',f')); + d d' (fun x -> yield (a',b',c',x,e',f')); + e e' (fun x -> yield (a',b',c',d',x,f')); + f f' (fun x -> yield (a',b',c',d',e',x)) + + let tup6_opt a b c d e f = + let a = Option.value ~default a in + let b = Option.value ~default b in + let c = Option.value ~default c in + let d = Option.value ~default d in + let e = Option.value ~default e in + let f = Option.value ~default f in + tup6 a b c d e f + + let tup7 a b c d e f g (a', b', c', d', e', f', g') yield = + a a' (fun x -> yield (x,b',c',d',e',f',g')); + b b' (fun x -> yield (a',x,c',d',e',f',g')); + c c' (fun x -> yield (a',b',x,d',e',f',g')); + d d' (fun x -> yield (a',b',c',x,e',f',g')); + e e' (fun x -> yield (a',b',c',d',x,f',g')); + f f' (fun x -> yield (a',b',c',d',e',x,g')); + g g' (fun x -> yield (a',b',c',d',e',f',x)) + + let tup7_opt a b c d e f g = + let a = Option.value ~default a in + let b = Option.value ~default b in + let c = Option.value ~default c in + let d = Option.value ~default d in + let e = Option.value ~default e in + let f = Option.value ~default f in + let g = Option.value ~default g in + tup7 a b c d e f g + + let tup8 a b c d e f g h (a', b', c', d', e', f', g', h') yield = + a a' (fun x -> yield (x,b',c',d',e',f',g',h')); + b b' (fun x -> yield (a',x,c',d',e',f',g',h')); + c c' (fun x -> yield (a',b',x,d',e',f',g',h')); + d d' (fun x -> yield (a',b',c',x,e',f',g',h')); + e e' (fun x -> yield (a',b',c',d',x,f',g',h')); + f f' (fun x -> yield (a',b',c',d',e',x,g',h')); + g g' (fun x -> yield (a',b',c',d',e',f',x,h')); + h h' (fun x -> yield (a',b',c',d',e',f',g',x)) + + let tup8_opt a b c d e f g h = + let a = Option.value ~default a in + let b = Option.value ~default b in + let c = Option.value ~default c in + let d = Option.value ~default d in + let e = Option.value ~default e in + let f = Option.value ~default f in + let g = Option.value ~default g in + let h = Option.value ~default h in + tup8 a b c d e f g h + + let tup9 a b c d e f g h i (a', b', c', d', e', f', g', h', i') yield = + a a' (fun x -> yield (x,b',c',d',e',f',g',h',i')); + b b' (fun x -> yield (a',x,c',d',e',f',g',h',i')); + c c' (fun x -> yield (a',b',x,d',e',f',g',h',i')); + d d' (fun x -> yield (a',b',c',x,e',f',g',h',i')); + e e' (fun x -> yield (a',b',c',d',x,f',g',h',i')); + f f' (fun x -> yield (a',b',c',d',e',x,g',h',i')); + g g' (fun x -> yield (a',b',c',d',e',f',x,h',i')); + h h' (fun x -> yield (a',b',c',d',e',f',g',x,i')); + i i' (fun x -> yield (a',b',c',d',e',f',g',h',x)) + + let tup9_opt a b c d e f g h i = + let a = Option.value ~default a in + let b = Option.value ~default b in + let c = Option.value ~default c in + let d = Option.value ~default d in + let e = Option.value ~default e in + let f = Option.value ~default f in + let g = Option.value ~default g in + let h = Option.value ~default h in + let i = Option.value ~default i in + tup9 a b c d e f g h i end (** {2 Observe Values} *) @@ -876,6 +1155,78 @@ let quad a b c d = (_opt_or d.shrink Shrink.nil)) (Gen.quad a.gen b.gen c.gen d.gen) +let tup2 a b= + make + ?small:(_opt_map_2 ~f:(fun a b (a', b') -> a a'+b b') a.small b.small) + ~print:(Print.tup2_opt a.print b.print) + ~shrink:(Shrink.pair (_opt_or a.shrink Shrink.nil) (_opt_or b.shrink Shrink.nil)) + (Gen.tup2 a.gen b.gen) + +let tup3 a b c = + make + ?small:(_opt_map_3 ~f:(fun a b c (a', b', c') -> + a a'+b b'+c c') a.small b.small c.small) + ~print:(Print.tup3_opt a.print b.print c.print) + ~shrink:(Shrink.tup3_opt a.shrink b.shrink c.shrink) + (Gen.tup3 a.gen b.gen c.gen) + +let tup4 a b c d = + make + ?small:(_opt_map_4 ~f:(fun a b c d (a', b', c', d') -> + a a'+b b'+c c'+d d') a.small b.small c.small d.small) + ~print:(Print.tup4_opt a.print b.print c.print d.print) + ~shrink:(Shrink.tup4_opt a.shrink b.shrink c.shrink d.shrink) + (Gen.tup4 a.gen b.gen c.gen d.gen) + +let tup5 a b c d e = + make + ?small:(_opt_map_5 ~f:(fun a b c d e (a', b', c', d', e') -> + a a'+b b'+c c'+d d'+e e') a.small b.small c.small d.small e.small) + ~print:(Print.tup5_opt a.print b.print c.print d.print e.print) + ~shrink:(Shrink.tup5_opt a.shrink b.shrink c.shrink d.shrink e.shrink) + (Gen.tup5 a.gen b.gen c.gen d.gen e.gen) + +let tup6 a b c d e f = + make + ?small:(_opt_map_6 ~f:(fun a b c d e f (a', b', c', d', e', f') -> + a a'+b b'+c c'+d d'+e e'+f f') a.small b.small c.small d.small e.small f.small) + ~print:(Print.tup6_opt a.print b.print c.print d.print e.print f.print) + ~shrink:(Shrink.tup6_opt a.shrink b.shrink c.shrink d.shrink e.shrink f.shrink) + (Gen.tup6 a.gen b.gen c.gen d.gen e.gen f.gen) + +let tup7 a b c d e f g = + make + ?small:(_opt_map_7 ~f:(fun a b c d e f g (a', b', c', d', e', f', g') -> + a a'+b b'+c c'+d d'+e e'+f f'+g g') + a.small b.small c.small d.small e.small f.small g.small) + ~print:(Print.tup7_opt + a.print b.print c.print d.print e.print f.print g.print) + ~shrink:(Shrink.tup7_opt + a.shrink b.shrink c.shrink d.shrink e.shrink f.shrink g.shrink) + (Gen.tup7 a.gen b.gen c.gen d.gen e.gen f.gen g.gen) + +let tup8 a b c d e f g h = + make + ?small:(_opt_map_8 ~f:(fun a b c d e f g h (a', b', c', d', e', f', g', h') -> + a a'+b b'+c c'+d d'+e e'+f f'+g g'+h h') + a.small b.small c.small d.small e.small f.small g.small h.small) + ~print:(Print.tup8_opt + a.print b.print c.print d.print e.print f.print g.print h.print) + ~shrink:(Shrink.tup8_opt + a.shrink b.shrink c.shrink d.shrink e.shrink f.shrink g.shrink h.shrink) + (Gen.tup8 a.gen b.gen c.gen d.gen e.gen f.gen g.gen h.gen) + +let tup9 a b c d e f g h i = + make + ?small:(_opt_map_9 ~f:(fun a b c d e f g h i (a', b', c', d', e', f', g', h', i') -> + a a'+b b'+c c'+d d'+e e'+f f'+g g'+h h'+i i') + a.small b.small c.small d.small e.small f.small g.small h.small i.small) + ~print:(Print.tup9_opt + a.print b.print c.print d.print e.print f.print g.print h.print i.print) + ~shrink:(Shrink.tup9_opt + a.shrink b.shrink c.shrink d.shrink e.shrink f.shrink g.shrink h.shrink i.shrink) + (Gen.tup9 a.gen b.gen c.gen d.gen e.gen f.gen g.gen h.gen i.gen) + let option ?ratio a = let g = Gen.opt ?ratio a.gen and shrink = _opt_map a.shrink ~f:Shrink.option diff --git a/src/core/QCheck.mli b/src/core/QCheck.mli index e86226cb..665bc001 100644 --- a/src/core/QCheck.mli +++ b/src/core/QCheck.mli @@ -353,6 +353,30 @@ module Gen : sig (** Generates quadruples. @since 0.5.1 *) + (** {3 Tuple of generators} *) + + (** {4 Shrinks on [gen1], then [gen2], then ... } *) + + val tup2 : 'a t -> 'b t -> ('a * 'b) t + + val tup3 : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t + + val tup4 : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t + + val tup5 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> ('a * 'b * 'c * 'd * 'e) t + + val tup6 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> + ('a * 'b * 'c * 'd * 'e * 'f) t + + val tup7 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g) t + + val tup8 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) t + + val tup9 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> 'i t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) t + val char : char t (** Generates characters upto character code 255. *) @@ -567,6 +591,34 @@ module Print : sig val comap : ('a -> 'b) -> 'b t -> 'a t (** [comap f p] maps [p], a printer of type ['b], to a printer of type ['a] by first converting a printed value using [f : 'a -> 'b]. *) + + val tup2 : 'a t -> 'b t -> ('a * 'b) t + (** 2-tuple printer. Expects printers for each component. *) + + val tup3 : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t + (** 3-tuple printer. Expects printers for each component. *) + + val tup4 : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t + (** 4-tuple printer. Expects printers for each component. *) + + val tup5 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> ('a * 'b * 'c * 'd * 'e) t + (** 5-tuple printer. Expects printers for each component. *) + + val tup6 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> + ('a * 'b * 'c * 'd * 'e * 'f) t + (** 6-tuple printer. Expects printers for each component. *) + + val tup7 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g) t + (** 7-tuple printer. Expects printers for each component. *) + + val tup8 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) t + (** 8-tuple printer. Expects printers for each component. *) + + val tup9 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> 'i t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) t + (** 9-tuple printer. Expects printers for each component. *) end (** {2 Iterators} @@ -682,6 +734,38 @@ module Shrink : sig val quad : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t (** Similar to {!pair} *) + + val tup2 : 'a t -> 'b t -> ('a * 'b) t + (** [tup2 a b] uses [a] to shrink the first element of tuples, + then tries to shrink the second element using [b]. + It is often better, when generating tuples, to put the "simplest" + element first (atomic type rather than list, etc.) because it will be + shrunk earlier. In particular, putting functions last might help. *) + + val tup3 : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t + (** Similar to {!tup2} *) + + val tup4 : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t + (** Similar to {!tup2} *) + + val tup5 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> ('a * 'b * 'c * 'd * 'e) t + (** Similar to {!tup2} *) + + val tup6 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> + ('a * 'b * 'c * 'd * 'e * 'f) t + (** Similar to {!tup2} *) + + val tup7 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g) t + (** Similar to {!tup2} *) + + val tup8 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) t + (** Similar to {!tup2} *) + + val tup9 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> 'i t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) t + (** Similar to {!tup2} *) end (** {2 Observe Values} *) @@ -1174,6 +1258,101 @@ val quad : 'a arbitrary -> 'b arbitrary -> 'c arbitrary -> 'd arbitrary -> ('a * (** Combines four generators into a generator of 4-tuples. Order matters for shrinking, see {!Shrink.pair} and the likes *) +(** {3 Tuple of generators} *) + +(** {4 Shrinks on [gen1], then [gen2], then ... } *) + +val tup2 : + 'a arbitrary -> + 'b arbitrary -> + ('a * 'b) arbitrary +(** Combines two generators into a 2-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + +val tup3 : + 'a arbitrary -> + 'b arbitrary -> + 'c arbitrary -> + ('a * 'b * 'c) arbitrary +(** Combines two generators into a 3-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + +val tup4 : + 'a arbitrary -> + 'b arbitrary -> + 'c arbitrary -> + 'd arbitrary -> + ('a * 'b * 'c * 'd) arbitrary +(** Combines two generators into a 4-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + +val tup5 : 'a arbitrary -> + 'b arbitrary -> + 'c arbitrary -> + 'd arbitrary -> + 'e arbitrary -> + ('a * 'b * 'c * 'd * 'e) arbitrary +(** Combines two generators into a 5-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + +val tup6 : + 'a arbitrary -> + 'b arbitrary -> + 'c arbitrary -> + 'd arbitrary -> + 'e arbitrary -> + 'f arbitrary -> + ('a * 'b * 'c * 'd * 'e * 'f) arbitrary +(** Combines two generators into a 6-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + +val tup7 : + 'a arbitrary -> + 'b arbitrary -> + 'c arbitrary -> + 'd arbitrary -> + 'e arbitrary -> + 'f arbitrary -> + 'g arbitrary -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g) arbitrary +(** Combines two generators into a 7-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + +val tup8 : + 'a arbitrary -> + 'b arbitrary -> + 'c arbitrary -> + 'd arbitrary -> + 'e arbitrary -> + 'f arbitrary -> + 'g arbitrary -> + 'h arbitrary -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) arbitrary +(** Combines two generators into a 8-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + +val tup9 : + 'a arbitrary -> + 'b arbitrary -> + 'c arbitrary -> + 'd arbitrary -> + 'e arbitrary -> + 'f arbitrary -> + 'g arbitrary -> + 'h arbitrary -> + 'i arbitrary -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) arbitrary +(** Combines two generators into a 9-tuple generator. + Order of elements can matter (w.r.t shrinking, see {!Shrink.tup2}) + Prints as many elements as available printers *) + val option : ?ratio:float -> 'a arbitrary -> 'a option arbitrary (** Choose between returning Some random value with optional ratio, or None. *) diff --git a/src/core/QCheck2.ml b/src/core/QCheck2.ml index a398baa4..b17c374d 100644 --- a/src/core/QCheck2.ml +++ b/src/core/QCheck2.ml @@ -600,6 +600,27 @@ module Gen = struct let quad (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) : ('a * 'b * 'c * 'd) t = (fun a b c d -> (a, b, c, d)) <$> g1 <*> g2 <*> g3 <*> g4 + let tup2 = pair + + let tup3 = triple + + let tup4 = quad + + let tup5 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) : ('a * 'b * 'c * 'd * 'e) t = + (fun a b c d e -> (a, b, c, d, e)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 + + let tup6 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) : ('a * 'b * 'c * 'd * 'e * 'f) t = + (fun a b c d e f -> (a, b, c, d, e, f)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 + + let tup7 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) (g7 : 'g t) : ('a * 'b * 'c * 'd * 'e * 'f * 'g) t = + (fun a b c d e f g -> (a, b, c, d, e, f, g)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 <*> g7 + + let tup8 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) (g7 : 'g t) (g8 : 'h t) : ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) t = + (fun a b c d e f g h -> (a, b, c, d, e, f, g, h)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 <*> g7 <*> g8 + + let tup9 (g1 : 'a t) (g2 : 'b t) (g3 : 'c t) (g4 : 'd t) (g5 : 'e t) (g6 : 'f t) (g7 : 'g t) (g8 : 'h t) (g9 : 'i t) : ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) t = + (fun a b c d e f g h i -> (a, b, c, d, e, f, g, h, i)) <$> g1 <*> g2 <*> g3 <*> g4 <*> g5 <*> g6 <*> g7 <*> g8 <*> g9 + (** Don't reuse {!int_range} which is much less performant (many more checks because of the possible range and origins). As a [string] generator may call this hundreds or even thousands of times for a single value, it's worth optimizing. *) let char : char t = fun st -> let c = RS.int st 256 in @@ -768,6 +789,121 @@ module Print = struct let contramap f p x = p (f x) let comap = contramap + + let default = fun _ -> "" + + let tup2 p_a p_b (a, b) = + Printf.sprintf "(%s, %s)" (p_a a) (p_b b) + + let tup2_opt p_a p_b (a, b) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + tup2 p_a p_b (a, b) + + let tup3 p_a p_b (p_c) (a, b, c) = + Printf.sprintf "(%s, %s, %s)" (p_a a) (p_b b) (p_c c) + + let tup3_opt p_a p_b p_c (a, b, c) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + tup3 p_a p_b p_c (a, b, c) + + let tup4 p_a p_b p_c p_d (a, b, c, d) = + Printf.sprintf "(%s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + + let tup4_opt p_a p_b p_c p_d (a, b, c, d) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + tup4 p_a p_b p_c p_d (a, b, c, d) + + let tup5 p_a p_b p_c p_d p_e (a, b, c, d, e) = + Printf.sprintf "(%s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) + + let tup5_opt p_a p_b p_c p_d p_e (a, b, c, d, e) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + tup5 p_a p_b p_c p_d p_e (a, b, c, d, e) + + let tup6 p_a p_b p_c p_d p_e p_f (a, b, c, d, e, f) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + + let tup6_opt p_a p_b p_c p_d p_e p_f (a, b, c, d, e, f) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + tup6 p_a p_b p_c p_d p_e p_f (a, b, c, d, e, f) + + let tup7 p_a p_b p_c p_d p_e p_f p_g (a, b, c, d, e, f, g) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + (p_g g) + + let tup7_opt p_a p_b p_c p_d p_e p_f p_g (a, b, c, d, e, f, g) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + let p_g = Option.value ~default p_g in + tup7 p_a p_b p_c p_d p_e p_f p_g (a, b, c, d, e, f, g) + + let tup8 p_a p_b p_c p_d p_e p_f p_g p_h (a, b, c, d, e, f, g, h) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + (p_g g) (p_h h) + + let tup8_opt p_a p_b p_c p_d p_e p_f p_g p_h (a, b, c, d, e, f, g, h) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + let p_g = Option.value ~default p_g in + let p_h = Option.value ~default p_h in + tup8 p_a p_b p_c p_d p_e p_f p_g p_h (a, b, c, d, e, f, g, h) + + let tup9 p_a p_b p_c p_d p_e p_f p_g p_h p_i (a, b, c, d, e, f, g, h, i) = + Printf.sprintf "(%s, %s, %s, %s, %s, %s, %s, %s, %s)" + (p_a a) (p_b b) + (p_c c) (p_d d) + (p_e e) (p_f f) + (p_g g) (p_h h) + (p_i i) + + let tup9_opt p_a p_b p_c p_d p_e p_f p_g p_h p_i (a, b, c, d, e, f, g, h, i) = + let p_a = Option.value ~default p_a in + let p_b = Option.value ~default p_b in + let p_c = Option.value ~default p_c in + let p_d = Option.value ~default p_d in + let p_e = Option.value ~default p_e in + let p_f = Option.value ~default p_f in + let p_g = Option.value ~default p_g in + let p_h = Option.value ~default p_h in + let p_i = Option.value ~default p_i in + tup9 p_a p_b p_c p_d p_e p_f p_g p_h p_i (a, b, c, d, e, f, g, h, i) end (** {2 Observe Values} *) diff --git a/src/core/QCheck2.mli b/src/core/QCheck2.mli index 11843651..0bf62ff5 100644 --- a/src/core/QCheck2.mli +++ b/src/core/QCheck2.mli @@ -626,6 +626,26 @@ module Gen : sig @since 0.5.1 *) + (** {3 Tuple of generators} *) + + (** {4 Shrinks on [gen1], then [gen2], then ... } *) + + val tup2 : 'a t -> 'b t -> ('a * 'b) t + + val tup3 : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t + + val tup4 : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t + + val tup5 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> ('a * 'b * 'c * 'd * 'e) t + + val tup6 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> ('a * 'b * 'c * 'd * 'e * 'f) t + + val tup7 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> ('a * 'b * 'c * 'd * 'e * 'f * 'g) t + + val tup8 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) t + + val tup9 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> 'i t -> ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) t + (** {3 Convert a structure of generator to a generator of structure} *) val flatten_l : 'a t list -> 'a list t @@ -1036,6 +1056,34 @@ module Print : sig val comap : ('b -> 'a) -> 'a t -> 'b t (** @deprecated use {!contramap} instead. *) + + val tup2 : 'a t -> 'b t -> ('a * 'b) t + (** 2-tuple printer. Expects printers for each component. *) + + val tup3 : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t + (** 3-tuple printer. Expects printers for each component. *) + + val tup4 : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t + (** 4-tuple printer. Expects printers for each component. *) + + val tup5 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> ('a * 'b * 'c * 'd * 'e) t + (** 5-tuple printer. Expects printers for each component. *) + + val tup6 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> + ('a * 'b * 'c * 'd * 'e * 'f) t + (** 6-tuple printer. Expects printers for each component. *) + + val tup7 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g) t + (** 7-tuple printer. Expects printers for each component. *) + + val tup8 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h) t + (** 8-tuple printer. Expects printers for each component. *) + + val tup9 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> 'f t -> 'g t -> 'h t -> 'i t -> + ('a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i) t + (** 9-tuple printer. Expects printers for each component. *) end (** Shrinking helper functions. *) From 7d41ebeeb717127f8735500405daebdf6928cc7f Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Fri, 3 Dec 2021 17:38:45 +0100 Subject: [PATCH 2/3] Relocate tests per module --- test/core/QCheck2_expect_test.ml | 127 +++++++++++++++++----------- test/core/QCheck_expect_test.ml | 137 ++++++++++++++++++------------- 2 files changed, 158 insertions(+), 106 deletions(-) diff --git a/test/core/QCheck2_expect_test.ml b/test/core/QCheck2_expect_test.ml index e6653e0f..48ec2fd6 100644 --- a/test/core/QCheck2_expect_test.ml +++ b/test/core/QCheck2_expect_test.ml @@ -79,6 +79,17 @@ module Overall = struct (fun x -> QCheck.assume (x mod 100 = 1); true) + + let tests = [ + passing; + failing; + error; + collect; + stats; + bad_assume_warn; + bad_assume_fail; + ] + end (* positive tests of the various generators *) @@ -130,6 +141,17 @@ module Generator = struct ~name:"tree_rev_is_involutive" IntTree.gen_tree (fun tree -> IntTree.(rev_tree (rev_tree tree)) = tree) + + let tests = [ + char_dist_issue_23; + char_test; + nat_test; + string_test; + list_test; + list_repeat_test; + array_repeat_test; + passing_tree_rev; + ] end (* negative tests that exercise shrinking behaviour *) @@ -236,6 +258,27 @@ module Shrink = struct Test.make ~name:"tree contains only 42" ~print:IntTree.print_tree IntTree.gen_tree (fun tree -> IntTree.contains_only_n tree 42) + + let tests = [ + (*test_fac_issue59;*) + big_bound_issue59; + long_shrink; + ints_arent_0_mod_3; + ints_are_0; + ints_smaller_209609; + nats_smaller_5001; + char_is_never_abcdef; + strings_are_empty; + string_never_has_000_char; + string_never_has_255_char; + lists_are_empty_issue_64; + list_shorter_10; + list_shorter_432; + list_shorter_4332; + list_equal_dupl; + list_unique_elems; + tree_contains_only_42; + ] end (* tests function generator and shrinker *) @@ -313,6 +356,15 @@ module Function = struct let f = Fn.apply f in List.fold_left f acc (is @ js) = List.fold_left f (List.fold_left f acc is) is) (*Typo*) + + let tests = [ + fail_pred_map_commute; + fail_pred_strings; + prop_foldleft_foldright; + prop_foldleft_foldright_uncurry; + prop_foldleft_foldright_uncurry_funlast; + fold_left_test; + ] end (* tests of (inner) find_example(_gen) behaviour *) @@ -337,6 +389,12 @@ module FindExample = struct let find_ex_uncaught_issue_99_2_succeed = Test.make ~name:"should_succeed_#99_2" ~count:10 Gen.int (fun i -> i <= max_int) + + let tests = [ + find_ex; + find_ex_uncaught_issue_99_1_fail; + find_ex_uncaught_issue_99_2_succeed; + ] end (* tests of statistics and histogram display *) @@ -401,62 +459,31 @@ module Stats = struct let tree_depth_test = let depth = ("depth", IntTree.depth) in Test.make ~name:"tree's depth" ~count:1000 ~stats:[depth] IntTree.gen_tree (fun _ -> true) + + let tests = + [ + bool_dist; + char_dist; + tree_depth_test + ] + @ string_len_tests + @ list_len_tests + @ array_len_tests + @ int_dist_tests + end (* Calling runners *) let () = QCheck_base_runner.set_seed 1234 let _ = - QCheck_base_runner.run_tests ~colors:false ([ - Overall.passing; - Overall.failing; - Overall.error; - Overall.collect; - Overall.stats; - Overall.bad_assume_warn; - Overall.bad_assume_fail; - Generator.char_dist_issue_23; - Generator.char_test; - Generator.nat_test; - Generator.string_test; - Generator.list_test; - Generator.list_repeat_test; - Generator.array_repeat_test; - Generator.passing_tree_rev; - (*Shrink.test_fac_issue59;*) - Shrink.big_bound_issue59; - Shrink.long_shrink; - Shrink.ints_arent_0_mod_3; - Shrink.ints_are_0; - Shrink.ints_smaller_209609; - Shrink.nats_smaller_5001; - Shrink.char_is_never_abcdef; - Shrink.strings_are_empty; - Shrink.string_never_has_000_char; - Shrink.string_never_has_255_char; - Shrink.lists_are_empty_issue_64; - Shrink.list_shorter_10; - Shrink.list_shorter_432; - Shrink.list_shorter_4332; - Shrink.list_equal_dupl; - Shrink.list_unique_elems; - Shrink.tree_contains_only_42; - Function.fail_pred_map_commute; - Function.fail_pred_strings; - Function.prop_foldleft_foldright; - Function.prop_foldleft_foldright_uncurry; - Function.prop_foldleft_foldright_uncurry_funlast; - Function.fold_left_test; - FindExample.find_ex; - FindExample.find_ex_uncaught_issue_99_1_fail; - FindExample.find_ex_uncaught_issue_99_2_succeed; - Stats.bool_dist; - Stats.char_dist; - Stats.tree_depth_test ] - @ Stats.string_len_tests - @ Stats.list_len_tests - @ Stats.array_len_tests - @ Stats.int_dist_tests) + QCheck_base_runner.run_tests ~colors:false ( + Overall.tests @ + Generator.tests @ + Shrink.tests @ + Function.tests @ + FindExample.tests @ + Stats.tests) let () = QCheck_base_runner.set_seed 153870556 let _ = QCheck_base_runner.run_tests ~colors:false [Stats.int_dist_empty_bucket] diff --git a/test/core/QCheck_expect_test.ml b/test/core/QCheck_expect_test.ml index 6282d761..cb6f34ad 100644 --- a/test/core/QCheck_expect_test.ml +++ b/test/core/QCheck_expect_test.ml @@ -81,6 +81,16 @@ module Overall = struct (fun x -> QCheck.assume (x mod 100 = 1); true) + + let tests = [ + passing; + failing; + error; + collect; + stats; + bad_assume_warn; + bad_assume_fail; + ] end (* positive tests of the various generators @@ -212,6 +222,23 @@ module Generator = struct Array.length arr = m && Array.for_all (fun k -> 0 < k) arr && Array.fold_left (+) 0 arr = n) + + let tests = [ + char_dist_issue_23; + char_test; + nat_test; + string_test; + list_test; + list_repeat_test; + array_repeat_test; + passing_tree_rev; + nat_split2_spec; + pos_split2_spec; + range_subset_spec; + nat_split_n_way; + nat_split_smaller; + pos_split; + ] end (* negative tests that exercise shrinking behaviour *) @@ -311,6 +338,26 @@ module Shrink = struct (list small_int) (fun xs -> let ys = List.sort_uniq Int.compare xs in print_list xs; List.length xs = List.length ys) + + let tests = [ + (*test_fac_issue59;*) + big_bound_issue59; + long_shrink; + ints_arent_0_mod_3; + ints_are_0; + ints_smaller_209609; + nats_smaller_5001; + char_is_never_abcdef; + strings_are_empty; + string_never_has_000_char; + string_never_has_255_char; + lists_are_empty_issue_64; + list_shorter_10; + list_shorter_432; + list_shorter_4332; + list_equal_dupl; + list_unique_elems; + ] end (* tests function generator and shrinker *) @@ -384,6 +431,15 @@ module Function = struct let f = Fn.apply f in List.fold_left f acc (is @ js) = List.fold_left f (List.fold_left f acc is) is) (*Typo*) + + let tests = [ + fail_pred_map_commute; + fail_pred_strings; + prop_foldleft_foldright; + prop_foldleft_foldright_uncurry; + prop_foldleft_foldright_uncurry_funlast; + fold_left_test; + ] end (* tests of (inner) find_example(_gen) behaviour *) @@ -407,6 +463,12 @@ module FindExample = struct let find_ex_uncaught_issue_99_2_succeed = Test.make ~name:"should_succeed_#99_2" ~count:10 int (fun i -> i <= max_int) + + let tests = [ + find_ex; + find_ex_uncaught_issue_99_1_fail; + find_ex_uncaught_issue_99_2_succeed; + ] end (* tests of statistics and histogram display *) @@ -475,68 +537,31 @@ module Stats = struct Test.make ~name:"range_subset_spec" ~count:5_000 (add_stat ("dist", fun a -> a.(0)) (make (Gen.range_subset ~size:1 0 20))) (fun a -> Array.length a = 1) + + let tests = + [ + bool_dist; + char_dist; + tree_depth_test; + range_subset_test + ] + @ string_len_tests + @ list_len_tests + @ array_len_tests + @ int_dist_tests end (* Calling runners *) let () = QCheck_base_runner.set_seed 1234 let _ = - QCheck_base_runner.run_tests ~colors:false ([ - Overall.passing; - Overall.failing; - Overall.error; - Overall.collect; - Overall.stats; - Overall.bad_assume_warn; - Overall.bad_assume_fail; - Generator.char_dist_issue_23; - Generator.char_test; - Generator.nat_test; - Generator.string_test; - Generator.list_test; - Generator.list_repeat_test; - Generator.array_repeat_test; - Generator.passing_tree_rev; - Generator.nat_split2_spec; - Generator.pos_split2_spec; - Generator.range_subset_spec; - Generator.nat_split_n_way; - Generator.nat_split_smaller; - Generator.pos_split; - (*Shrink.test_fac_issue59;*) - Shrink.big_bound_issue59; - Shrink.long_shrink; - Shrink.ints_arent_0_mod_3; - Shrink.ints_are_0; - Shrink.ints_smaller_209609; - Shrink.nats_smaller_5001; - Shrink.char_is_never_abcdef; - Shrink.strings_are_empty; - Shrink.string_never_has_000_char; - Shrink.string_never_has_255_char; - Shrink.lists_are_empty_issue_64; - Shrink.list_shorter_10; - Shrink.list_shorter_432; - Shrink.list_shorter_4332; - Shrink.list_equal_dupl; - Shrink.list_unique_elems; - Function.fail_pred_map_commute; - Function.fail_pred_strings; - Function.prop_foldleft_foldright; - Function.prop_foldleft_foldright_uncurry; - Function.prop_foldleft_foldright_uncurry_funlast; - Function.fold_left_test; - FindExample.find_ex; - FindExample.find_ex_uncaught_issue_99_1_fail; - FindExample.find_ex_uncaught_issue_99_2_succeed; - Stats.bool_dist; - Stats.char_dist; - Stats.tree_depth_test; - Stats.range_subset_test] - @ Stats.string_len_tests - @ Stats.list_len_tests - @ Stats.array_len_tests - @ Stats.int_dist_tests) + QCheck_base_runner.run_tests ~colors:false ( + Overall.tests @ + Generator.tests @ + Shrink.tests @ + Function.tests @ + FindExample.tests @ + Stats.tests) let () = QCheck_base_runner.set_seed 153870556 let _ = QCheck_base_runner.run_tests ~colors:false [Stats.int_dist_empty_bucket] From c830129c74f3798353bc77788e0dac3cf4f3d0a5 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Fri, 3 Dec 2021 18:20:14 +0100 Subject: [PATCH 3/3] Tests for tup2..9 generators and shrinkers --- test/core/QCheck2_expect_test.ml | 126 ++++++++++++++++++++++++++ test/core/QCheck_expect_test.ml | 118 ++++++++++++++++++++++++ test/core/qcheck2_output.txt.expected | 50 +++++++++- test/core/qcheck_output.txt.expected | 50 +++++++++- 4 files changed, 342 insertions(+), 2 deletions(-) diff --git a/test/core/QCheck2_expect_test.ml b/test/core/QCheck2_expect_test.ml index 48ec2fd6..fa710abf 100644 --- a/test/core/QCheck2_expect_test.ml +++ b/test/core/QCheck2_expect_test.ml @@ -142,6 +142,60 @@ module Generator = struct IntTree.gen_tree (fun tree -> IntTree.(rev_tree (rev_tree tree)) = tree) + let test_tup2 = + Test.make ~count:10 + ~name:"forall x in (0, 1): x = (0, 1)" + Gen.(tup2 (pure 0) (pure 1)) + (fun x -> x = (0, 1)) + + let test_tup3 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2): x = (0, 1, 2)" + Gen.(tup3 (pure 0) (pure 1) (pure 2)) + (fun x -> x = (0, 1, 2)) + + let test_tup4 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3): x = (0, 1, 2, 3)" + Gen.(tup4 (pure 0) (pure 1) (pure 2) (pure 3)) + (fun x -> x = (0, 1, 2, 3)) + + let test_tup5 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4): x = (0, 1, 2, 3, 4)" + Gen.(tup5 (pure 0) (pure 1) (pure 2) (pure 3) (pure 4)) + (fun x -> x = (0, 1, 2, 3, 4)) + + let test_tup6 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5): x = (0, 1, 2, 3, 4, 5)" + Gen.(tup6 (pure 0) (pure 1) (pure 2) (pure 3) (pure 4) (pure 5)) + (fun x -> x = (0, 1, 2, 3, 4, 5)) + + let test_tup7 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5, 6): x = (0, 1, 2, 3, 4, 5, 6)" + Gen.(tup7 + (pure 0) (pure 1) (pure 2) (pure 3) (pure 4) + (pure 5) (pure 6)) + (fun x -> x = (0, 1, 2, 3, 4, 5, 6)) + + let test_tup8 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5, 6, 7): x = (0, 1, 2, 3, 4, 5, 6, 7)" + Gen.(tup8 + (pure 0) (pure 1) (pure 2) (pure 3) (pure 4) + (pure 5) (pure 6) (pure 7)) + (fun x -> x = (0, 1, 2, 3, 4, 5, 6, 7)) + + let test_tup9 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5, 6, 7, 8): x = (0, 1, 2, 3, 4, 5, 6, 7, 8)" + Gen.(tup9 + (pure 0) (pure 1) (pure 2) (pure 3) (pure 4) + (pure 5) (pure 6) (pure 7) (pure 8)) + (fun x -> x = (0, 1, 2, 3, 4, 5, 6, 7, 8)) + let tests = [ char_dist_issue_23; char_test; @@ -151,6 +205,14 @@ module Generator = struct list_repeat_test; array_repeat_test; passing_tree_rev; + test_tup2; + test_tup3; + test_tup4; + test_tup5; + test_tup6; + test_tup7; + test_tup8; + test_tup9; ] end @@ -259,6 +321,62 @@ module Shrink = struct IntTree.gen_tree (fun tree -> IntTree.contains_only_n tree 42) + let test_tup2 = + Test.make + ~print:Print.(tup2 int int) + ~name:"forall (a, b) in nat: a < b" + Gen.(tup2 small_int small_int) + (fun (a, b) -> a < b) + + let test_tup3 = + Test.make + ~print:Print.(tup3 int int int) + ~name:"forall (a, b, c) in nat: a < b < c" + Gen.(tup3 small_int small_int small_int) + (fun (a, b, c) -> a < b && b < c) + + let test_tup4 = + Test.make + ~print:Print.(tup4 int int int int) + ~name:"forall (a, b, c, d) in nat: a < b < c < d" + Gen.(tup4 small_int small_int small_int small_int) + (fun (a, b, c, d) -> a < b && b < c && c < d) + + let test_tup5 = + Test.make + ~print:Print.(tup5 int int int int int) + ~name:"forall (a, b, c, d, e) in nat: a < b < c < d < e" + Gen.(tup5 small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e) -> a < b && b < c && c < d && d < e) + + let test_tup6 = + Test.make + ~print:Print.(tup6 int int int int int int) + ~name:"forall (a, b, c, d, e, f) in nat: a < b < c < d < e < f" + Gen.(tup6 small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f) -> a < b && b < c && c < d && d < e && e < f) + + let test_tup7 = + Test.make + ~print:Print.(tup7 int int int int int int int) + ~name:"forall (a, b, c, d, e, f, g) in nat: a < b < c < d < e < f < g" + Gen.(tup7 small_int small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f, g) -> a < b && b < c && c < d && d < e && e < f && f < g) + + let test_tup8 = + Test.make + ~print:Print.(tup8 int int int int int int int int) + ~name:"forall (a, b, c, d, e, f, g, h) in nat: a < b < c < d < e < f < g < h" + Gen.(tup8 small_int small_int small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f, g, h) -> a < b && b < c && c < d && d < e && e < f && f < g && g < h) + + let test_tup9 = + Test.make + ~print:Print.(tup9 int int int int int int int int int) + ~name:"forall (a, b, c, d, e, f, g, h, i) in nat: a < b < c < d < e < f < g < h < i" + Gen.(tup9 small_int small_int small_int small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f, g, h, i) -> a < b && b < c && c < d && d < e && e < f && f < g && g < h && h < i) + let tests = [ (*test_fac_issue59;*) big_bound_issue59; @@ -278,6 +396,14 @@ module Shrink = struct list_equal_dupl; list_unique_elems; tree_contains_only_42; + test_tup2; + test_tup3; + test_tup4; + test_tup5; + test_tup6; + test_tup7; + test_tup8; + test_tup9; ] end diff --git a/test/core/QCheck_expect_test.ml b/test/core/QCheck_expect_test.ml index cb6f34ad..28fc0a25 100644 --- a/test/core/QCheck_expect_test.ml +++ b/test/core/QCheck_expect_test.ml @@ -223,6 +223,60 @@ module Generator = struct && Array.for_all (fun k -> 0 < k) arr && Array.fold_left (+) 0 arr = n) + let test_tup2 = + Test.make ~count:10 + ~name:"forall x in (0, 1): x = (0, 1)" + (tup2 (always 0) (always 1)) + (fun x -> x = (0, 1)) + + let test_tup3 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2): x = (0, 1, 2)" + (tup3 (always 0) (always 1) (always 2)) + (fun x -> x = (0, 1, 2)) + + let test_tup4 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3): x = (0, 1, 2, 3)" + (tup4 (always 0) (always 1) (always 2) (always 3)) + (fun x -> x = (0, 1, 2, 3)) + + let test_tup5 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4): x = (0, 1, 2, 3, 4)" + (tup5 (always 0) (always 1) (always 2) (always 3) (always 4)) + (fun x -> x = (0, 1, 2, 3, 4)) + + let test_tup6 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5): x = (0, 1, 2, 3, 4, 5)" + (tup6 (always 0) (always 1) (always 2) (always 3) (always 4) (always 5)) + (fun x -> x = (0, 1, 2, 3, 4, 5)) + + let test_tup7 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5, 6): x = (0, 1, 2, 3, 4, 5, 6)" + (tup7 + (always 0) (always 1) (always 2) (always 3) (always 4) + (always 5) (always 6)) + (fun x -> x = (0, 1, 2, 3, 4, 5, 6)) + + let test_tup8 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5, 6, 7): x = (0, 1, 2, 3, 4, 5, 6, 7)" + (tup8 + (always 0) (always 1) (always 2) (always 3) (always 4) + (always 5) (always 6) (always 7)) + (fun x -> x = (0, 1, 2, 3, 4, 5, 6, 7)) + + let test_tup9 = + Test.make ~count:10 + ~name:"forall x in (0, 1, 2, 3, 4, 5, 6, 7, 8): x = (0, 1, 2, 3, 4, 5, 6, 7, 8)" + (tup9 + (always 0) (always 1) (always 2) (always 3) (always 4) + (always 5) (always 6) (always 7) (always 8)) + (fun x -> x = (0, 1, 2, 3, 4, 5, 6, 7, 8)) + let tests = [ char_dist_issue_23; char_test; @@ -238,6 +292,14 @@ module Generator = struct nat_split_n_way; nat_split_smaller; pos_split; + test_tup2; + test_tup3; + test_tup4; + test_tup5; + test_tup6; + test_tup7; + test_tup8; + test_tup9; ] end @@ -339,6 +401,54 @@ module Shrink = struct (fun xs -> let ys = List.sort_uniq Int.compare xs in print_list xs; List.length xs = List.length ys) + let test_tup2 = + Test.make + ~name:"forall (a, b) in nat: a < b" + (tup2 small_int small_int) + (fun (a, b) -> a < b) + + let test_tup3 = + Test.make + ~name:"forall (a, b, c) in nat: a < b < c" + (tup3 small_int small_int small_int) + (fun (a, b, c) -> a < b && b < c) + + let test_tup4 = + Test.make + ~name:"forall (a, b, c, d) in nat: a < b < c < d" + (tup4 small_int small_int small_int small_int) + (fun (a, b, c, d) -> a < b && b < c && c < d) + + let test_tup5 = + Test.make + ~name:"forall (a, b, c, d, e) in nat: a < b < c < d < e" + (tup5 small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e) -> a < b && b < c && c < d && d < e) + + let test_tup6 = + Test.make + ~name:"forall (a, b, c, d, e, f) in nat: a < b < c < d < e < f" + (tup6 small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f) -> a < b && b < c && c < d && d < e && e < f) + + let test_tup7 = + Test.make + ~name:"forall (a, b, c, d, e, f, g) in nat: a < b < c < d < e < f < g" + (tup7 small_int small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f, g) -> a < b && b < c && c < d && d < e && e < f && f < g) + + let test_tup8 = + Test.make + ~name:"forall (a, b, c, d, e, f, g, h) in nat: a < b < c < d < e < f < g < h" + (tup8 small_int small_int small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f, g, h) -> a < b && b < c && c < d && d < e && e < f && f < g && g < h) + + let test_tup9 = + Test.make + ~name:"forall (a, b, c, d, e, f, g, h, i) in nat: a < b < c < d < e < f < g < h < i" + (tup9 small_int small_int small_int small_int small_int small_int small_int small_int small_int) + (fun (a, b, c, d, e, f, g, h, i) -> a < b && b < c && c < d && d < e && e < f && f < g && g < h && h < i) + let tests = [ (*test_fac_issue59;*) big_bound_issue59; @@ -357,6 +467,14 @@ module Shrink = struct list_shorter_4332; list_equal_dupl; list_unique_elems; + test_tup2; + test_tup3; + test_tup4; + test_tup5; + test_tup6; + test_tup7; + test_tup8; + test_tup9; ] end diff --git a/test/core/qcheck2_output.txt.expected b/test/core/qcheck2_output.txt.expected index 7c04fa8b..208dfb3d 100644 --- a/test/core/qcheck2_output.txt.expected +++ b/test/core/qcheck2_output.txt.expected @@ -348,6 +348,54 @@ Leaf 0 --- Failure -------------------------------------------------------------------- +Test forall (a, b) in nat: a < b failed (6 shrink steps): + +(0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c) in nat: a < b < c failed (3 shrink steps): + +(0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d) in nat: a < b < c < d failed (4 shrink steps): + +(0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e) in nat: a < b < c < d < e failed (5 shrink steps): + +(0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f) in nat: a < b < c < d < e < f failed (6 shrink steps): + +(0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f, g) in nat: a < b < c < d < e < f < g failed (7 shrink steps): + +(0, 0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f, g, h) in nat: a < b < c < d < e < f < g < h failed (8 shrink steps): + +(0, 0, 0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f, g, h, i) in nat: a < b < c < d < e < f < g < h < i failed (9 shrink steps): + +(0, 0, 0, 0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + Test fail_pred_map_commute failed (16 shrink steps): ([2], {_ -> 0}, {1 -> false; 2 -> true; _ -> false}) @@ -934,7 +982,7 @@ stats dist: 4150517416584649600.. 4611686018427387903: ################# 189 ================================================================================ 1 warning(s) -failure (27 tests failed, 1 tests errored, ran 67 tests) +failure (35 tests failed, 1 tests errored, ran 83 tests) random seed: 153870556 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/test/core/qcheck_output.txt.expected b/test/core/qcheck_output.txt.expected index 4d55d633..6b455dda 100644 --- a/test/core/qcheck_output.txt.expected +++ b/test/core/qcheck_output.txt.expected @@ -277,6 +277,54 @@ Test lists have unique elems failed (7 shrink steps): --- Failure -------------------------------------------------------------------- +Test forall (a, b) in nat: a < b failed (13 shrink steps): + +(0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c) in nat: a < b < c failed (15 shrink steps): + +(0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d) in nat: a < b < c < d failed (23 shrink steps): + +(0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e) in nat: a < b < c < d < e failed (28 shrink steps): + +(0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f) in nat: a < b < c < d < e < f failed (30 shrink steps): + +(0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f, g) in nat: a < b < c < d < e < f < g failed (31 shrink steps): + +(0, 0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f, g, h) in nat: a < b < c < d < e < f < g < h failed (35 shrink steps): + +(0, 0, 0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + +Test forall (a, b, c, d, e, f, g, h, i) in nat: a < b < c < d < e < f < g < h < i failed (42 shrink steps): + +(0, 0, 0, 0, 0, 0, 0, 0, 0) + +--- Failure -------------------------------------------------------------------- + Test fail_pred_map_commute failed (127 shrink steps): ([3], {_ -> 0}, {3 -> false; _ -> true}) @@ -889,7 +937,7 @@ stats dist: 4150517416584649600.. 4611686018427387903: ################# 189 ================================================================================ 1 warning(s) -failure (26 tests failed, 1 tests errored, ran 73 tests) +failure (34 tests failed, 1 tests errored, ran 89 tests) random seed: 153870556 +++ Stats for int_dist_empty_bucket ++++++++++++++++++++++++++++++++++++++++++++++++++++++++