mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-05 19:00:31 -05:00
239 lines
7.3 KiB
OCaml
239 lines
7.3 KiB
OCaml
open CCHeap
|
|
module T = (val Containers_testlib.make ~__FILE__ ())
|
|
include T
|
|
|
|
(* A QCheck generator for natural numbers that are not too large (larger than
|
|
* [small_nat] but smaller than [big_nat]), with a bias towards smaller numbers.
|
|
* This also happens to be what QCheck uses for picking a length for a list
|
|
* generated by [QCheck.list].
|
|
* QCheck defines this generator under the name [nat] but does not expose it. *)
|
|
let medium_nat =
|
|
Q.make ~print:Q.Print.int ~shrink:Q.Shrink.int
|
|
~small:(fun _ -> 1)
|
|
(fun st ->
|
|
let p = Random.State.float st 1. in
|
|
if p < 0.5 then
|
|
Random.State.int st 10
|
|
else if p < 0.75 then
|
|
Random.State.int st 100
|
|
else if p < 0.95 then
|
|
Random.State.int st 1_000
|
|
else
|
|
Random.State.int st 10_000)
|
|
|
|
let list_delete_first (x0 : int) (xs : int list) : int list =
|
|
let rec aux acc xs =
|
|
match xs with
|
|
| [] -> List.rev acc
|
|
| x :: xs' when x = x0 -> List.rev_append acc xs'
|
|
| x :: xs' -> aux (x :: acc) xs'
|
|
in
|
|
aux [] xs
|
|
|
|
module H = CCHeap.Make (struct
|
|
type t = int
|
|
|
|
let leq x y = x <= y
|
|
end)
|
|
;;
|
|
|
|
t ~name:"of_list, find_min_exn, take_exn" @@ fun () ->
|
|
let h = H.of_list [ 5; 4; 3; 4; 1; 42; 0 ] in
|
|
assert_equal ~printer:string_of_int 0 (H.find_min_exn h);
|
|
let h, x = H.take_exn h in
|
|
assert_equal ~printer:string_of_int 0 x;
|
|
assert_equal ~printer:string_of_int 1 (H.find_min_exn h);
|
|
let h, x = H.take_exn h in
|
|
assert_equal ~printer:string_of_int 1 x;
|
|
assert_equal ~printer:string_of_int 3 (H.find_min_exn h);
|
|
let h, x = H.take_exn h in
|
|
assert_equal ~printer:string_of_int 3 x;
|
|
assert_equal ~printer:string_of_int 4 (H.find_min_exn h);
|
|
let h, x = H.take_exn h in
|
|
assert_equal ~printer:string_of_int 4 x;
|
|
assert_equal ~printer:string_of_int 4 (H.find_min_exn h);
|
|
let h, x = H.take_exn h in
|
|
assert_equal ~printer:string_of_int 4 x;
|
|
assert_equal ~printer:string_of_int 5 (H.find_min_exn h);
|
|
let h, x = H.take_exn h in
|
|
assert_equal ~printer:string_of_int 5 x;
|
|
assert_equal ~printer:string_of_int 42 (H.find_min_exn h);
|
|
let h, x = H.take_exn h in
|
|
assert_equal ~printer:string_of_int 42 x;
|
|
assert_raises (( = ) H.Empty) (fun () -> H.find_min_exn h);
|
|
assert_raises (( = ) H.Empty) (fun () -> H.take_exn h);
|
|
true
|
|
;;
|
|
|
|
q ~name:"of_list, to_list" ~count:30
|
|
Q.(list medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list |> H.to_list |> List.sort CCInt.compare
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"of_list, to_list_sorted" ~count:30
|
|
Q.(list medium_nat)
|
|
(fun l -> l |> H.of_list |> H.to_list_sorted = (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
(* The remaining tests assume the correctness of
|
|
[of_list], [to_list], [to_list_sorted]. *)
|
|
|
|
q ~name:"size" ~count:30
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l -> l |> H.of_list |> H.size = (l |> List.length))
|
|
;;
|
|
|
|
q ~name:"insert"
|
|
Q.(pair medium_nat (list medium_nat))
|
|
(fun (x, l) ->
|
|
l |> H.of_list |> H.insert x |> H.to_list_sorted
|
|
= (x :: l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"merge"
|
|
Q.(pair (list medium_nat) (list medium_nat))
|
|
(fun (l1, l2) ->
|
|
H.merge (H.of_list l1) (H.of_list l2)
|
|
|> H.to_list_sorted
|
|
= (l1 @ l2 |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"add_list"
|
|
Q.(pair (list medium_nat) (list medium_nat))
|
|
(fun (l1, l2) ->
|
|
H.add_list (H.of_list l1) l2
|
|
|> H.to_list_sorted
|
|
= (l1 @ l2 |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"delete_one"
|
|
Q.(pair medium_nat (list medium_nat))
|
|
(fun (x, l) ->
|
|
l |> H.of_list |> H.delete_one ( = ) x |> H.to_list_sorted
|
|
= (l |> list_delete_first x |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"delete_all"
|
|
Q.(pair medium_nat (list medium_nat))
|
|
(fun (x, l) ->
|
|
l |> H.of_list |> H.delete_all ( = ) x |> H.to_list_sorted
|
|
= (l |> List.filter (( <> ) x) |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"filter"
|
|
Q.(list medium_nat)
|
|
(fun l ->
|
|
let p x = x mod 2 = 0 in
|
|
let l' = l |> H.of_list |> H.filter p |> H.to_list in
|
|
List.for_all p l' && List.length l' = List.length (List.filter p l))
|
|
;;
|
|
|
|
t ~name:"physical equality" @@ fun () ->
|
|
let h = H.of_list [ 5; 4; 3; 4; 1; 42; 0 ] in
|
|
assert_bool "physical equality of merge with left empty"
|
|
(CCEqual.physical h (H.merge H.empty h));
|
|
assert_bool "physical equality of merge with right empty"
|
|
(CCEqual.physical h (H.merge h H.empty));
|
|
assert_bool "physical equality of delete_one with element lesser than min"
|
|
(CCEqual.physical h (H.delete_one ( = ) (-999) h));
|
|
assert_bool "physical equality of delete_one with element between min and max"
|
|
(CCEqual.physical h (H.delete_one ( = ) 2 h));
|
|
assert_bool "physical equality of delete_one with element greater than max"
|
|
(CCEqual.physical h (H.delete_one ( = ) 999 h));
|
|
assert_bool "physical equality of delete_all with element lesser than min"
|
|
(CCEqual.physical h (H.delete_all ( = ) (-999) h));
|
|
assert_bool "physical equality of delete_all with element between min and max"
|
|
(CCEqual.physical h (H.delete_all ( = ) 2 h));
|
|
assert_bool "physical equality of delete_all with element greater than max"
|
|
(CCEqual.physical h (H.delete_all ( = ) 999 h));
|
|
assert_bool "physical equality of filter"
|
|
(CCEqual.physical h (H.filter (fun _ -> true) h));
|
|
true
|
|
;;
|
|
|
|
q ~name:"fold"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l -> l |> H.of_list |> H.fold ( + ) 0 = (l |> List.fold_left ( + ) 0))
|
|
;;
|
|
|
|
q ~name:"of_iter"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> CCList.to_iter |> H.of_iter |> H.to_list_sorted
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"of_seq"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> CCList.to_seq |> H.of_seq |> H.to_list_sorted
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"of_gen"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> CCList.to_gen |> H.of_gen |> H.to_list_sorted
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"to_iter"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list |> H.to_iter |> CCList.of_iter |> List.sort CCInt.compare
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"to_seq"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list |> H.to_seq |> CCList.of_seq |> List.sort CCInt.compare
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"to_gen"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list |> H.to_gen |> CCList.of_gen |> List.sort CCInt.compare
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"to_iter_sorted"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list |> H.to_iter_sorted |> Iter.to_list
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"to_seq_sorted"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list |> H.to_seq_sorted |> CCList.of_seq
|
|
|> List.sort CCInt.compare
|
|
= (l |> List.sort CCInt.compare))
|
|
;;
|
|
|
|
q ~name:"to_string with default sep"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list |> H.to_string string_of_int
|
|
= (l |> List.sort CCInt.compare |> List.map string_of_int
|
|
|> String.concat ","))
|
|
;;
|
|
|
|
q ~name:"to_string with space as sep"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
l |> H.of_list
|
|
|> H.to_string ~sep:" " string_of_int
|
|
= (l |> List.sort CCInt.compare |> List.map string_of_int
|
|
|> String.concat " "))
|
|
;;
|
|
|
|
q ~name:"Make_from_compare"
|
|
Q.(list_of_size Gen.small_nat medium_nat)
|
|
(fun l ->
|
|
let module H' = Make_from_compare (CCInt) in
|
|
l |> H'.of_list |> H'.to_list_sorted = (l |> List.sort CCInt.compare))
|