iter/tests/unit/t_iter.ml

367 lines
10 KiB
OCaml

module Q = QCheck
open Iter
let spf = Printf.sprintf
let pp_ilist = Q.Print.(list int)
let qchecks = ref []
let add_qcheck line gen prop =
let test = Q.Test.make gen prop ~name:(spf "qcheck %d" line) in
qchecks := test :: !qchecks
let () =
let seq = empty in
OUnit.assert_bool "empty" (is_empty seq);
OUnit.assert_bool "empty"
(try
iter (fun _ -> raise Exit) seq;
true
with Exit -> false)
let () =
let seq = repeat "hello" in
OUnit.assert_equal [ "hello"; "hello"; "hello" ] (seq |> take 3 |> to_list)
let () =
OUnit.assert_equal [ 0; 1; 2; 3; 4 ] (init (fun x -> x) |> take 5 |> to_list)
let () =
let n = 1 -- 10 |> fold ( + ) 0 in
OUnit.assert_equal 55 n;
()
let () =
let l =
[ "hello"; "world" ] |> of_list |> foldi (fun acc i x -> (i, x) :: acc) []
in
OUnit.assert_equal [ 1, "world"; 0, "hello" ] l;
()
let () =
OUnit.assert_equal
~printer:Q.Print.(list int)
[ 0; 1; 3; 5 ]
(0 -- 3 |> fold_map (fun prev x -> x, prev + x) 0 |> to_list)
let () =
let s1 = 1 -- 5 in
let s2 = 6 -- 10 in
let l = [ 1; 2; 3; 4; 5; 6; 7; 8; 9; 10 ] in
OUnit.assert_equal l (to_list (append s1 s2));
()
let () =
1 -- 1000
|> map (fun i -> i -- (i + 1))
|> concat |> length |> OUnit.assert_equal 2000
let () =
1 -- 1000
|> flat_map (fun i -> i -- (i + 1))
|> length |> OUnit.assert_equal 2000
let test = OUnit.assert_equal ~printer:Q.Print.(list @@ list int)
let () =
test
[ [ 1; 2 ]; [ 1; 3 ] ]
(seq_list [ singleton 1; doubleton 2 3 ] |> to_list)
let () = test [] (seq_list [ singleton 1; empty; doubleton 2 3 ] |> to_list)
let () =
test
[ [ 1; 2; 4 ]; [ 1; 3; 4 ] ]
(seq_list [ singleton 1; doubleton 2 3; singleton 4 ] |> to_list)
let () =
add_qcheck __LINE__
Q.(list int)
(fun l ->
let seq = of_list l and f x = x mod 2 = 0 in
filter_count f seq = (filter f seq |> length))
let () =
1 -- 100
|> (fun seq -> intersperse 0 seq)
|> take 10 |> to_list
|> OUnit.assert_equal [ 1; 0; 2; 0; 3; 0; 4; 0; 5; 0 ]
let () =
let printer = pp_ilist in
let iter =
of_gen_once
(let i = ref (-1) in
fun () ->
incr i;
if !i < 5 then
Some !i
else
None)
in
(* consume iter into a persistent version of itself *)
let iter' = persistent iter in
OUnit.assert_raises OneShotSequence (fun () -> iter |> to_list);
OUnit.assert_equal ~printer [ 0; 1; 2; 3; 4 ] (iter' |> to_list);
OUnit.assert_equal ~printer [ 0; 1; 2; 3; 4 ] (iter' |> to_list);
OUnit.assert_equal ~printer [ 0; 1; 2; 3; 4 ]
(iter' |> to_seq_persistent |> of_seq |> to_list);
()
let () =
let printer = pp_ilist in
let iter = 0 -- 10_000 in
let iter' = persistent iter in
OUnit.assert_equal 10_001 (length iter');
OUnit.assert_equal 10_001 (length iter');
OUnit.assert_equal ~printer [ 0; 1; 2; 3 ] (iter' |> take 4 |> to_list);
()
let () =
1 -- 100
|> sort ~cmp:(fun i j -> j - i)
|> take 4 |> to_list
|> OUnit.assert_equal [ 100; 99; 98; 97 ]
let test line p = OUnit.assert_bool (spf "test at %d" line) p
let () = test __LINE__ @@ (of_list [ 1; 2; 3; 4 ] |> sorted)
let () = test __LINE__ @@ not (of_list [ 1; 2; 3; 0; 4 ] |> sorted)
let () = test __LINE__ @@ sorted empty
let () =
[ 1; 2; 3; 3; 2; 2; 3; 4 ] |> of_list |> group_succ_by ?eq:None |> to_list
|> OUnit.assert_equal [ [ 1 ]; [ 2 ]; [ 3; 3 ]; [ 2; 2 ]; [ 3 ]; [ 4 ] ]
let () =
[ 1; 2; 3; 3; 2; 2; 3; 4 ] |> of_list
|> group_by ?eq:None ?hash:None
|> sort ?cmp:None |> to_list
|> OUnit.assert_equal [ [ 1 ]; [ 2; 2; 2 ]; [ 3; 3; 3 ]; [ 4 ] ]
let () =
[ 1; 2; 3; 3; 2; 2; 3; 4 ] |> of_list |> count ?eq:None ?hash:None
|> sort ?cmp:None |> to_list
|> OUnit.assert_equal [ 1, 1; 2, 3; 3, 3; 4, 1 ]
let () =
[ 1; 2; 2; 3; 4; 4; 4; 3; 3 ]
|> of_list |> uniq ?eq:None |> to_list
|> OUnit.assert_equal [ 1; 2; 3; 4; 3 ]
let () =
[ 42; 1; 2; 3; 4; 5; 4; 3; 2; 1 ]
|> of_list |> sort_uniq ?cmp:None |> to_list
|> OUnit.assert_equal [ 1; 2; 3; 4; 5; 42 ]
let () =
let a = 0 -- 2 in
let b = of_list [ "a"; "b"; "c" ] in
let s =
product a b |> map (fun (x, y) -> y, x) |> to_list |> List.sort compare
in
OUnit.assert_equal
[ "a", 0; "a", 1; "a", 2; "b", 0; "b", 1; "b", 2; "c", 0; "c", 1; "c", 2 ]
s
let () =
OUnit.assert_equal [ 0, 1; 0, 2; 1, 2 ] (diagonal_l [ 0; 1; 2 ] |> to_list)
let () =
OUnit.assert_equal
[ 0, 1; 0, 2; 1, 2 ]
(of_list [ 0; 1; 2 ] |> diagonal |> to_list)
let () =
let s1 = 1 -- 3 in
let s2 = of_list [ "1"; "2" ] in
let join_row i j =
if string_of_int i = j then
Some (string_of_int i ^ " = " ^ j)
else
None
in
let s = join ~join_row s1 s2 in
OUnit.assert_equal [ "1 = 1"; "2 = 2" ] (to_list s);
()
let () =
OUnit.assert_equal
[ 'a', [ "abc"; "attic" ]; 'b', [ "barbary"; "boom"; "bop" ]; 'c', [] ]
(group_join_by
(fun s -> s.[0])
(of_str "abc")
(of_list [ "abc"; "boom"; "attic"; "deleted"; "barbary"; "bop" ])
|> map (fun (c, l) -> c, List.sort Stdlib.compare l)
|> sort |> to_list)
let () =
let f x =
if x < 5 then
Some (string_of_int x, x + 1)
else
None
in
unfoldr f 0 |> to_list |> OUnit.assert_equal [ "0"; "1"; "2"; "3"; "4" ]
let () =
1 -- 5 |> scan ( + ) 0 |> to_list
|> OUnit.assert_equal ~printer:pp_ilist [ 0; 1; 3; 6; 10; 15 ]
let test = OUnit.assert_equal ~printer:Q.Print.int
let () = test 100 (0 -- 100 |> max_exn ?lt:None)
let () = test 0 (0 -- 100 |> min_exn ?lt:None)
let () = OUnit.assert_equal 6 (of_list [ 1; 2; 3 ] |> sum)
let () =
let seq = of_list [ 10000.0; 3.14159; 2.71828 ] in
OUnit.assert_equal ~printer:string_of_float 10005.85987 (sumf seq)
let () =
let l = to_list (take 0 (of_list [ 1 ])) in
OUnit.assert_equal ~printer:pp_ilist [] l;
let l = to_list (take 5 (of_list [ 1; 2; 3; 4; 5; 6; 7; 8; 9; 10 ])) in
OUnit.assert_equal ~printer:pp_ilist [ 1; 2; 3; 4; 5 ] l;
()
let () =
let n =
of_list [ true; true; false; true ]
|> fold_while
(fun acc b ->
if b then
acc + 1, `Continue
else
acc, `Stop)
0
in
OUnit.assert_equal 2 n;
()
let () = 1 -- 5 |> drop 2 |> to_list |> OUnit.assert_equal [ 3; 4; 5 ]
let () = 1 -- 5 |> rev |> to_list |> OUnit.assert_equal [ 5; 4; 3; 2; 1 ]
let () =
OUnit.assert_bool "true" (for_all (fun x -> x < 10) (1 -- 9));
OUnit.assert_bool "false" (not (for_all (fun x -> x < 10) (2 -- 11)));
OUnit.assert_bool "true" (for_all (fun _ -> false) empty);
OUnit.assert_bool "nested"
(for_all
(fun seq -> not (for_all (fun x -> x < 8) seq))
(1 -- 10 >|= fun x -> x -- 20));
()
let () =
1 -- 100 |> exists (fun x -> x = 59) |> OUnit.assert_bool "exists";
1 -- 100
|> exists (fun x -> x < 0)
|> (fun x -> not x)
|> OUnit.assert_bool "not exists";
()
let () = 1 -- 1000 |> length |> OUnit.assert_equal 1000
let () =
let h = 1 -- 5 |> zip_i |> to_hashtbl in
0 -- 4 |> iter (fun i -> OUnit.assert_equal (i + 1) (Hashtbl.find h i));
OUnit.assert_equal [ 0; 1; 2; 3; 4 ]
(hashtbl_keys h |> sort ?cmp:None |> to_list);
()
let () =
let b = Buffer.create 4 in
let upp = function
| 'a' .. 'z' as c -> Char.chr (Char.code c - Char.code 'a' + Char.code 'A')
| c -> c
in
("hello world" |> of_str |> rev |> map upp |> fun seq -> to_buffer seq b);
OUnit.assert_equal "DLROW OLLEH" (Buffer.contents b);
()
let () =
OUnit.assert_equal ~printer:pp_ilist [ 1; 2; 3; 4 ] (to_list (1 -- 4));
OUnit.assert_equal ~printer:pp_ilist [ 10; 9; 8; 7; 6 ] (to_list (10 --^ 6));
OUnit.assert_equal ~printer:pp_ilist [] (to_list (10 -- 4));
OUnit.assert_equal ~printer:pp_ilist [] (to_list (10 --^ 60));
()
let test = OUnit.assert_equal ~printer:Q.Print.(list int)
let () = test [ 1; 2; 3; 4 ] (int_range_by ~step:1 1 4 |> to_list)
let () = test [ 4; 3; 2; 1 ] (int_range_by ~step:~-1 4 1 |> to_list)
let () = test [ 6; 4; 2 ] (int_range_by 6 1 ~step:~-2 |> to_list)
let () = test [] (int_range_by ~step:1 4 1 |> to_list)
let () =
add_qcheck __LINE__
Q.(pair small_int small_int)
(fun (i, j) ->
let i = Stdlib.min i j and j = Stdlib.max i j in
i -- j |> to_list = (int_range_by ~step:1 i j |> to_list))
let () =
add_qcheck __LINE__
Q.(pair small_int small_int)
(fun (i, j) ->
let i = Stdlib.min i j and j = Stdlib.max i j in
i -- j |> to_rev_list = (int_range_by ~step:~-1 j i |> to_list))
let array_for_all f a =
try
for i = 0 to Array.length a - 1 do
if not (f a.(i)) then raise Exit
done;
true
with Exit -> false
let () =
add_qcheck __LINE__
Q.(pair (list int) (1 -- 20))
(fun (l, n) ->
let seq = of_list l in
let a = sample n seq in
array_for_all (fun x -> exists (( = ) x) seq) a
&& Array.length a = Stdlib.min (length seq) n)
(* regression tests *)
let () =
let s = take 10 (repeat 1) in
OUnit.assert_bool "not empty" (not (is_empty s));
()
let with_tmp_file f =
let path = Filename.temp_file "test_iter" "data" in
try
let x = f path in
(try Sys.remove path with _ -> ());
x
with e ->
(try Sys.remove path with _ -> ());
raise e
let () =
with_tmp_file @@ fun path ->
Iter.IO.write_lines path Iter.empty;
let l = Iter.IO.lines_of path |> Iter.to_list in
OUnit.assert_equal ~printer:Q.Print.(list @@ Printf.sprintf "%S") [] l
let () =
let errcode = QCheck_base_runner.run_tests ~colors:false !qchecks in
if errcode <> 0 then exit errcode
(* map_by_2 tests *)
let test = OUnit.assert_equal ~printer:Q.Print.(list int)
let () = test [] (map_by_2 (fun a _ -> a) (of_list []) |> to_list)
(* Test empty iterator *)
let () = test [1] (map_by_2 (fun _ b -> b) (of_list [1]) |> to_list)
let () = test [3] (map_by_2 (fun _ b -> b) (1--3) |> drop 1 |> to_list)
let () = test [9] (map_by_2 (fun _ b -> b) (1--9) |> drop 4 |> to_list)
(* Odd number of elements should leave the last element in the iterator.
For an increasing integer range [1,2k] (fun _ b -> b) returns only
even numbers so this is sufficient to test that this element is left
in the iterator. *)
let () = test [1] (map_by_2 (fun a _ -> a) (1--2) |> to_list)
let () = test [2] (map_by_2 (fun _ b -> b) (1--2) |> to_list)
(* Test two elements *)
let () = test [1;3;5;7;9] (map_by_2 (fun a _ -> a) (1--10) |> to_list)
let () = test [2;4;6;8;10] (map_by_2 (fun _ b -> b) (1--10) |> to_list)
(* Test more than two elements *)