724 lines
20 KiB
OCaml
724 lines
20 KiB
OCaml
open! Import
|
|
open! Sequence
|
|
|
|
let%test_unit "of_lazy" =
|
|
let t = range 0 100 in
|
|
[%test_result: int list] (to_list (of_lazy (lazy t))) ~expect:(to_list t)
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
let seq_of_seqs =
|
|
unfold ~init:0 ~f:(fun i ->
|
|
Some (unfold ~init:i ~f:(fun j -> Some ((i, j), j + 1)), i + 1))
|
|
in
|
|
[%test_result: (int * int) list]
|
|
(to_list (take (interleave seq_of_seqs) 10))
|
|
~expect:[ 0, 0; 0, 1; 1, 1; 0, 2; 1, 2; 2, 2; 0, 3; 1, 3; 2, 3; 3, 3 ]
|
|
;;
|
|
|
|
let%expect_test "round_robin vs interleave" =
|
|
let list_of_lists = [ [ 1; 10; 100; 1000 ]; [ 2; 20; 200 ]; [ 3; 30 ]; [ 4 ] ] in
|
|
let list_of_seqs = List.map list_of_lists ~f:of_list in
|
|
let seq_of_seqs = of_list list_of_seqs in
|
|
print_s [%sexp (to_list (round_robin list_of_seqs) : int list)];
|
|
[%expect {| (1 2 3 4 10 20 30 100 200 1_000) |}];
|
|
print_s [%sexp (to_list (interleave seq_of_seqs) : int list)];
|
|
[%expect {| (1 10 2 100 20 3 1_000 200 30 4) |}]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
let evens = unfold ~init:0 ~f:(fun i -> Some (i, i + 2)) in
|
|
let vowels = cycle_list_exn [ 'a'; 'e'; 'i'; 'o'; 'u' ] in
|
|
[%test_result: (int * char) list]
|
|
(to_list (take (interleaved_cartesian_product evens vowels) 10))
|
|
~expect:
|
|
[ 0, 'a'; 0, 'e'; 2, 'a'; 0, 'i'; 2, 'e'; 4, 'a'; 0, 'o'; 2, 'i'; 4, 'e'; 6, 'a' ]
|
|
;;
|
|
|
|
let%test_module "Sequence.merge*" =
|
|
(module struct
|
|
let%test_unit _ =
|
|
[%test_eq: (int, int) Merge_with_duplicates_element.t list]
|
|
(to_list
|
|
(merge_with_duplicates
|
|
(of_list [ 1; 2 ])
|
|
(of_list [ 2; 3 ])
|
|
(* Can't use Core_int.compare because it would be a dependency cycle. *)
|
|
~compare:Int.compare))
|
|
[ Left 1; Both (2, 2); Right 3 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_eq: (int, int) Merge_with_duplicates_element.t list]
|
|
(to_list
|
|
(merge_with_duplicates
|
|
(of_list [ 2; 1 ])
|
|
(of_list [ 2; 3 ])
|
|
~compare:Int.compare))
|
|
[ Both (2, 2); Left 1; Right 3 ]
|
|
;;
|
|
|
|
let test_merge_semantics ~merge ~(normalize_list : _ -> compare:(_ -> _ -> _) -> _) =
|
|
Base_quickcheck.Test.run_exn
|
|
(module struct
|
|
module Deduped_and_sorted_int_list = struct
|
|
type t = int list [@@deriving quickcheck, sexp_of]
|
|
|
|
let sort t = normalize_list t ~compare:Int.compare
|
|
|
|
let quickcheck_generator =
|
|
Base_quickcheck.Generator.map quickcheck_generator ~f:sort
|
|
;;
|
|
|
|
let quickcheck_shrinker =
|
|
Base_quickcheck.Shrinker.map quickcheck_shrinker ~f:sort ~f_inverse:sort
|
|
;;
|
|
end
|
|
|
|
type t = Deduped_and_sorted_int_list.t * Deduped_and_sorted_int_list.t
|
|
[@@deriving quickcheck, sexp_of]
|
|
end)
|
|
~f:(fun (xs, ys) ->
|
|
[%test_result: int list]
|
|
(Sequence.to_list
|
|
(merge (Sequence.of_list xs) (Sequence.of_list ys) ~compare:Int.compare))
|
|
~expect:(normalize_list (xs @ ys) ~compare:Int.compare))
|
|
;;
|
|
|
|
let%test_unit "merge_deduped_and_sorted" =
|
|
test_merge_semantics
|
|
~merge:Sequence.merge_deduped_and_sorted
|
|
~normalize_list:List.dedup_and_sort
|
|
;;
|
|
|
|
let%test_unit "merge_sorted" =
|
|
test_merge_semantics ~merge:Sequence.merge_sorted ~normalize_list:List.sort
|
|
;;
|
|
end)
|
|
;;
|
|
|
|
let%test _ = fold ~f:( + ) ~init:0 (of_list [ 1; 2; 3; 4; 5 ]) = 15
|
|
let%test _ = fold ~f:( + ) ~init:0 (of_list []) = 0
|
|
|
|
let%test_unit _ =
|
|
let test_equal l = [%test_result: int list] (to_list (of_list l)) ~expect:l in
|
|
test_equal [];
|
|
test_equal [ 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
(* The test for longer list is after range *)
|
|
|
|
let%test_unit _ = [%test_result: int list] (to_list (range 0 5)) ~expect:[ 0; 1; 2; 3; 4 ]
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (range ~stop:`inclusive 0 5))
|
|
~expect:[ 0; 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (range ~start:`exclusive 0 5)) ~expect:[ 1; 2; 3; 4 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (range ~stride:(-2) 5 1)) ~expect:[ 5; 3 ]
|
|
;;
|
|
|
|
(* Test for to_list *)
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (range 0 5000)) ~expect:(List.range 0 5000)
|
|
;;
|
|
|
|
(* Functions used for testing by comparing to List implementation*)
|
|
let test_to_list s f g = [%test_result: int list] (to_list (f s)) ~expect:(g (to_list s))
|
|
|
|
(* For testing, we create a sequence which is equal to 1;2;3;4;5, but
|
|
with a more interesting structure inside*)
|
|
|
|
let s12345 =
|
|
map
|
|
~f:(fun x -> x / 2)
|
|
(filter ~f:(fun x -> x % 2 = 0) (of_list [ 1; 2; 3; 4; 5; 6; 7; 8; 9; 10 ]))
|
|
;;
|
|
|
|
let sempty = filter ~f:(fun x -> x < 0) (of_list [ 1; 2; 3; 4 ])
|
|
|
|
let test f g =
|
|
test_to_list s12345 f g;
|
|
test_to_list sempty f g
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list s12345) ~expect:[ 1; 2; 3; 4; 5 ];
|
|
[%test_result: int list] (to_list sempty) ~expect:[]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list
|
|
(unfold_with s12345 ~init:1 ~f:(fun s _ ->
|
|
if s % 2 = 0
|
|
then Skip { state = s + 1 }
|
|
else if s = 5
|
|
then Done
|
|
else Yield { value = s; state = s + 1 })))
|
|
~expect:[ 1; 3 ]
|
|
;;
|
|
|
|
let test_delay init =
|
|
unfold_with_and_finish
|
|
~init
|
|
~running_step:(fun prev next -> Yield { value = prev; state = next })
|
|
~inner_finished:(fun x -> Some x)
|
|
~finishing_step:(fun prev ->
|
|
match prev with
|
|
| None -> Done
|
|
| Some prev -> Yield { value = prev; state = None })
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (test_delay 0 s12345)) ~expect:[ 0; 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ = [%test_result: int list] (to_list (test_delay 0 sempty)) ~expect:[ 0 ]
|
|
let%test_unit _ = [%test_result: int list] (to_list s12345) ~expect:[ 1; 2; 3; 4; 5 ]
|
|
let%test_unit _ = test (map ~f:(fun i -> -i)) (List.map ~f:(fun i -> -i))
|
|
|
|
let%test_unit _ =
|
|
test (mapi ~f:(fun i j -> j - (2 * i))) (List.mapi ~f:(fun i j -> j - (2 * i)))
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
test (filter ~f:(fun i -> i % 2 = 0)) (List.filter ~f:(fun i -> i % 2 = 0))
|
|
;;
|
|
|
|
let%test _ = length s12345 = 5 && length sempty = 0
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int option] (find s12345 ~f:(fun x -> x = 3)) ~expect:(Some 3);
|
|
[%test_result: int option] (find s12345 ~f:(fun x -> x = 7)) ~expect:None
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: string option]
|
|
(find_map s12345 ~f:(fun x -> if x = 3 then Some "a" else None))
|
|
~expect:(Some "a");
|
|
[%test_result: string option]
|
|
(find_map s12345 ~f:(fun x -> if x = 7 then Some "a" else None))
|
|
~expect:None
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: string option]
|
|
(find_mapi s12345 ~f:(fun _ x -> if x = 3 then Some "a" else None))
|
|
~expect:(Some "a")
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: string option]
|
|
(find_mapi s12345 ~f:(fun _ x -> if x = 7 then Some "a" else None))
|
|
~expect:None
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: (int * int) option]
|
|
(find_mapi s12345 ~f:(fun i x -> if i + x >= 6 then Some (i, x) else None))
|
|
~expect:(Some (3, 4))
|
|
;;
|
|
|
|
let%test _ = for_all sempty ~f:(fun _ -> false)
|
|
let%test _ = for_all s12345 ~f:(fun x -> x > 0)
|
|
let%test _ = not (for_all s12345 ~f:(fun x -> x < 5))
|
|
let%test _ = for_alli sempty ~f:(fun _ _ -> false)
|
|
let%test _ = for_alli s12345 ~f:(fun _ x -> x > 0)
|
|
let%test _ = not (for_alli s12345 ~f:(fun _ x -> x < 5))
|
|
let%test _ = for_alli s12345 ~f:(fun i x -> x = i + 1)
|
|
let%test _ = not (exists sempty ~f:(fun _ -> assert false))
|
|
let%test _ = exists s12345 ~f:(fun x -> x = 5)
|
|
let%test _ = not (exists s12345 ~f:(fun x -> x = 0))
|
|
let%test _ = not (existsi sempty ~f:(fun _ _ -> assert false))
|
|
let%test _ = existsi s12345 ~f:(fun _ x -> x = 5)
|
|
let%test _ = not (existsi s12345 ~f:(fun _ x -> x = 0))
|
|
let%test _ = not (existsi s12345 ~f:(fun i x -> x <> i + 1))
|
|
|
|
let%test_unit _ =
|
|
let l = ref [] in
|
|
iter s12345 ~f:(fun x -> l := x :: !l);
|
|
[%test_result: int list] !l ~expect:[ 5; 4; 3; 2; 1 ]
|
|
;;
|
|
|
|
let%test _ = is_empty sempty
|
|
let%test _ = not (is_empty (of_list [ 1 ]))
|
|
let%test _ = mem s12345 1 ~equal:Int.equal
|
|
let%test _ = not (mem s12345 6 ~equal:Int.equal)
|
|
let%test_unit _ = [%test_result: int list] (to_list empty) ~expect:[]
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (bind sempty ~f:(fun _ -> s12345))) ~expect:[]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (bind s12345 ~f:(fun _ -> sempty))) ~expect:[]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (bind s12345 ~f:(fun x -> of_list [ x; -x ])))
|
|
~expect:[ 1; -1; 2; -2; 3; -3; 4; -4; 5; -5 ]
|
|
;;
|
|
|
|
let%test_unit _ = [%test_result: int list] (to_list (return 1)) ~expect:[ 1 ]
|
|
let%test_unit _ = [%test_result: int option] (nth s12345 3) ~expect:(Some 4)
|
|
let%test_unit _ = [%test_result: int option] (nth s12345 5) ~expect:None
|
|
let%test_unit _ = [%test_result: int option] (hd s12345) ~expect:(Some 1)
|
|
let%test_unit _ = [%test_result: int option] (hd sempty) ~expect:None
|
|
let%test_unit _ = [%test_result: int t option] (tl sempty) ~expect:None
|
|
|
|
let%test_unit _ =
|
|
match tl s12345 with
|
|
| Some l -> [%test_result: int list] (to_list l) ~expect:[ 2; 3; 4; 5 ]
|
|
| None -> failwith "expected Some"
|
|
;;
|
|
|
|
let%test_unit _ = [%test_result: (int * int t) option] (next sempty) ~expect:None
|
|
|
|
let%test_unit _ =
|
|
match next s12345 with
|
|
| Some (hd, tl) ->
|
|
[%test_result: int] hd ~expect:1;
|
|
[%test_result: int list] (to_list tl) ~expect:[ 2; 3; 4; 5 ]
|
|
| None -> failwith "expected Some"
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (filter_opt (of_list [ None; Some 1; None; Some 2; Some 3 ])))
|
|
~expect:[ 1; 2; 3 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
let l, r = split_n s12345 2 in
|
|
[%test_result: int list] l ~expect:[ 1; 2 ];
|
|
[%test_result: int list] (to_list r) ~expect:[ 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list list]
|
|
(to_list (chunks_exn s12345 2))
|
|
~expect:[ [ 1; 2 ]; [ 3; 4 ]; [ 5 ] ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (append s12345 s12345))
|
|
~expect:[ 1; 2; 3; 4; 5; 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (append sempty s12345)) ~expect:[ 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: (int * int) list] (to_list (zip s12345 sempty)) ~expect:[]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: (int * int) list]
|
|
(to_list (zip s12345 (of_list [ 6; 5; 4; 3; 2; 1 ])))
|
|
~expect:[ 1, 6; 2, 5; 3, 4; 4, 3; 5, 2 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: (int * string) list]
|
|
(to_list (zip s12345 (of_list [ "a" ])))
|
|
~expect:[ 1, "a" ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: (int * int) option]
|
|
(find_consecutive_duplicate s12345 ~equal:( = ))
|
|
~expect:None
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: (int * int) option]
|
|
(find_consecutive_duplicate (of_list [ 1; 2; 2; 3; 4; 4; 5 ]) ~equal:( = ))
|
|
~expect:(Some (2, 2))
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list
|
|
(remove_consecutive_duplicates
|
|
~equal:( = )
|
|
(of_list [ 1; 2; 2; 3; 3; 3; 3; 4; 4; 5; 6; 6; 7 ])))
|
|
~expect:[ 1; 2; 3; 4; 5; 6; 7 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (remove_consecutive_duplicates ~equal:( = ) s12345))
|
|
~expect:[ 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (remove_consecutive_duplicates ~equal:(fun _ _ -> true) s12345))
|
|
~expect:[ 1 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (init (-1) ~f:(fun _ -> assert false))) ~expect:[]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (init 5 ~f:Fn.id)) ~expect:[ 0; 1; 2; 3; 4 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (sub s12345 ~pos:4 ~len:10)) ~expect:[ 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (sub s12345 ~pos:1 ~len:2)) ~expect:[ 2; 3 ]
|
|
;;
|
|
|
|
let%test_unit _ = [%test_result: int list] (to_list (sub s12345 ~pos:0 ~len:0)) ~expect:[]
|
|
let%test_unit _ = [%test_result: int list] (to_list (take s12345 2)) ~expect:[ 1; 2 ]
|
|
let%test_unit _ = [%test_result: int list] (to_list (take s12345 0)) ~expect:[]
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (take s12345 9)) ~expect:[ 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ = [%test_result: int list] (to_list (drop s12345 2)) ~expect:[ 3; 4; 5 ]
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (drop s12345 0)) ~expect:[ 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ = [%test_result: int list] (to_list (drop s12345 9)) ~expect:[]
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (take_while ~f:(fun x -> x < 3) s12345))
|
|
~expect:[ 1; 2 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (drop_while ~f:(fun x -> x < 3) s12345))
|
|
~expect:[ 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (shift_right (shift_right s12345 0) (-1)))
|
|
~expect:[ -1; 0; 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: char list] (to_list (intersperse ~sep:'a' (of_list []))) ~expect:[]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: char list]
|
|
(to_list (intersperse ~sep:'a' (of_list [ 'b' ])))
|
|
~expect:[ 'b' ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (intersperse ~sep:(-1) (take s12345 1))) ~expect:[ 1 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (intersperse ~sep:0 s12345))
|
|
~expect:[ 1; 0; 2; 0; 3; 0; 4; 0; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (take (repeat 1) 3)) ~expect:[ 1; 1; 1 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(to_list (take (cycle_list_exn [ 1; 2; 3; 4; 5 ]) 7))
|
|
~expect:[ 1; 2; 3; 4; 5; 1; 2 ]
|
|
;;
|
|
|
|
let%expect_test _ =
|
|
require_does_raise [%here] (fun () -> cycle_list_exn []);
|
|
[%expect {| (Invalid_argument Sequence.cycle_list_exn) |}]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: (char * int) list]
|
|
(to_list (cartesian_product (of_list [ 'a'; 'b' ]) s12345))
|
|
~expect:
|
|
[ 'a', 1; 'a', 2; 'a', 3; 'a', 4; 'a', 5; 'b', 1; 'b', 2; 'b', 3; 'b', 4; 'b', 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: float]
|
|
(delayed_fold
|
|
s12345
|
|
~init:0.0
|
|
~f:(fun a i ~k -> if Float.( <= ) a 5.0 then k (a +. Float.of_int i) else a)
|
|
~finish:(fun _ -> assert false))
|
|
~expect:6.0
|
|
;;
|
|
|
|
let%expect_test "fold_m" =
|
|
let module Simple_monad = struct
|
|
type 'a t =
|
|
| Return of 'a
|
|
| Step of 'a t
|
|
[@@deriving sexp_of]
|
|
|
|
let return a = Return a
|
|
|
|
let rec bind t ~f =
|
|
match t with
|
|
| Return a -> f a
|
|
| Step t -> Step (bind t ~f)
|
|
;;
|
|
|
|
let step = Step (Return ())
|
|
end
|
|
in
|
|
fold_m
|
|
~bind:Simple_monad.bind
|
|
~return:Simple_monad.return
|
|
s12345
|
|
~init:[]
|
|
~f:(fun acc n ->
|
|
Simple_monad.bind Simple_monad.step ~f:(fun () -> Simple_monad.return (n :: acc)))
|
|
|> printf !"%{sexp: int list Simple_monad.t}\n";
|
|
[%expect {| (Step (Step (Step (Step (Step (Return (5 4 3 2 1))))))) |}]
|
|
;;
|
|
|
|
let%expect_test "iter_m" =
|
|
iter_m ~bind:Generator.bind ~return:Generator.return s12345 ~f:Generator.yield
|
|
|> Generator.run
|
|
|> printf !"%{sexp: int t}\n";
|
|
[%expect {| (1 2 3 4 5) |}]
|
|
;;
|
|
|
|
let%test _ =
|
|
let num_computations = ref 0 in
|
|
let t =
|
|
memoize
|
|
(unfold ~init:() ~f:(fun () ->
|
|
Int.incr num_computations;
|
|
None))
|
|
in
|
|
iter t ~f:Fn.id;
|
|
iter t ~f:Fn.id;
|
|
!num_computations = 1
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (drop_eagerly s12345 0)) ~expect:[ 1; 2; 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list] (to_list (drop_eagerly s12345 2)) ~expect:[ 3; 4; 5 ]
|
|
;;
|
|
|
|
let%test_unit _ = [%test_result: int list] (to_list (drop_eagerly s12345 5)) ~expect:[]
|
|
let%test_unit _ = [%test_result: int list] (to_list (drop_eagerly s12345 8)) ~expect:[]
|
|
|
|
let compare_tests =
|
|
[ [ 1; 2; 3 ], [ 1; 2; 3 ], 0
|
|
; [ 1; 2; 3 ], [], 1
|
|
; [], [ 1; 2; 3 ], -1
|
|
; [ 1; 2 ], [ 1; 2; 3 ], -1
|
|
; [ 1; 2; 3 ], [ 1; 2 ], 1
|
|
; [ 1; 3; 2 ], [ 1; 2; 3 ], 1
|
|
; [ 1; 2; 3 ], [ 1; 3; 2 ], -1
|
|
]
|
|
;;
|
|
|
|
(* this test has to use base OCaml library functions to avoid circular dependencies *)
|
|
let%test _ =
|
|
List.for_all
|
|
~f:Fn.id
|
|
(List.map
|
|
~f:(fun (l1, l2, expected_res) ->
|
|
compare Int.compare (of_list l1) (of_list l2) = expected_res)
|
|
compare_tests)
|
|
;;
|
|
|
|
let%expect_test "[equal]" =
|
|
let equal l1 l2 =
|
|
let t1 = of_list l1 in
|
|
let t2 = of_list l2 in
|
|
let b = equal Int.equal t1 t2 in
|
|
print_s [%sexp (b : bool)];
|
|
require [%here] (Bool.equal b (equal Int.equal t2 t1))
|
|
in
|
|
equal [] [];
|
|
[%expect {| true |}];
|
|
equal [] [ 1 ];
|
|
[%expect {| false |}];
|
|
equal [ 1 ] [ 1 ];
|
|
[%expect {| true |}];
|
|
equal [ 1 ] [ 1; 2 ];
|
|
[%expect {| false |}]
|
|
;;
|
|
|
|
let%test_unit "[equal] randomised test" =
|
|
let with_gen ?examples gen =
|
|
Base_quickcheck.Test.run_exn
|
|
?examples
|
|
(module struct
|
|
type t = int list * int list [@@deriving quickcheck, sexp_of]
|
|
|
|
let quickcheck_generator = gen
|
|
end)
|
|
~f:(fun (left, right) ->
|
|
[%test_result: bool]
|
|
~expect:(List.equal Int.equal left right)
|
|
(Comparable.lift (Sequence.equal Int.equal) ~f:Sequence.of_list left right))
|
|
in
|
|
let list_gen = [%generator: int list] in
|
|
(* certainly equal. *)
|
|
with_gen
|
|
~examples:
|
|
(List.map ~f:(fun x -> x, x) [ []; [ 1 ]; [ Int.max_value ]; [ 5; 4; 3; 2; 1 ] ])
|
|
(Base_quickcheck.Generator.map list_gen ~f:(fun x -> x, x));
|
|
(* Probably not equal. *)
|
|
with_gen
|
|
~examples:[ [], []; [], [ 1 ]; [ 1 ], []; [ Int.min_value ], [ Int.max_value ] ]
|
|
(Base_quickcheck.Generator.both list_gen list_gen)
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(folding_map
|
|
(of_list [ 1; 2; 3; 4 ])
|
|
~init:0
|
|
~f:(fun acc x ->
|
|
let y = acc + x in
|
|
y, y)
|
|
|> to_list)
|
|
~expect:[ 1; 3; 6; 10 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: bool]
|
|
(folding_map empty ~init:0 ~f:(fun acc x ->
|
|
let y = acc + x in
|
|
y, y)
|
|
|> is_empty)
|
|
~expect:true
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: int list]
|
|
(folding_mapi
|
|
(of_list [ 1; 2; 3; 4 ])
|
|
~init:0
|
|
~f:(fun i acc x ->
|
|
let y = acc + (i * x) in
|
|
y, y)
|
|
|> to_list)
|
|
~expect:[ 0; 2; 8; 20 ]
|
|
;;
|
|
|
|
let%test_unit _ =
|
|
[%test_result: bool]
|
|
(folding_mapi empty ~init:0 ~f:(fun i acc x ->
|
|
let y = acc + (i * x) in
|
|
y, y)
|
|
|> is_empty)
|
|
~expect:true
|
|
;;
|
|
|
|
let%expect_test "findi" =
|
|
Base_quickcheck.Test.run_exn
|
|
(module struct
|
|
type t = int option list * (int -> int -> bool) [@@deriving quickcheck, sexp_of]
|
|
end)
|
|
~f:(fun (option_list, f) ->
|
|
let sequence = option_list |> of_list |> filter_opt in
|
|
[%test_result: (int * int) option]
|
|
(findi sequence ~f)
|
|
~expect:(List.findi (to_list sequence) ~f));
|
|
[%expect {| |}]
|
|
;;
|
|
|
|
let%expect_test _ =
|
|
let xs = init 3 ~f:Fn.id |> Generator.of_sequence in
|
|
let ( @ ) xs ys = Generator.bind xs ~f:(fun () -> ys) in
|
|
xs @ xs @ xs @ xs @ xs |> Generator.run |> [%sexp_of: int t] |> print_s;
|
|
[%expect {| (0 1 2 0 1 2 0 1 2 0 1 2 0 1 2) |}]
|
|
;;
|
|
|
|
let%test_module "group" =
|
|
(module struct
|
|
let%test _ =
|
|
of_list [ 1; 2; 3; 4 ]
|
|
|> group ~break:(fun _ x -> Int.equal x 3)
|
|
|> [%compare.equal: int list t] (of_list [ [ 1; 2 ]; [ 3; 4 ] ])
|
|
;;
|
|
|
|
let%test _ =
|
|
group empty ~break:(fun _ -> assert false) |> [%compare.equal: unit list t] empty
|
|
;;
|
|
|
|
let mis = of_list [ 'M'; 'i'; 's'; 's'; 'i'; 's'; 's'; 'i'; 'p'; 'p'; 'i' ]
|
|
|
|
let equal_letters =
|
|
of_list
|
|
[ [ 'M' ]
|
|
; [ 'i' ]
|
|
; [ 's'; 's' ]
|
|
; [ 'i' ]
|
|
; [ 's'; 's' ]
|
|
; [ 'i' ]
|
|
; [ 'p'; 'p' ]
|
|
; [ 'i' ]
|
|
]
|
|
;;
|
|
|
|
let single_letters =
|
|
of_list [ [ 'M'; 'i'; 's'; 's'; 'i'; 's'; 's'; 'i'; 'p'; 'p'; 'i' ] ]
|
|
;;
|
|
|
|
let%test _ =
|
|
group ~break:Char.( <> ) mis |> [%compare.equal: char list t] equal_letters
|
|
;;
|
|
|
|
let%test _ =
|
|
group ~break:(fun _ _ -> false) mis |> [%compare.equal: char list t] single_letters
|
|
;;
|
|
end)
|
|
;;
|
|
|
|
let%test_module "Caml.Seq" =
|
|
(module struct
|
|
let list = [ 1; 2; 3; 4 ]
|
|
|
|
let%expect_test "of_seq" =
|
|
list |> Stdlib.List.to_seq |> Sequence.of_seq |> Sequence.iter ~f:(printf "%d\n");
|
|
[%expect {|
|
|
1
|
|
2
|
|
3
|
|
4
|
|
|}]
|
|
;;
|
|
|
|
let%expect_test "to_seq" =
|
|
list |> Sequence.of_list |> Sequence.to_seq |> Stdlib.Seq.iter (printf "%d\n");
|
|
[%expect {|
|
|
1
|
|
2
|
|
3
|
|
4
|
|
|}]
|
|
;;
|
|
end)
|
|
;;
|