move all core tests to new testlib

This commit is contained in:
Simon Cruanes 2022-07-02 00:29:25 -04:00
parent 49c06e93fa
commit b695918e99
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
50 changed files with 2039 additions and 2384 deletions

View file

@ -157,58 +157,3 @@ module Decode = struct
| Some x -> x
| None -> failwith "bencode.decode: invalid string"
end
(*$= & ~printer:to_string_debug
(map_of_list []) (Decode.of_string_exn "de")
(list [int 1; int 2; string "foo"]) (Decode.of_string_exn "li1ei2e3:fooe")
*)
(*$inject
module B = Containers_bencode
let rec size = function
| Int _ | String _ -> 1
| List l -> List.fold_left (fun n x -> n + size x) 0 l
| Map m -> Str_map.fold(fun _ v n -> size v + n) m 0
let g_rand_b =
Q.Gen.(
sized_size (0--7) @@ fix @@ fun self n ->
let str n = string_size ~gen:char (0 -- n) in
let base = [
int >|= B.int;
str 100 >|= B.string;
] in
match n with
| 0 -> oneof base
| n ->
frequency @@
List.map (fun x -> 2, x) base @
[ 1, list_size (0 -- 10) (self (n-1)) >|= B.list;
1, list_size (0 -- 10) (pair (str 10) (self (n-1)) ) >|= B.map_of_list;
]
)
let rec shrink_b self = Q.(Iter.(
match self with
| Int i -> Shrink.int64 i >|= B.int64
| String s -> Shrink.string s >|= B.string
| List l -> Shrink.list ~shrink:shrink_b l >|= B.list
| Map l ->
let l = Str_map.fold (fun k v l -> (k,v) :: l) l [] in
Shrink.list ~shrink:(fun (k,v) ->
(Shrink.string k >|= fun k -> k,v) <+>
(shrink_b v >|= fun v -> k,v))
l
>|= B.map_of_list
))
let rand_b = Q.make ~print:to_string_debug ~stats:["size", size]
~shrink:shrink_b g_rand_b
*)
(*$Q
rand_b (fun b -> \
let s=Encode.to_string b in \
equal (Decode.of_string_exn s) b)
*)

View file

@ -36,24 +36,19 @@ val map : f:('a -> 'b) -> 'b t -> 'a t
[map fst int] compares values of type [(int * 'a)] by their
first component. *)
val always_eq : _ t
(** Always returns true. All values are equal.
@since NEXT_RELEASE *)
val never_eq : _ t
(** Always returns false. No values are, so this
is not even reflexive (i.e. [x=x] is false).
Be careful!
@since NEXT_RELEASE *)
module Infix : sig
val (>|=) : 'b t -> ('a -> 'b) -> 'a t
(** Infix equivalent of {!map}. *)
end
include module type of Infix
(* test consistency of interfaces *)
(*$inject
module type L = module type of CCEqual
module type LL = module type of CCEqualLabels
*)
(*$R
ignore (module CCEqualLabels : L)
*)
(*$R
ignore (module CCEqual : LL)
*)

View file

@ -19,10 +19,6 @@ module Poly = struct
try Hashtbl.find tbl x
with Not_found -> default
(*$=
"c" (let tbl = of_list [1,"a"; 2,"b"] in get_or tbl 3 ~default:"c")
"b" (let tbl = of_list [1,"a"; 2,"b"] in get_or tbl 2 ~default:"c")
*)
let keys tbl k = Hashtbl.iter (fun key _ -> k key) tbl
@ -54,11 +50,6 @@ module Poly = struct
(fun x y acc -> f x y :: acc)
h []
(*$T
of_list [1,"a"; 2,"b"] |> map_list (fun x y -> string_of_int x ^ y) \
|> List.sort Stdlib.compare = ["1a"; "2b"]
*)
let to_iter tbl k = Hashtbl.iter (fun key v -> k (key,v)) tbl
let add_iter tbl i = i (fun (k,v) -> Hashtbl.add tbl k v)
@ -123,17 +114,6 @@ module Poly = struct
| Some _, Some v' -> Hashtbl.replace tbl k v'
| Some _, None -> Hashtbl.remove tbl k
(*$R
let tbl = Hashtbl.create 32 in
update tbl ~f:(fun _ _ -> Some "1") ~k:1;
assert_equal (Some "1") (get tbl 1);
update tbl ~f:(fun _ v->match v with Some _ -> assert false | None -> Some "2") ~k:2;
assert_equal (Some "2") (get tbl 2);
assert_equal 2 (Hashtbl.length tbl);
update tbl ~f:(fun _ _ -> None) ~k:1;
assert_equal None (get tbl 1);
*)
let get_or_add tbl ~f ~k =
try Hashtbl.find tbl k
with Not_found ->
@ -141,19 +121,6 @@ module Poly = struct
Hashtbl.add tbl k v;
v
(*$R
let tbl = Hashtbl.create 32 in
let v1 = get_or_add tbl ~f:(fun _ -> "1") ~k:1 in
assert_equal "1" v1;
assert_equal (Some "1") (get tbl 1);
let v2 = get_or_add tbl ~f:(fun _ ->"2") ~k:2 in
assert_equal "2" v2;
assert_equal (Some "2") (get tbl 2);
assert_equal "2" (get_or_add tbl ~f:(fun _ -> assert false) ~k:2);
assert_equal 2 (Hashtbl.length tbl);
()
*)
let pp ?(pp_start=fun _ () -> ()) ?(pp_stop=fun _ () -> ())
?(pp_sep=fun fmt () -> Format.fprintf fmt ",@ ")
?(pp_arrow=fun fmt () -> Format.fprintf fmt "@ -> ") pp_k pp_v fmt m =
@ -342,10 +309,6 @@ module type S = sig
@since 0.13 *)
end
(*$inject
module T = Make(CCInt)
*)
module Make(X : Hashtbl.HashedType)
: S with type key = X.t and type 'a t = 'a Hashtbl.Make(X).t
= struct
@ -359,31 +322,12 @@ module Make(X : Hashtbl.HashedType)
try find tbl x
with Not_found -> default
(*$=
"c" (let tbl = T.of_list [1,"a"; 2,"b"] in T.get_or tbl 3 ~default:"c")
"b" (let tbl = T.of_list [1,"a"; 2,"b"] in T.get_or tbl 2 ~default:"c")
*)
let incr ?(by=1) tbl x =
let n = get_or tbl x ~default:0 in
if n+by <= 0
then remove tbl x
else replace tbl x (n+by)
(*$R
let tbl = T.create 32 in
T.incr tbl 1 ;
T.incr tbl 2;
T.incr tbl 1;
assert_equal 2 (T.find tbl 1);
assert_equal 1 (T.find tbl 2);
assert_equal 2 (T.length tbl);
T.decr tbl 2;
assert_equal 0 (T.get_or tbl 2 ~default:0);
assert_equal 1 (T.length tbl);
assert_bool "2 removed" (not (T.mem tbl 2));
*)
let add_list tbl k v =
let l = try find tbl k with Not_found -> [] in
replace tbl k (v::l)

View file

@ -23,69 +23,6 @@ module type TOTAL_ORD = sig
a positive value if [a] is greater than [b] *)
end
(*$inject
module H = CCHeap.Make(struct
type t = int
let leq x y = x<=y
end)
let rec is_sorted l = match l with
| [_]
| [] -> true
| x::((y::_) as l') -> x <= y && is_sorted l'
let extract_list = H.to_list_sorted
*)
(*$R
let h = H.of_list [5;3;4;1;42;0] in
let h, x = H.take_exn h in
OUnit2.assert_equal ~printer:string_of_int 0 x;
let h, x = H.take_exn h in
OUnit2.assert_equal ~printer:string_of_int 1 x;
let h, x = H.take_exn h in
OUnit2.assert_equal ~printer:string_of_int 3 x;
let h, x = H.take_exn h in
OUnit2.assert_equal ~printer:string_of_int 4 x;
let h, x = H.take_exn h in
OUnit2.assert_equal ~printer:string_of_int 5 x;
let h, x = H.take_exn h in
OUnit2.assert_equal ~printer:string_of_int 42 x;
OUnit2.assert_raises H.Empty (fun () -> H.take_exn h);
*)
(*$QR & ~count:30
Q.(list_of_size Gen.(return 1_000) int) (fun l ->
(* put elements into a heap *)
let h = H.of_iter (Iter.of_list l) in
OUnit2.assert_equal 1_000 (H.size h);
let l' = extract_list h in
is_sorted l'
)
*)
(* test filter *)
(*$QR & ~count:30
Q.(list_of_size Gen.(return 1_000) int) (fun l ->
(* put elements into a heap *)
let h = H.of_iter (Iter.of_list l) in
let h = H.filter (fun x->x mod 2=0) h in
OUnit2.assert_bool "all odd"
(H.to_iter h |> Iter.for_all (fun x -> x mod 2 = 0));
let l' = extract_list h in
is_sorted l'
)
*)
(*$QR
Q.(list_of_size Gen.(return 1_000) int) (fun l ->
(* put elements into a heap *)
let h = H.of_iter (Iter.of_list l) in
let l' = H.to_iter_sorted h |> Iter.to_list in
is_sorted l'
)
*)
module type S = sig
type elt
type t
@ -405,16 +342,6 @@ module Make(E : PARTIAL_ORD) : S with type elt = E.t = struct
Some x
in next
(*$Q
Q.(list int) (fun l -> \
extract_list (H.of_list l) = \
extract_list (H.of_gen (CCList.to_gen l)))
Q.(list int) (fun l -> \
let h = H.of_list l in \
(H.to_gen h |> CCList.of_gen |> List.sort Stdlib.compare) \
= (H.to_list h |> List.sort Stdlib.compare))
*)
let rec to_tree h () = match h with
| E -> `Nil
| N (_, x, l, r) -> `Node(x, [to_tree l; to_tree r])
@ -424,17 +351,6 @@ module Make(E : PARTIAL_ORD) : S with type elt = E.t = struct
|> List.map elt_to_string
|> String.concat sep
(*$Q
Q.(list int) (fun l -> \
let h = H.of_list l in \
(H.to_string string_of_int h) \
= (List.sort Stdlib.compare l |> List.map string_of_int |> String.concat ","))
Q.(list int) (fun l -> \
let h = H.of_list l in \
(H.to_string ~sep:" " string_of_int h) \
= (List.sort Stdlib.compare l |> List.map string_of_int |> String.concat " "))
*)
let pp ?(pp_start=fun _ () -> ()) ?(pp_stop=fun _ () -> ())
?(pp_sep=fun out () -> Format.fprintf out ",") pp_elt out h =
let first=ref true in
@ -453,11 +369,3 @@ module Make_from_compare(E : TOTAL_ORD) =
let leq a b = E.compare a b <= 0
end)
(*$QR
Q.(list_of_size Gen.(return 1_000) int) (fun l ->
let module H' = Make_from_compare(CCInt) in
let h = H'.of_list l in
let l' = H'.to_list_sorted h in
is_sorted l'
)
*)

View file

@ -167,19 +167,6 @@ let read_all_bytes ?(size=1024) ic = read_all_ ~op:Ret_bytes ~size ic
let read_all ?(size=1024) ic = read_all_ ~op:Ret_string ~size ic
(*$R
let s = String.make 200 'y' in
let s = Printf.sprintf "a\nb\n %s\nlast line\n" s in
File.with_temp ~prefix:"test_containers" ~suffix:""
(fun name ->
with_out name @@ fun oc ->
output_string oc s;
flush oc;
let s' = with_in name read_all in
OUnit2.assert_equal ~printer:(fun s->s) s s'
)
*)
let with_out ?(mode=0o644) ?(flags=[Open_creat; Open_trunc; Open_text]) filename f =
let oc = open_out_gen (Open_wronly::flags) mode filename in
@ -235,34 +222,6 @@ let write_lines_l oc l =
(* test {read,write}_lines. Need to concatenate the lists because some
strings in the random input might contain '\n' themselves *)
(*$QR
Q.(list_of_size Gen.(0 -- 40) printable_string) (fun l ->
let l' = ref [] in
File.with_temp ~prefix:"test_containers" ~suffix:""
(fun name ->
with_out name @@ fun oc ->
write_lines_l oc l;
flush oc;
l' := with_in name read_lines_l;
);
String.concat "\n" l = String.concat "\n" !l'
)
*)
(*$QR
Q.(list_of_size Gen.(0 -- 40) printable_string) (fun l ->
let l' = ref [] in
File.with_temp ~prefix:"test_containers" ~suffix:""
(fun name ->
with_out name @@ fun oc ->
write_lines oc (Gen.of_list l);
flush oc;
l' := with_in name (fun ic -> read_lines_gen ic |> Gen.to_list);
);
String.concat "\n" l = String.concat "\n" !l'
)
*)
let with_in_out ?(mode=0o644) ?(flags=[Open_creat]) filename f =
let ic = open_in_gen (Open_rdonly::flags) mode filename in
let oc = open_out_gen (Open_wronly::flags) mode filename in
@ -288,25 +247,6 @@ let copy_into ?(bufsize=4_096) ic oc : unit =
)
done
(*$QR
Q.(list_of_size Gen.(0 -- 40) printable_string) (fun l ->
let s = ref "" in
File.with_temp ~prefix:"test_containers1" ~suffix:""
(fun name1 ->
with_out name1 @@ fun oc1 ->
write_gen ~sep:"" oc1 (Gen.of_list l);
flush oc1;
File.with_temp ~prefix:"test_containers2" ~suffix:""
(fun name2 ->
with_out name2 @@ fun oc2 ->
CCIO.with_in name1 (fun ic1 -> copy_into ic1 oc2);
flush oc2;
s := with_in name2 read_all;);
);
String.concat "" l = !s
)
*)
let tee funs g () = match g() with
| None -> None
| Some x as res ->
@ -394,17 +334,6 @@ module File = struct
)
else gen_singleton (`File, d)
(*$R
OUnit2.assert_bool "walk categorizes files"
(File.walk "."
|> Gen.for_all
(function
| `File, f -> not (Sys.is_directory f)
| `Dir, f -> Sys.is_directory f
)
)
*)
let walk_seq d = seq_of_gen_ (walk d)
let walk_iter d = fun yield -> gen_iter yield (walk d)

View file

@ -74,23 +74,11 @@ let range i j yield =
in
if i<=j then up i j yield else down i j yield
(*$= & ~printer:Q.Print.(list int)
[0;1;2;3;4;5] (range 0 5 |> Iter.to_list)
[0] (range 0 0 |> Iter.to_list)
[5;4;3;2] (range 5 2 |> Iter.to_list)
*)
let range' i j yield =
if i<j then range i (j-1) yield
else if i=j then ()
else range i (j+1) yield
(*$= & ~printer:Q.Print.(list int)
[] (range' 0 0 |> Iter.to_list)
[0;1;2;3;4] (range' 0 5 |> Iter.to_list)
[5;4;3] (range' 5 2 |> Iter.to_list)
*)
let sign i = compare i 0
let neg i = -i
@ -108,14 +96,6 @@ let pow a b =
| b when b < 0 -> raise (Invalid_argument "pow: can't raise int to negative power")
| b -> aux a b
(*$T
pow 2 10 = 1024
pow 2 15 = 32768
pow 10 5 = 100000
pow 1 0 = 1
pow 0 1 = 0
*)
module Infix : sig
val (=) : t -> t -> bool
val (<>) : t -> t -> bool
@ -158,36 +138,6 @@ let floor_div a n =
else
a / n
(*$T
(floor_div 3 5 = 0)
(floor_div 5 5 = 1)
(floor_div 20 5 = 4)
(floor_div 12 5 = 2)
(floor_div 0 5 = 0)
(floor_div (-1) 5 = -1)
(floor_div (-5) 5 = -1)
(floor_div (-12) 5 = -3)
(floor_div 0 (-5) = 0)
(floor_div 3 (-5) = -1)
(floor_div 5 (-5) = -1)
(floor_div 9 (-5) = -2)
(floor_div 20 (-5) = -4)
(floor_div (-2) (-5) = 0)
(floor_div (-8) (-5) = 1)
(floor_div (-35) (-5) = 7)
try ignore (floor_div 12 0); false with Division_by_zero -> true
try ignore (floor_div (-12) 0); false with Division_by_zero -> true
*)
(*$Q
(Q.pair Q.small_signed_int Q.pos_int) \
(fun (n, m) -> floor_div n m = int_of_float @@ floor (float n /. float m))
(Q.pair Q.small_signed_int Q.pos_int) \
(fun (n, m) -> floor_div n (-m) = int_of_float @@ floor (float n /. float (-m)))
*)
let bool_neq (a : bool) b = Stdlib.(<>) a b
let rem a n =
@ -197,38 +147,6 @@ let rem a n =
else
y
(*$T
(rem 3 5 = 3)
(rem 5 5 = 0)
(rem 9 5 = 4)
(rem (-1) 5 = 4)
(rem (-5) 5 = 0)
(rem (-20) 5 = 0)
(rem (-9) 5 = 1)
(rem 0 5 = 0)
(rem 0 (-5) = 0)
(rem 3 (-5) = -2)
(rem 5 (-5) = 0)
(rem 9 (-5) = -1)
(rem (-2) (-5) = -2)
(rem (-8) (-5) = -3)
(rem (-35) (-5) = 0)
try ignore (rem 12 0); false with Division_by_zero -> true
try ignore (rem (-12) 0); false with Division_by_zero -> true
*)
(*$Q
(Q.pair Q.int Q.pos_int) (fun (n, m) -> let y = rem n m in y >= 0 && y < m)
(Q.pair Q.int Q.pos_int) (fun (n, m) -> let y = rem n (-m) in y > (-m) && y <= 0)
*)
(*$Q
(Q.pair Q.int Q.pos_int) (fun (n, m) -> n = m * floor_div n m + rem n m)
(Q.pair Q.int Q.pos_int) (fun (n, m) -> n = (-m) * floor_div n (-m) + rem n (-m))
*)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
@ -247,21 +165,12 @@ let of_string s =
try Some (int_of_string s)
with Failure _ -> None
(*$=
None (of_string "moo")
(Some 42) (of_string "42")
*)
let of_string_exn = Stdlib.int_of_string
let to_float = float_of_int
let of_float = int_of_float
(*$=
1 (of_float 1.2)
*)
type output = char -> unit
(* abstract printer *)
@ -292,17 +201,6 @@ let to_string_binary n =
to_binary_gen (Buffer.add_char buf) n;
Buffer.contents buf
(*$= & ~printer:CCFun.id
"0b111" (to_string_binary 7)
"-0b111" (to_string_binary (-7))
"0b0" (to_string_binary 0)
*)
(*$Q & ~count:10_000
Q.int (fun n -> n = int_of_string (to_string_binary n))
*)
let range_by ~step i j yield =
let rec range i j yield =
if i=j then yield i
@ -316,29 +214,6 @@ let range_by ~step i j yield =
else if (if step > 0 then i>j else i<j) then ()
else range i ((j-i)/step*step + i) yield
(* note: the last test checks that no error occurs due to overflows. *)
(*$= & ~printer:Q.Print.(list int)
[0] (range_by ~step:1 0 0 |> Iter.to_list)
[] (range_by ~step:1 5 0 |> Iter.to_list)
[] (range_by ~step:2 1 0 |> Iter.to_list)
[0;2;4] (range_by ~step:2 0 4 |> Iter.to_list)
[0;2;4] (range_by ~step:2 0 5 |> Iter.to_list)
[0] (range_by ~step:~-1 0 0 |> Iter.to_list)
[] (range_by ~step:~-1 0 5 |> Iter.to_list)
[] (range_by ~step:~-2 0 1 |> Iter.to_list)
[5;3;1] (range_by ~step:~-2 5 1 |> Iter.to_list)
[5;3;1] (range_by ~step:~-2 5 0 |> Iter.to_list)
[0] (range_by ~step:max_int 0 2 |> Iter.to_list)
*)
(*$Q
Q.(pair small_int small_int) (fun (i,j) -> \
let i = min i j and j = max i j in \
CCList.equal CCInt.equal \
(CCInt.range_by ~step:1 i j |> Iter.to_list) \
(CCInt.range i j |> Iter.to_list) )
*)
(*
from https://en.wikipedia.org/wiki/Hamming_weight
@ -377,44 +252,6 @@ let popcount (b:int) : int =
let b = logand b 0x7fL in
to_int b
(*$=
0 (popcount 0)
1 (popcount 1)
(Sys.word_size-2) (popcount max_int)
1 (popcount min_int)
10 (popcount 0b1110010110110001010)
5 (popcount 0b1101110000000000)
*)
(*$inject
let simple_popcnt i =
let rec loop n i =
if i=0 then n
else if i land 0b1 = 1 then loop (n+1) (i lsr 1)
else loop n (i lsr 1)
in
loop 0 i
*)
(*$=
0 (simple_popcnt 0)
1 (simple_popcnt 1)
(Sys.word_size-2) (simple_popcnt max_int)
1 (simple_popcnt min_int)
5 (simple_popcnt 0b1101110000000000)
*)
(*$QR & ~count:3_000 ~long_factor:10
Q.(let g = int in
set_gen (Gen.graft_corners g.gen [min_int; max_int; 0; -1; 1] ()) g)
(fun i ->
if simple_popcnt i <> popcount i then (
Q.Test.fail_reportf "on %d: simple-popcount=%d, popcount=%d"
i (simple_popcnt i) (popcount i)
);
true)
*)
let logand = (land)
let logor = (lor)

View file

@ -24,14 +24,6 @@ let pow a b =
| b when compare b 0l < 0 -> raise (Invalid_argument "pow: can't raise int to negative power")
| b -> aux a b
(*$T
pow 2l 10l = 1024l
pow 2l 15l = 32768l
pow 10l 5l = 100000l
pow 42l 0l = 1l
pow 0l 1l = 0l
*)
let floor_div a n =
if compare a 0l < 0 && compare n 0l >= 0 then
sub (div (add a 1l) n) 1l
@ -40,38 +32,6 @@ let floor_div a n =
else
div a n
(*$T
(floor_div 3l 5l = 0l)
(floor_div 5l 5l = 1l)
(floor_div 20l 5l = 4l)
(floor_div 12l 5l = 2l)
(floor_div 0l 5l = 0l)
(floor_div (-1l) 5l = -1l)
(floor_div (-5l) 5l = -1l)
(floor_div (-12l) 5l = -3l)
(floor_div 0l (-5l) = 0l)
(floor_div 3l (-5l) = -1l)
(floor_div 5l (-5l) = -1l)
(floor_div 9l (-5l) = -2l)
(floor_div 20l (-5l) = -4l)
(floor_div (-2l) (-5l) = 0l)
(floor_div (-8l) (-5l) = 1l)
(floor_div (-35l) (-5l) = 7l)
try ignore (floor_div 12l 0l); false with Division_by_zero -> true
try ignore (floor_div (-12l) 0l); false with Division_by_zero -> true
*)
(*$Q
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1l in \
floor_div n m = of_float @@ floor (to_float n /. to_float m))
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1l in \
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)))
*)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
@ -92,12 +52,6 @@ let range i j yield =
in
if compare i j <= 0 then up i j yield else down i j yield
(*$= & ~printer:Q.Print.(list to_string)
[0l;1l;2l;3l;4l;5l] (range 0l 5l |> Iter.to_list)
[0l] (range 0l 0l |> Iter.to_list)
[5l;4l;3l;2l] (range 5l 2l |> Iter.to_list)
*)
let range' i j yield =
if compare i j < 0 then range i (sub j 1l) yield
else if equal i j then ()
@ -116,29 +70,6 @@ let range_by ~step i j yield =
else if (if compare step 0l > 0 then compare i j > 0 else compare i j < 0) then ()
else range i (add (mul (div (sub j i) step) step) i) yield
(* note: the last test checks that no error occurs due to overflows. *)
(*$= & ~printer:Q.Print.(list to_string)
[0l] (range_by ~step:1l 0l 0l |> Iter.to_list)
[] (range_by ~step:1l 5l 0l |> Iter.to_list)
[] (range_by ~step:2l 1l 0l |> Iter.to_list)
[0l;2l;4l] (range_by ~step:2l 0l 4l |> Iter.to_list)
[0l;2l;4l] (range_by ~step:2l 0l 5l |> Iter.to_list)
[0l] (range_by ~step:(neg 1l) 0l 0l |> Iter.to_list)
[] (range_by ~step:(neg 1l) 0l 5l |> Iter.to_list)
[] (range_by ~step:(neg 2l) 0l 1l |> Iter.to_list)
[5l;3l;1l] (range_by ~step:(neg 2l) 5l 1l |> Iter.to_list)
[5l;3l;1l] (range_by ~step:(neg 2l) 5l 0l |> Iter.to_list)
[0l] (range_by ~step:max_int 0l 2l |> Iter.to_list)
*)
(*$Q
Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) -> \
let i = min i j and j = max i j in \
CCList.equal CCInt32.equal \
(CCInt32.range_by ~step:1l i j |> Iter.to_list) \
(CCInt32.range i j |> Iter.to_list) )
*)
let random n st = Random.State.int32 st n
let random_small = random 100l
let random_range i j st = add i (random (sub j i) st)
@ -181,12 +112,6 @@ let to_string_binary n =
to_binary_gen (Buffer.add_char buf) n;
Buffer.contents buf
(*$= & ~printer:CCFun.id
"0b111" (to_string_binary 7l)
"-0b111" (to_string_binary (-7l))
"0b0" (to_string_binary 0l)
*)
(** {2 Printing} *)
let pp out n = Format.pp_print_string out (to_string n)

View file

@ -24,14 +24,6 @@ let pow a b =
| b when compare b 0L < 0 -> raise (Invalid_argument "pow: can't raise int to negative power")
| b -> aux a b
(*$T
pow 2L 10L = 1024L
pow 2L 15L = 32768L
pow 10L 5L = 100000L
pow 42L 0L = 1L
pow 0L 1L = 0L
*)
let floor_div a n =
if compare a 0L < 0 && compare n 0L >= 0 then
sub (div (add a 1L) n) 1L
@ -40,38 +32,6 @@ let floor_div a n =
else
div a n
(*$T
(floor_div 3L 5L = 0L)
(floor_div 5L 5L = 1L)
(floor_div 20L 5L = 4L)
(floor_div 12L 5L = 2L)
(floor_div 0L 5L = 0L)
(floor_div (-1L) 5L = -1L)
(floor_div (-5L) 5L = -1L)
(floor_div (-12L) 5L = -3L)
(floor_div 0L (-5L) = 0L)
(floor_div 3L (-5L) = -1L)
(floor_div 5L (-5L) = -1L)
(floor_div 9L (-5L) = -2L)
(floor_div 20L (-5L) = -4L)
(floor_div (-2L) (-5L) = 0L)
(floor_div (-8L) (-5L) = 1L)
(floor_div (-35L) (-5L) = 7L)
try ignore (floor_div 12L 0L); false with Division_by_zero -> true
try ignore (floor_div (-12L) 0L); false with Division_by_zero -> true
*)
(*$Q
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1L in \
floor_div n m = of_float @@ floor (to_float n /. to_float m))
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1L in \
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)))
*)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
@ -92,12 +52,6 @@ let range i j yield =
in
if compare i j <= 0 then up i j yield else down i j yield
(*$= & ~printer:Q.Print.(list to_string)
[0L;1L;2L;3L;4L;5L] (range 0L 5L |> Iter.to_list)
[0L] (range 0L 0L |> Iter.to_list)
[5L;4L;3L;2L] (range 5L 2L |> Iter.to_list)
*)
let range' i j yield =
if compare i j < 0 then range i (sub j 1L) yield
else if equal i j then ()
@ -116,29 +70,6 @@ let range_by ~step i j yield =
else if (if compare step 0L > 0 then compare i j > 0 else compare i j < 0) then ()
else range i (add (mul (div (sub j i) step) step) i) yield
(* note: the last test checks that no error occurs due to overflows. *)
(*$= & ~printer:Q.Print.(list to_string)
[0L] (range_by ~step:1L 0L 0L |> Iter.to_list)
[] (range_by ~step:1L 5L 0L |> Iter.to_list)
[] (range_by ~step:2L 1L 0L |> Iter.to_list)
[0L;2L;4L] (range_by ~step:2L 0L 4L |> Iter.to_list)
[0L;2L;4L] (range_by ~step:2L 0L 5L |> Iter.to_list)
[0L] (range_by ~step:(neg 1L) 0L 0L |> Iter.to_list)
[] (range_by ~step:(neg 1L) 0L 5L |> Iter.to_list)
[] (range_by ~step:(neg 2L) 0L 1L |> Iter.to_list)
[5L;3L;1L] (range_by ~step:(neg 2L) 5L 1L |> Iter.to_list)
[5L;3L;1L] (range_by ~step:(neg 2L) 5L 0L |> Iter.to_list)
[0L] (range_by ~step:max_int 0L 2L |> Iter.to_list)
*)
(*$Q
Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) -> \
let i = min i j and j = max i j in \
CCList.equal CCInt64.equal \
(CCInt64.range_by ~step:1L i j |> Iter.to_list) \
(CCInt64.range i j |> Iter.to_list) )
*)
let random n st = Random.State.int64 st n
let random_small = random 100L
let random_range i j st = add i (random (sub j i) st)
@ -181,12 +112,6 @@ let to_string_binary n =
to_binary_gen (Buffer.add_char buf) n;
Buffer.contents buf
(*$= & ~printer:CCFun.id
"0b111" (to_string_binary 7L)
"-0b111" (to_string_binary (-7L))
"0b0" (to_string_binary 0L)
*)
(** {2 Printing} *)
let pp out n = Format.pp_print_string out (to_string n)

View file

@ -162,10 +162,6 @@ module type S = sig
contents of the map. *)
end
(*$inject
module M = CCMap.Make(String)
*)
module Make(O : Map.OrderedType) = struct
module M = Map.Make(O)
@ -238,15 +234,6 @@ module Make(O : Map.OrderedType) = struct
| None -> raise Not_found
| Some (k,v) -> k, v
(*$= & ~printer:CCFormat.(to_string @@ Dump.(list (pair string int)))
["a", 1; "b", 20] \
(M.of_list ["b", 2; "c", 3] \
|> M.update "a" (function _ -> Some 1) \
|> M.update "c" (fun _ -> None) \
|> M.update "b" (CCOption.map (fun x -> x * 10)) \
|> M.to_list |> List.sort CCOrd.compare)
*)
(* === include M.
This will shadow some values depending on OCaml's current version
=== *)
@ -333,18 +320,3 @@ module Make(O : Map.OrderedType) = struct
m;
pp_stop fmt ()
end
(*$inject
module M2 = Make(CCInt)
*)
(*$Q
Q.(list (pair small_int small_int)) M2.(fun l -> \
to_list (of_list l) = to_list (of_list_with ~f:(fun _ v _ ->v) l))
Q.(list (pair small_int small_int)) M2.(fun l -> \
to_list (of_iter @@ Iter.of_list l) = \
to_list (of_iter_with ~f:(fun _ v _ ->v) @@ Iter.of_list l))
Q.(list (pair small_int small_int)) M2.(fun l -> \
to_list (of_seq @@ CCSeq.of_list l) = \
to_list (of_seq_with ~f:(fun _ v _ ->v) @@ CCSeq.of_list l))
*)

View file

@ -24,14 +24,6 @@ let pow a b =
| b when compare b 0n < 0 -> raise (Invalid_argument "pow: can't raise int to negative power")
| b -> aux a b
(*$T
pow 2n 10n = 1024n
pow 2n 15n = 32768n
pow 10n 5n = 100000n
pow 42n 0n = 1n
pow 0n 1n = 0n
*)
let floor_div a n =
if compare a 0n < 0 && compare n 0n >= 0 then
sub (div (add a 1n) n) 1n
@ -40,38 +32,6 @@ let floor_div a n =
else
div a n
(*$T
(floor_div 3n 5n = 0n)
(floor_div 5n 5n = 1n)
(floor_div 20n 5n = 4n)
(floor_div 12n 5n = 2n)
(floor_div 0n 5n = 0n)
(floor_div (-1n) 5n = -1n)
(floor_div (-5n) 5n = -1n)
(floor_div (-12n) 5n = -3n)
(floor_div 0n (-5n) = 0n)
(floor_div 3n (-5n) = -1n)
(floor_div 5n (-5n) = -1n)
(floor_div 9n (-5n) = -2n)
(floor_div 20n (-5n) = -4n)
(floor_div (-2n) (-5n) = 0n)
(floor_div (-8n) (-5n) = 1n)
(floor_div (-35n) (-5n) = 7n)
try ignore (floor_div 12n 0n); false with Division_by_zero -> true
try ignore (floor_div (-12n) 0n); false with Division_by_zero -> true
*)
(*$Q
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1n in \
floor_div n m = of_float @@ floor (to_float n /. to_float m))
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1n in \
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)))
*)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
@ -92,12 +52,6 @@ let range i j yield =
in
if compare i j <= 0 then up i j yield else down i j yield
(*$= & ~printer:Q.Print.(list to_string)
[0n;1n;2n;3n;4n;5n] (range 0n 5n |> Iter.to_list)
[0n] (range 0n 0n |> Iter.to_list)
[5n;4n;3n;2n] (range 5n 2n |> Iter.to_list)
*)
let range' i j yield =
if compare i j < 0 then range i (sub j 1n) yield
else if equal i j then ()
@ -116,29 +70,6 @@ let range_by ~step i j yield =
else if (if compare step 0n > 0 then compare i j > 0 else compare i j < 0) then ()
else range i (add (mul (div (sub j i) step) step) i) yield
(* note: the last test checks that no error occurs due to overflows. *)
(*$= & ~printer:Q.Print.(list to_string)
[0n] (range_by ~step:1n 0n 0n |> Iter.to_list)
[] (range_by ~step:1n 5n 0n |> Iter.to_list)
[] (range_by ~step:2n 1n 0n |> Iter.to_list)
[0n;2n;4n] (range_by ~step:2n 0n 4n |> Iter.to_list)
[0n;2n;4n] (range_by ~step:2n 0n 5n |> Iter.to_list)
[0n] (range_by ~step:(neg 1n) 0n 0n |> Iter.to_list)
[] (range_by ~step:(neg 1n) 0n 5n |> Iter.to_list)
[] (range_by ~step:(neg 2n) 0n 1n |> Iter.to_list)
[5n;3n;1n] (range_by ~step:(neg 2n) 5n 1n |> Iter.to_list)
[5n;3n;1n] (range_by ~step:(neg 2n) 5n 0n |> Iter.to_list)
[0n] (range_by ~step:max_int 0n 2n |> Iter.to_list)
*)
(*$Q
Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) -> \
let i = min i j and j = max i j in \
CCList.equal CCNativeint.equal \
(CCNativeint.range_by ~step:1n i j |> Iter.to_list) \
(CCNativeint.range i j |> Iter.to_list) )
*)
let random n st = Random.State.nativeint st n
let random_small = random 100n
let random_range i j st = add i (random (sub j i) st)
@ -181,12 +112,6 @@ let to_string_binary n =
to_binary_gen (Buffer.add_char buf) n;
Buffer.contents buf
(*$= & ~printer:CCFun.id
"0b111" (to_string_binary 7n)
"-0b111" (to_string_binary (-7n))
"0b0" (to_string_binary 0n)
*)
(** {2 Printing} *)
let pp out n = Format.pp_print_string out (to_string n)

View file

@ -76,12 +76,6 @@ let filter p = function
| Some x as o when p x -> o
| _ -> None
(*$=
None (filter ((=) 0) (Some 1))
(Some 0) (filter ((=) 0) (Some 0))
None (filter (fun _ -> true) None)
*)
let if_ p x = if p x then Some x else None
let exists p = function
@ -116,11 +110,6 @@ let get_exn_or msg = function
| Some x -> x
| None -> invalid_arg msg
(*$T
(try get_exn_or "ohno" (None:unit option); false with Invalid_argument s->s= "ohno")
123 = get_exn_or "yes" (Some 123)
*)
let get_lazy default_fn x = match x with
| None -> default_fn ()
| Some y -> y
@ -133,12 +122,6 @@ let sequence_l l =
in
try aux [] l with Exit -> None
(*$T
sequence_l [None; Some 1; Some 2] = None
sequence_l [Some 1; Some 2; Some 3] = Some [1;2;3]
sequence_l [] = Some []
*)
let wrap ?(handler=fun _ -> true) f x =
try Some (f x)
with e ->
@ -211,23 +194,11 @@ let choice_iter s =
end;
!r
(*$T
choice_iter (Iter.of_list [None; Some 1; Some 2]) = Some 1
choice_iter Iter.empty = None
choice_iter (Iter.repeat None |> Iter.take 100) = None
*)
let rec choice_seq s = match s() with
| Seq.Nil -> None
| Seq.Cons (Some x, _) -> Some x
| Seq.Cons (None, tl) -> choice_seq tl
(*$T
choice_seq (CCSeq.of_list [None; Some 1; Some 2]) = Some 1
choice_seq CCSeq.empty = None
choice_seq (CCSeq.repeat None |> CCSeq.take 100) = None
*)
let to_gen o =
match o with
| None -> (fun () -> None)
@ -251,19 +222,8 @@ let flatten = function
| Some x -> x
| None -> None
(*$T
flatten None = None
flatten (Some None) = None
flatten (Some (Some 1)) = Some 1
*)
let return_if b x =
if b then
Some x
else
None
(*$T
return_if false 1 = None
return_if true 1 = Some 1
*)

View file

@ -18,35 +18,11 @@ let equiv i j =
else if i>0 then j>0
else j=0
(*$T
equiv 1 2
equiv ~-1 ~-10
equiv 0 0
equiv ~-1 ~-1
not (equiv 0 1)
not (equiv 1 ~-1)
not (equiv 1 0)
*)
(*$Q
Q.(pair int int) (fun (x,y) -> \
(equiv x y) = (equiv y x))
Q.(triple int int int) (fun (x,y,z) -> \
if (equiv x y && equiv y z) then (equiv x z) else true)
*)
let int (x:int) y = Stdlib.compare x y
let string (x:string) y = Stdlib.compare x y
let bool (x:bool) y = Stdlib.compare x y
let float (x:float) y = Stdlib.compare x y
(*$T
bool true false > 0
bool false true < 0
bool true true = 0
bool false false = 0
*)
(** {2 Lexicographic Combination} *)
let (<?>) c (ord,x,y) =
@ -60,22 +36,12 @@ let option c o1 o2 = match o1, o2 with
| Some _, None -> 1
| Some x1, Some x2 -> c x1 x2
(*$Q
Q.(option int) (fun o -> option int None o <= 0)
*)
let pair o_x o_y (x1,y1) (x2,y2) =
let c = o_x x1 x2 in
if c = 0
then o_y y1 y2
else c
(*$T
pair int string (1, "b") (2, "a") < 0
pair int string (1, "b") (0, "a") > 0
pair int string (1, "b") (1, "b") = 0
*)
let triple o_x o_y o_z (x1,y1,z1) (x2,y2,z2) =
let c = o_x x1 x2 in
if c = 0
@ -96,17 +62,6 @@ let rec list ord l1 l2 = match l1, l2 with
then list ord l1' l2'
else c
(*$T
list int [1;2;3] [1;2;3;4] < 0
list int [1;2;3;4] [1;2;3] > 0
list int [1;2;3;4] [1;3;4] < 0
*)
(*$Q
Q.(pair (list int)(list int)) CCOrd.(fun (l1,l2) -> \
equiv (list int l1 l2) (Stdlib.compare l1 l2))
*)
let array ord a1 a2 =
let rec aux i =
if i = Array.length a1
@ -121,17 +76,6 @@ let array ord a1 a2 =
in
aux 0
(*$T
array int [|1;2;3|] [|1;2;3;4|] < 0
array int [|1;2;3;4|] [|1;2;3|] > 0
array int [|1;2;3;4|] [|1;3;4|] < 0
*)
(*$Q & ~small:(fun (a1, a2) -> Array.length a1+Array.length a2)
Q.(pair (array int)(array int)) CCOrd.(fun (a1,a2) -> \
equiv (array int a1 a2) (list int (Array.to_list a1) (Array.to_list a2)))
*)
let map f ord a b = ord (f a) (f b)
let (>|=) x f = map f x

View file

@ -4,108 +4,6 @@
open CCShims_
(*$inject
module T = struct
type tree = L of int | N of tree * tree
end
open T
let mk_leaf x = L x
let mk_node x y = N(x,y)
let ptree = fix @@ fun self ->
skip_space *>
( (char '(' *> (pure mk_node <*> self <*> self) <* char ')')
<|>
(U.int >|= mk_leaf) )
let ptree' = fix_memo @@ fun self ->
skip_space *>
( (char '(' *> (pure mk_node <*> self <*> self) <* char ')')
<|>
(U.int >|= mk_leaf) )
let rec pptree = function
| N (a,b) -> Printf.sprintf "N (%s, %s)" (pptree a) (pptree b)
| L x -> Printf.sprintf "L %d" x
let errpp pp = function
| Ok x -> "Ok " ^ pp x
| Error s -> "Error " ^ s
let errpptree = errpp pptree
let erreq eq x y = match x, y with
| Ok x, Ok y -> eq x y
| Error _ , Error _ -> true
| _ -> false ;;
*)
(*$= & ~printer:errpptree
(Ok (N (L 1, N (L 2, L 3)))) \
(parse_string ptree "(1 (2 3))" )
(Ok (N (N (L 1, L 2), N (L 3, N (L 4, L 5))))) \
(parse_string ptree "((1 2) (3 (4 5)))" )
(Ok (N (L 1, N (L 2, L 3)))) \
(parse_string ptree' "(1 (2 3))" )
(Ok (N (N (L 1, L 2), N (L 3, N (L 4, L 5))))) \
(parse_string ptree' "((1 2) (3 (4 5)))" )
*)
(*$R
let p = U.list ~sep:"," U.word in
let printer = function
| Ok l -> "Ok " ^ CCFormat.(to_string (Dump.list string_quoted)) l
| Error s -> "Error " ^ s
in
assert_equal ~printer
(Ok ["abc"; "de"; "hello"; "world"])
(parse_string p "[abc , de, hello ,world ]");
*)
(*$R
let test n =
let p = CCParse.(U.list ~sep:"," U.int) in
let l = CCList.(1 -- n) in
let l_printed =
CCFormat.(to_string (within "[" "]" (list ~sep:(return ",") int))) l in
let l' = CCParse.parse_string_exn p l_printed in
assert_equal ~printer:Q.Print.(list int) l l'
in
test 300_000;
*)
(*$R
let open CCParse.Infix in
let module P = CCParse in
let parens p = P.char '(' *> p <* P.char ')' in
let add = P.char '+' *> P.return (+) in
let sub = P.char '-' *> P.return (-) in
let mul = P.char '*' *> P.return ( * ) in
let div = P.char '/' *> P.return ( / ) in
let integer =
P.chars1_if (function '0'..'9'->true|_->false) >|= int_of_string in
let chainr1 e op =
P.fix (fun r ->
e >>= fun x -> (op <*> P.return x <*> r) <|> P.return x) in
let expr : int P.t =
P.fix (fun expr ->
let factor = parens expr <|> integer in
let term = chainr1 factor (mul <|> div) in
chainr1 term (add <|> sub)) in
assert_equal (Ok 6) (P.parse_string expr "4*1+2");
assert_equal (Ok 12) (P.parse_string expr "4*(1+2)");
()
*)
module Memo_tbl = Hashtbl.Make(struct
type t = int * int (* id of parser, position *)
let equal ((a,b):t)(c,d) = a=c && b=d
@ -381,12 +279,6 @@ let eoi = {
else err (mk_error_ st (const_str_ "expected end of input"))
}
(*$= & ~printer:(errpp Q.Print.bool) ~cmp:(erreq (=))
(Ok true) (parse_string (U.bool <* eoi) "true")
(Error "") (parse_string (U.bool <* eoi) "true ")
(Ok true) (parse_string (U.bool <* skip_white <* eoi) "true")
*)
let with_pos p : _ t = {
run=fun st ~ok ~err ->
p.run st
@ -399,21 +291,6 @@ let pos : _ t = {
run=fun st ~ok ~err:_ -> ok st (pos_of_st_ st)
}
(*$= & ~printer:Q.Print.(pair int int)
(0,5) (let p = any_char_n 5 *> pos in \
match parse_string p "abcde " with \
| Ok p -> Position.line_and_column p \
| Error _ -> assert false)
*)
(*$= & ~printer:Q.Print.(list @@ pair int int)
[(0,2); (1,3); (2,1); (3,0); (4,0); (5,2)] \
(let p = each_line (skip_space *> pos) in \
match parse_string p " a\n b\nc\n\n\n a" with \
| Ok ps -> List.map Position.line_and_column ps \
| Error _ -> assert false)
*)
(* a slice is just a state, which makes {!recurse} quite easy. *)
type slice = state
@ -443,16 +320,6 @@ let all = {
let all_str = all >|= Slice.to_string
(*$= & ~printer:(errpp Q.Print.string) ~cmp:(erreq (=))
(Ok "abcd") (parse_string all_str "abcd")
(Ok "cd") (parse_string (string "ab" *> all_str) "abcd")
(Ok "") (parse_string (string "ab" *> all_str) "ab")
*)
(*$= & ~printer:(errpp Q.Print.(pair string string)) ~cmp:(erreq (=))
(Ok ("foobar", "")) (parse_string (both all_str all_str) "foobar")
*)
let fail msg : _ t = {
run=fun st ~ok:_ ~err ->
err (mk_error_ st (const_str_ msg))
@ -559,19 +426,6 @@ let chars1_if ?descr p = {
~err
}
(*$QR
Q.(printable_string) (fun s ->
let pred = (function 'a'..'z' | 'A' .. 'Z' | '{' | '}' -> true | _ -> false) in
let p1 = chars1_if pred in
let p2 = take1_if pred >|= Slice.to_string in
parse_string p1 s = parse_string p2 s)
*)
(*$T
let pred = (function 'a'..'z' | 'A' .. 'Z' | '{' | '}' -> true | _ -> false) in \
parse_string (chars_if pred) "coucou{lol} 123" = Ok "coucou{lol}"
*)
exception Fold_fail of state * string
let chars_fold ~f acc0 = {
@ -787,16 +641,6 @@ let many p : _ t = {
}
*)
(*$R
let p0 = skip_white *> U.int in
let p = (skip_white *> char '(' *> many p0) <* (skip_white <* char ')') in
let printer = CCFormat.(to_string @@ Dump.result @@ Dump.list int) in
assert_equal ~printer
(Ok [1;2;3]) (parse_string p "(1 2 3)");
assert_equal ~printer
(Ok [1;2; -30; 4]) (parse_string p "( 1 2 -30 4 )")
*)
let many1 p =
p >>= fun x ->
@ -836,16 +680,6 @@ let sep ~by p =
) in
Lazy.force read_p
(*$inject
let aword = chars1_if (function 'a'..'z'|'A'..'Z'->true|_ -> false);;
*)
(*$= & ~printer:(errpp Q.Print.(list string))
(Ok ["a";"b";"c"]) \
(parse_string (optional (char '/') *> sep ~by:(char '/') aword) "/a/b/c")
(Ok ["a";"b";"c"]) \
(parse_string (optional (char '/') *> sep ~by:(char '/') aword) "a/b/c")
*)
let sep1 ~by p =
p >>= fun x ->
sep ~by p >|= fun tl ->
@ -871,18 +705,6 @@ let set_current_slice sl : _ t = {
ok sl () (* jump to slice *)
}
(*$= & ~printer:(errpp Q.Print.(string))
(Ok "abc") (parse_string (lookahead (string "ab") *> (string "abc")) "abcd")
*)
(*$= & ~printer:(errpp Q.Print.(string))
(Ok "1234") (parse_string line_str "1234\nyolo")
*)
(*$= & ~printer:(errpp Q.Print.(pair String.escaped String.escaped))
(Ok ("1234", "yolo")) (parse_string (line_str ||| line_str) "1234\nyolo\nswag")
*)
let split_1 ~on_char : _ t = {
run=fun st ~ok ~err:_ ->
if st.i >= st.j then (
@ -922,13 +744,6 @@ let split_list_at_most ~on_char n : slice list t =
in
loop [] n
(*$= & ~printer:(errpp Q.Print.(list string)) ~cmp:(erreq (=))
(Ok ["a";"b";"c";"d,e,f"]) \
(parse_string (split_list_at_most ~on_char:',' 3 >|= List.map Slice.to_string) "a,b,c,d,e,f")
(Ok ["a";"bc"]) \
(parse_string (split_list_at_most ~on_char:',' 3 >|= List.map Slice.to_string) "a,bc")
*)
let split_list ~on_char : _ t =
split_list_at_most ~on_char max_int
@ -986,11 +801,6 @@ let line_str = line >|= Slice.to_string
let each_line p : _ t =
each_split ~on_char:'\n' p
(*$= & ~printer:(errpp Q.Print.(list @@ list int))
(Ok ([[1;1];[2;2];[3;3];[]])) \
(parse_string (each_line (sep ~by:skip_space U.int)) "1 1\n2 2\n3 3\n")
*)
let memo (type a) (p:a t) : a t =
let id = !Memo_state.id_ in
incr Memo_state.id_;
@ -1094,13 +904,6 @@ module U = struct
try return (int_of_string s)
with Failure _ -> fail "expected an int"
(*$= & ~printer:(errpp Q.Print.int) ~cmp:(erreq (=))
(Ok 42) (parse_string U.int " 42")
(Ok 2) (parse_string U.int "2")
(Error "") (parse_string U.int "abc")
(Error "") (parse_string U.int "")
*)
let in_paren (p:'a t) : 'a t =
skip_white *>
(char '(' *> skip_white *> p <* skip_white <* char ')')
@ -1113,16 +916,6 @@ module U = struct
~f:(fun _ -> skip_white *> self <* skip_white <* char ')')
~else_:p)
(*$= & ~printer:(errpp Q.Print.int) ~cmp:(erreq (=))
(Ok 15) (parse_string (U.in_paren (U.in_paren U.int)) "( ( 15) )")
(Ok 2) (parse_string (U.in_paren U.int) "(2)")
(Error "") (parse_string (U.in_paren U.int) "2")
(Error "") (parse_string (U.in_paren U.int) "")
(Ok 2) (parse_string (U.in_parens_opt U.int) "((((2))))")
(Ok 2) (parse_string (U.in_parens_opt U.int) "2")
(Ok 200) (parse_string (U.in_parens_opt U.int) "( ( 200 ) )")
*)
let option p =
skip_white *>
try_or
@ -1130,13 +923,6 @@ module U = struct
~f:(fun _ -> skip_white *> p >|= fun x -> Some x)
~else_:(string "None" *> return None)
(*$= & ~printer:(errpp Q.Print.(option int)) ~cmp:(erreq (=))
(Ok (Some 12)) (parse_string U.(option int) " Some 12")
(Ok None) (parse_string U.(option int) " None")
(Ok (Some 0)) (parse_string U.(option int) "Some 0")
(Ok (Some 0)) (parse_string U.(in_parens_opt @@ option int) "(( Some 0) )")
*)
let hexa_int =
(exact "0x" <|> return "") *>
begin
@ -1156,13 +942,6 @@ module U = struct
!i
end
(*$= & ~printer:(errpp Q.Print.int) ~cmp:(erreq (=))
(Ok 16) (parse_string U.hexa_int "0x10")
(Ok 16) (parse_string U.hexa_int "10")
(Error "") (parse_string U.hexa_int "x10")
(Error "") (parse_string U.hexa_int "0xz")
*)
let prepend_str c s = String.make 1 c ^ s
let word =
@ -1171,10 +950,6 @@ module U = struct
let bool =
skip_white *>
((string "true" *> return true) <|> (string "false" *> return false))
(*$= & ~printer:(errpp Q.Print.bool) ~cmp:(erreq (=))
(Ok true) (parse_string U.bool "true")
(Ok false) (parse_string U.bool "false")
*)
let pair ?(start="(") ?(stop=")") ?(sep=",") p1 p2 =
skip_white *> string start *> skip_white *>
@ -1183,10 +958,6 @@ module U = struct
p2 >>= fun x2 ->
skip_white *> string stop *> return (x1,x2)
(*$= & ~printer:Q.Print.(errpp (pair int int))
(Ok(1,2)) U.(parse_string (pair int int) "(1 , 2 )")
*)
let triple ?(start="(") ?(stop=")") ?(sep=",") p1 p2 p3 =
string start *> skip_white *>
p1 >>= fun x1 ->

View file

@ -47,11 +47,6 @@ let pick_list l =
fun st ->
List.nth l (Random.State.int st n)
(*$Q
Q.(list small_int) (fun l -> \
l=[] || List.mem (run (pick_list l)) l)
*)
let pick_array a =
let n = Array.length a in
if n=0 then raise Pick_from_empty;
@ -123,13 +118,6 @@ let split_list i ~len st =
) else
None
(*$Q
Q.(pair small_int small_int) (fun (i,j) -> \
let len, n = 2+min i j, max i j in \
let l = QCheck.Gen.generate1 (split_list n ~len) in \
match l with None -> true | Some l -> l<> [] && List.for_all (fun x->x>0) l)
*)
let retry ?(max=10) g st =
let rec aux n =
match g st with
@ -208,8 +196,3 @@ let (and*) = (and+)
let __default_state = Random.State.make_self_init ()
let run ?(st=__default_state) g = g st
(*$R
let open Containers in
ignore @@ List.random_choose [1;2;3] (Random.get_state())
*)

View file

@ -27,10 +27,6 @@ let fail_printf format =
(fun buf -> fail (Buffer.contents buf))
buf format
(*$T
(Error "ohno 42") = (fail_printf "ohno %d" 42)
*)
let fail_fprintf format =
let buf = Buffer.create 64 in
let out = Format.formatter_of_buffer buf in
@ -38,10 +34,6 @@ let fail_fprintf format =
(fun out -> Format.pp_print_flush out (); fail (Buffer.contents buf))
out format
(*$T
(Error "ohno 42") = (fail_fprintf "ohno %d" 42)
*)
let add_ctx msg x = match x with
| Error e -> Error (e ^ "\ncontext:" ^ msg)
| Ok x -> Ok x
@ -53,11 +45,6 @@ let add_ctxf msg =
(fun out e -> Format.pp_print_flush out (); add_ctx (Buffer.contents buf) e)
out msg
(*$=
(Error "error\ncontext:message(number 42, foo: true)") \
(add_ctxf "message(number %d, foo: %B)" 42 true (Error "error"))
*)
let of_exn e =
let msg = Printexc.to_string e in
Error msg
@ -96,15 +83,6 @@ let iter_err f e = match e with
| Ok _ -> ()
| Error err -> f err
(*$R iter_err
let called_with = ref None in
let f e = called_with := Some e in
iter_err f (Ok 1);
assert_bool "should not apply when Ok" (!called_with = None);
iter_err f (Error 1);
assert_bool "should apply f to Error" (!called_with = Some 1)
*)
exception Get_error
let get_exn = function
@ -123,20 +101,10 @@ let get_or_failwith = function
| Ok x -> x
| Error msg -> failwith msg
(*$T
get_or_failwith (Ok 1) = 1
try ignore @@ get_or_failwith (Error "e"); false with Failure msg -> msg = "e"
*)
let get_lazy default_fn x = match x with
| Ok x -> x
| Error e -> default_fn e
(*$= get_lazy
(get_lazy (fun _ -> 2) (Ok 1)) (1)
(get_lazy (fun _ -> 2) (Error "error")) (2)
*)
let map_or f e ~default = match e with
| Ok x -> f x
| Error _ -> default
@ -168,11 +136,6 @@ let fold_ok f acc r = match r with
| Ok x -> f acc x
| Error _ -> acc
(*$=
42 (fold_ok (+) 2 (Ok 40))
40 (fold_ok (+) 40 (Error "foo"))
*)
let is_ok = function
| Ok _ -> true
| Error _ -> false
@ -243,12 +206,6 @@ let flatten_l l =
| Error e::_ -> Error e
in loop [] l
(*$=
(Ok []) (flatten_l [])
(Ok [1;2;3]) (flatten_l [Ok 1; Ok 2; Ok 3])
(Error "ohno") (flatten_l [Ok 1; Error "ohno"; Ok 2; Ok 3; Error "wut"])
*)
exception LocalExit
let fold_iter f acc seq =

View file

@ -27,12 +27,6 @@ let repeat ?n x = match n with
| None -> _forever x
| Some n -> _repeat n x
(*$T
repeat ~n:4 0 |> to_list = [0;0;0;0]
repeat ~n:0 1 |> to_list = []
repeat 1 |> take 20 |> to_list = (repeat ~n:20 1 |> to_list)
*)
let is_empty l = match l () with
| Nil -> true
| Cons _ -> false
@ -89,10 +83,6 @@ let rec take_while p l () = match l () with
| Cons (x,l') ->
if p x then Cons (x, take_while p l') else Nil
(*$T
of_list [1;2;3;4] |> take_while (fun x->x < 4) |> to_list = [1;2;3]
*)
let rec drop n (l:'a t) () = match l () with
| l' when n=0 -> l'
| Nil -> Nil
@ -103,20 +93,10 @@ let rec drop_while p l () = match l() with
| Cons (x,l') when p x -> drop_while p l' ()
| Cons _ as res -> res
(*$Q
(Q.pair (Q.list Q.small_int) Q.small_int) (fun (l,n) -> \
let s = of_list l in let s1, s2 = take n s, drop n s in \
append s1 s2 |> to_list = l )
*)
let rec map f l () = match l () with
| Nil -> Nil
| Cons (x, l') -> Cons (f x, map f l')
(*$T
(map ((+) 1) (1 -- 5) |> to_list) = (2 -- 6 |> to_list)
*)
let mapi f l =
let rec aux f l i () = match l() with
| Nil -> Nil
@ -125,10 +105,6 @@ let mapi f l =
in
aux f l 0
(*$T
mapi (fun i x -> i,x) (1 -- 3) |> to_list = [0, 1; 1, 2; 2, 3]
*)
let rec fmap f (l:'a t) () = match l() with
| Nil -> Nil
| Cons (x, l') ->
@ -137,11 +113,6 @@ let rec fmap f (l:'a t) () = match l() with
| Some y -> Cons (y, fmap f l')
end
(*$T
fmap (fun x -> if x mod 2=0 then Some (x*3) else None) (1--10) |> to_list \
= [6;12;18;24;30]
*)
let rec filter p l () = match l () with
| Nil -> Nil
| Cons (x, l') ->
@ -155,54 +126,20 @@ let rec append l1 l2 () = match l1 () with
let rec cycle l () = append l (cycle l) ()
(*$T
cycle (of_list [1;2]) |> take 5 |> to_list = [1;2;1;2;1]
cycle (of_list [1; ~-1]) |> take 100_000 |> fold (+) 0 = 0
*)
let rec unfold f acc () = match f acc with
| None -> Nil
| Some (x, acc') -> Cons (x, unfold f acc')
(*$T
let f = function 10 -> None | x -> Some (x, x+1) in \
unfold f 0 |> to_list = [0;1;2;3;4;5;6;7;8;9]
*)
let rec for_all p l =
match l () with
| Nil -> true
| Cons (x, tl) -> p x && for_all p tl
(*$T
for_all ((=) 1) (of_list []) = true
for_all ((=) 1) (of_list [0]) = false
for_all ((=) 1) (of_list [1]) = true
for_all ((=) 1) (of_list [1; 0]) = false
for_all ((=) 1) (of_list [0; 1]) = false
for_all ((=) 1) (of_list [1; 1]) = true
let l () = Cons (0, fun () -> failwith "no second element") in \
try ignore (for_all ((=) 1) l); true with Failure _ -> false
*)
let rec exists p l =
match l () with
| Nil -> false
| Cons (x, tl) -> p x || exists p tl
(*$T
exists ((=) 1) (of_list []) = false
exists ((=) 1) (of_list [0]) = false
exists ((=) 1) (of_list [1]) = true
exists ((=) 1) (of_list [1; 0]) = true
exists ((=) 1) (of_list [0; 1]) = true
exists ((=) 1) (of_list [0; 0]) = false
let l () = Cons (1, fun () -> failwith "no second element") in \
try ignore (exists ((=) 1) l); true with Failure _ -> false
*)
let rec flat_map f l () = match l () with
| Nil -> Nil
| Cons (x, l') ->
@ -245,11 +182,6 @@ let rec group eq l () = match l() with
| Cons (x, l') ->
Cons (cons x (take_while (eq x) l'), group eq (drop_while (eq x) l'))
(*$T
of_list [1;1;1;2;2;3;3;1] |> group (=) |> map to_list |> to_list = \
[[1;1;1]; [2;2]; [3;3]; [1]]
*)
let rec _uniq eq prev l () = match prev, l() with
| _, Nil -> Nil
| None, Cons (x, l') ->
@ -278,12 +210,6 @@ let range i j =
else Cons (i, aux (i-1) j)
in aux i j
(*$T
range 0 5 |> to_list = [0;1;2;3;4;5]
range 0 0 |> to_list = [0]
range 5 2 |> to_list = [5;4;3;2]
*)
let (--) = range
let (--^) i j =
@ -291,13 +217,6 @@ let (--^) i j =
else if i<j then range i (j-1)
else range i (j+1)
(*$T
1 --^ 5 |> to_list = [1;2;3;4]
5 --^ 1 |> to_list = [5;4;3;2]
1 --^ 2 |> to_list = [1]
0 --^ 0 |> to_list = []
*)
let rec fold2 f acc l1 l2 = match l1(), l2() with
| Nil, _
| _, Nil -> acc
@ -351,11 +270,6 @@ let unzip l =
in
first l, second l
(*$Q
Q.(list (pair int int)) (fun l -> \
let l = of_list l in let a, b = unzip l in equal (=) l (zip a b))
*)
let zip_i seq =
let rec loop i seq () = match seq() with
| Nil -> Nil
@ -363,10 +277,6 @@ let zip_i seq =
in
loop 0 seq
(*$=
[0,'a'; 1, 'b'; 2, 'c'] (of_string "abcde" |> zip_i |> take 3 |> to_list)
*)
(** {2 Implementations} *)
let return x () = Cons (x, nil)
@ -428,18 +338,6 @@ let to_array l =
ignore (List.fold_left (fun i x -> a.(i) <- x; i - 1) idx rest : int);
a
(*$Q
Q.(array int) (fun a -> of_array a |> to_array = a)
*)
(*$T
of_array [| 1; 2; 3 |] |> to_list = [1;2;3]
of_list [1;2;3] |> to_array = [| 1; 2; 3; |]
let r = ref 1 in \
let s = unfold (fun i -> if i < 3 then let x = !r in incr r; Some (x, succ i) else None) 0 in \
to_array s = [| 1; 2; 3; |]
*)
let rec to_iter res k = match res () with
| Nil -> ()
| Cons (s, f) -> k s; to_iter f k
@ -474,14 +372,6 @@ let of_gen g =
in
consume (ref (Of_gen_thunk g))
(*$R
let g = let n = ref 0 in fun () -> Some (incr n; !n) in
let l = of_gen g in
assert_equal [1;2;3;4;5;6;7;8;9;10] (take 10 l |> to_list);
assert_equal [1;2;3;4;5;6;7;8;9;10] (take 10 l |> to_list);
assert_equal [11;12] (drop 10 l |> take 2 |> to_list);
*)
let sort ~cmp l =
let l = to_list l in
of_list (List.sort cmp l)
@ -506,20 +396,6 @@ let rec memoize f =
r := MemoSave l;
l
(*$R
let printer = Q.Print.(list int) in
let gen () =
let rec l = let r = ref 0 in fun () -> incr r; Cons (!r, l) in l
in
let l1 = gen () in
assert_equal ~printer [1;2;3;4] (take 4 l1 |> to_list);
assert_equal ~printer [5;6;7;8] (take 4 l1 |> to_list);
let l2 = gen () |> memoize in
assert_equal ~printer [1;2;3;4] (take 4 l2 |> to_list);
assert_equal ~printer [1;2;3;4] (take 4 l2 |> to_list);
*)
(** {2 Fair Combinations} *)
let rec interleave a b () = match a() with
@ -540,12 +416,6 @@ let rec fair_app f a () = match f() with
let (>>-) a f = fair_flat_map f a
let (<.>) f a = fair_app f a
(*$T
interleave (of_list [1;3;5]) (of_list [2;4;6]) |> to_list = [1;2;3;4;5;6]
fair_app (of_list [(+)1; ( * ) 3]) (of_list [1; 10]) \
|> to_list |> List.sort Stdlib.compare = [2; 3; 11; 30]
*)
(** {2 Infix} *)
module Infix = struct

View file

@ -8,13 +8,6 @@ type 'a printer = Format.formatter -> 'a -> unit
module type OrderedType = Set.OrderedType
(*$inject
module S = CCSet.Make(struct
type t = int
let compare x y = Stdlib.compare x y
end)
*)
module type S = sig
include Set.S
@ -165,22 +158,6 @@ module Make(O : Map.OrderedType) = struct
to_list h
|> CCList.to_string ~start ~stop ~sep elt_to_string
(*$= & ~printer:(fun s -> s)
(S.to_string string_of_int (S.of_list [4; 3])) "3,4"
*)
(*$Q
Q.(list int) (fun l -> \
let s = S.of_list l in \
(S.to_string string_of_int s) \
= (CCList.sort_uniq ~cmp:CCInt.compare l \
|> List.map string_of_int |> String.concat ","))
Q.(list int) (fun l -> \
let s = S.of_list l in \
(S.to_string ~sep:" " string_of_int s) \
= (CCList.sort_uniq ~cmp:CCInt.compare l \
|> List.map string_of_int |> String.concat " "))
*)
let pp ?(pp_start=fun _ () -> ()) ?(pp_stop=fun _ () -> ())
?(pp_sep=fun fmt () -> Format.fprintf fmt ",@ ") pp_x fmt m =
pp_start fmt ();

View file

@ -347,92 +347,4 @@ end
include (Make(Basic_) : S with type t := t and type loc = unit)
(*$T
CCResult.to_opt (parse_string "(abc d/e/f \"hello \\\" () world\" )") <> None
CCResult.to_opt (parse_string "(abc ( d e ffff ) \"hello/world\")") <> None
CCResult.to_opt (parse_string "\"\123\bcoucou\"") <> None
*)
(*$= & ~printer:(function Ok x -> to_string x | Error e -> "error " ^ e)
(parse_string "(a b)") (Ok (`List [`Atom "a"; `Atom "b"]))
(parse_string "(a\n ;coucou\n b)") (Ok (`List [`Atom "a"; `Atom "b"]))
(parse_string "(a #; (foo bar\n (1 2 3)) b)") (Ok (`List [`Atom "a"; `Atom "b"]))
(parse_string "#; (a b) (c d)") (Ok (`List [`Atom "c"; `Atom "d"]))
(parse_string "#; (a b) 1") (Ok (`Atom "1"))
*)
(*$= & ~printer:(function Ok x -> String.concat ";" @@ List.map to_string x | Error e -> "error " ^ e)
(parse_string_list "(a b)(c)") (Ok [`List [`Atom "a"; `Atom "b"]; `List [`Atom "c"]])
(parse_string_list " ") (Ok [])
(parse_string_list "(a\n ;coucou\n b)") (Ok [`List [`Atom "a"; `Atom "b"]])
(parse_string_list "#; (a b) (c d) e ") (Ok [`List [`Atom "c"; `Atom "d"]; `Atom "e"])
(parse_string_list "#; (a b) 1") (Ok [`Atom "1"])
*)
(*$inject
let sexp_bijective s = to_string s |> parse_string = Ok s
*)
(*$= & ~printer:CCFormat.(to_string (Dump.result pp))
(Ok (`List [`Atom ""])) (parse_string "(\"\")")
*)
(*$T
sexp_bijective (`List [`Atom ""])
*)
(*$inject
let sexp_gen =
let mkatom a = `Atom a and mklist l = `List l in
let atom = Q.Gen.(map mkatom (string_size ~gen:printable (1 -- 30))) in
let gen = Q.Gen.(
sized (fix
(fun self n st -> match n with
| 0 -> atom st
| _ ->
frequency
[ 1, atom
; 2, map mklist (list_size (0 -- 10) (self (n/10)))
] st
)
)) in
let rec small = function
| `Atom s -> String.length s
| `List l -> List.fold_left (fun n x->n+small x) 0 l
and print = function
| `Atom s -> Printf.sprintf "`Atom \"%s\"" s
| `List l -> "`List " ^ Q.Print.list print l
and shrink = function
| `Atom s -> Q.Iter.map mkatom (Q.Shrink.string s)
| `List l -> Q.Iter.map mklist (Q.Shrink.list ~shrink l)
in
Q.make ~print ~small ~shrink gen
*)
(*$Q & ~count:100
sexp_gen sexp_bijective
*)
let atom s : t = `Atom s
(* regression for #338 *)
(*$R
Printexc.record_backtrace true;
let cases = [
"\"\\256\"";
"\"\\722\02622222\\\\\n\r<\\\\\\\\\"\\222222222\\\\\"\"\2032!2222\\\\\"\"";
"\"\n\r<\\t\023\n\203\\622222222\\\\\"\"\2032!2222\\\\\"\"";
"\"\n\r<@t\023\n\203\\2222D2\n\r22222\01622222222222222222222222\203\\292242\222 2\\\\\">K2";
"\"\n\r<\\t\023\n\203\\272222222\\\\\"\"\2032\0042222\\\\\"\"";
"\"\023\n\203\\5222\n\r<\\t\023\n\203\\52222222\\\\\"2\\\216\216\216\216\216\\\\\"\216\216\216\216\216\216\216\216\216222222222222222\147";
"\"\\722\02622222\\\\\n\r<\\\\\\\\\"\\222222222\\\\\"\"\2032!2222\\\\\"\"";
] in
cases
|> List.iter (fun s ->
try ignore (parse_string s);
with e ->
let st = Printexc.get_backtrace() in
print_endline @@ Printexc.to_string e ^ "\n" ^ st;
assert false)
*)

View file

@ -3,10 +3,6 @@
(** {1 Basic String Utils} *)
(*$inject
open CCShims_.Stdlib
*)
open CCShims_
type 'a iter = ('a -> unit) -> unit
@ -29,23 +25,6 @@ let rev s =
let n = length s in
init n (fun i -> s.[n-i-1])
(*$Q
Q.printable_string (fun s -> s = rev (rev s))
Q.printable_string (fun s -> length s = length (rev s))
*)
(*$Q
Q.printable_string (fun s -> \
rev s = (to_list s |> List.rev |> of_list))
*)
(*$=
"abc" (rev "cba")
"" (rev "")
" " (rev " ")
*)
let rec _to_list s acc i len =
if len=0 then List.rev acc
else _to_list s (s.[i]::acc) (i+1) (len-1)
@ -234,19 +213,6 @@ let find ?(start=0) ~sub =
let pattern = Find.compile sub in
fun s -> Find.find ~start ~pattern s
(*$= & ~printer:string_of_int
1 (find ~sub:"bc" "abcd")
~-1 (find ~sub:"bc" "abd")
1 (find ~sub:"a" "_a_a_a_")
6 (find ~start:5 ~sub:"a" "a1a234a")
*)
(*$Q & ~count:10_000
Q.(pair printable_string printable_string) (fun (s1,s2) -> \
let i = find ~sub:s2 s1 in \
i < 0 || String.sub s1 i (length s2) = s2)
*)
let find_all ?(start=0) ~sub =
let pattern = Find.compile sub in
fun s ->
@ -266,38 +232,12 @@ let find_all_l ?start ~sub s =
in
aux [] (find_all ?start ~sub s)
(*$= & ~printer:Q.Print.(list int)
[1; 6] (find_all_l ~sub:"bc" "abc aabc aab")
[] (find_all_l ~sub:"bc" "abd")
[76] (find_all_l ~sub:"aaaaaa" \
"aabbaabbaaaaabbbbabababababbbbabbbabbaaababbbaaabaabbaabbaaaabbababaaaabbaabaaaaaabbbaaaabababaabaaabbaabaaaabbababbaabbaaabaabbabababbbaabababaaabaaababbbaaaabbbaabaaababbabaababbaabbaaaaabababbabaababbbaaabbabbabababaaaabaaababaaaaabbabbaabbabbbbbbbbbbbbbbaabbabbbbbabbaaabbabbbbabaaaaabbababbbaaaa")
*)
let mem ?start ~sub s = find ?start ~sub s >= 0
(*$T
mem ~sub:"bc" "abcd"
not (mem ~sub:"a b" "abcd")
*)
let rfind ~sub =
let pattern = Find.rcompile sub in
fun s -> Find.rfind ~start:(String.length s-1) ~pattern s
(*$= & ~printer:string_of_int
1 (rfind ~sub:"bc" "abcd")
~-1 (rfind ~sub:"bc" "abd")
5 (rfind ~sub:"a" "_a_a_a_")
4 (rfind ~sub:"bc" "abcdbcd")
6 (rfind ~sub:"a" "a1a234a")
*)
(*$Q & ~count:10_000
Q.(pair printable_string printable_string) (fun (s1,s2) -> \
let i = rfind ~sub:s2 s1 in \
i < 0 || String.sub s1 i (length s2) = s2)
*)
(* Replace substring [s.[pos] … s.[pos+len-1]] by [by] in [s] *)
let replace_at_ ~pos ~len ~by s =
let b = Buffer.create (length s + length by - len) in
@ -335,16 +275,6 @@ let replace ?(which=`All) ~sub ~by s =
done;
Buffer.contents b
(*$= & ~printer:CCFun.id
(replace ~which:`All ~sub:"a" ~by:"b" "abcdabcd") "bbcdbbcd"
(replace ~which:`Left ~sub:"a" ~by:"b" "abcdabcd") "bbcdabcd"
(replace ~which:`Right ~sub:"a" ~by:"b" "abcdabcd") "abcdbbcd"
(replace ~which:`All ~sub:"ab" ~by:"hello" " abab cdabb a") \
" hellohello cdhellob a"
(replace ~which:`Left ~sub:"ab" ~by:"nope" " a b c d ") " a b c d "
(replace ~sub:"a" ~by:"b" "1aa234a") "1bb234b"
*)
module Split = struct
type drop_if_empty = {
first: bool;
@ -403,12 +333,6 @@ module Split = struct
let list_cpy ?(drop=default_drop) ~by s = _mklist ~drop ~by s String.sub
(*$T
Split.list_cpy ~by:"," "aa,bb,cc" = ["aa"; "bb"; "cc"]
Split.list_cpy ~by:"--" "a--b----c--" = ["a"; "b"; ""; "c"; ""]
Split.list_cpy ~by:" " "hello world aie" = ["hello"; ""; "world"; "aie"]
*)
let _mkseq ~drop ~by s k =
let by = Find.compile by in
let rec make state () = match _split ~by s state with
@ -444,14 +368,6 @@ module Split = struct
let left ~by s = try Some (left_exn ~by s) with Not_found -> None
(*$T
Split.left ~by:" " "ab cde f g " = Some ("ab", "cde f g ")
Split.left ~by:"__" "a__c__e_f" = Some ("a", "c__e_f")
Split.left ~by:"_" "abcde" = None
Split.left ~by:"bb" "abbc" = Some ("a", "c")
Split.left ~by:"a_" "abcde" = None
*)
let right_exn ~by s =
let i = rfind ~sub:by s in
if i = ~-1 then raise Not_found
@ -460,13 +376,6 @@ module Split = struct
String.sub s 0 i, String.sub s right (String.length s - right)
let right ~by s = try Some (right_exn ~by s) with Not_found -> None
(*$T
Split.right ~by:" " "ab cde f g" = Some ("ab cde f", "g")
Split.right ~by:"__" "a__c__e_f" = Some ("a__c", "e_f")
Split.right ~by:"_" "abcde" = None
Split.right ~by:"a_" "abcde" = None
*)
end
[@@@ifge 4.04]
@ -477,17 +386,6 @@ let split_on_char c s: _ list =
[@@@endif]
(*$= & ~printer:Q.Print.(list string)
["a"; "few"; "words"; "from"; "our"; "sponsors"] \
(split_on_char ' ' "a few words from our sponsors")
*)
(*$Q
Q.(printable_string) (fun s -> \
let s = split_on_char ' ' s |> String.concat " " in \
s = (split_on_char ' ' s |> String.concat " "))
*)
let split ~by s = Split.list_cpy ~by s
let compare_versions a b =
@ -509,20 +407,6 @@ let compare_versions a b =
in
cmp_rec (Split.gen_cpy ~by:"." a) (Split.gen_cpy ~by:"." b)
(*$T
compare_versions "0.1.3" "0.1" > 0
compare_versions "10.1" "2.0" > 0
compare_versions "0.1.alpha" "0.1" > 0
compare_versions "0.3.dev" "0.4" < 0
compare_versions "0.foo" "0.0" < 0
compare_versions "1.2.3.4" "01.2.4.3" < 0
*)
(*$Q
Q.(pair printable_string printable_string) (fun (a,b) -> \
CCOrd.equiv (compare_versions a b) (CCOrd.opp compare_versions b a))
*)
type nat_chunk =
| NC_char of char
| NC_int of int
@ -561,25 +445,6 @@ let compare_natural a b =
in
cmp_rec (chunks a) (chunks b)
(*$T
compare_natural "foo1" "foo2" < 0
compare_natural "foo11" "foo2" > 0
compare_natural "foo11" "foo11" = 0
compare_natural "foo011" "foo11" = 0
compare_natural "foo1a" "foo1b" < 0
compare_natural "foo1a1" "foo1a2" < 0
compare_natural "foo1a17" "foo1a2" > 0
*)
(*Q
(Q.pair printable_string printable_string) (fun (a,b) -> \
CCOrd.opp (compare_natural a b) = compare_natural b a)
(Q.printable_string) (fun a -> compare_natural a a = 0)
(Q.triple printable_string printable_string printable_string) (fun (a,b,c) -> \
if compare_natural a b < 0 && compare_natural b c < 0 \
then compare_natural a c < 0 else Q.assume_fail())
*)
let edit_distance ?(cutoff=max_int) s1 s2 =
let n1 = length s1 in
let n2 = length s2 in
@ -622,52 +487,6 @@ let edit_distance ?(cutoff=max_int) s1 s2 =
v1.(length s2)
with Exit -> cutoff
(*$Q
Q.(string_of_size Gen.(0 -- 30)) (fun s -> \
edit_distance s s = 0)
Q.(let p = string_of_size Gen.(0 -- 20) in pair p p) (fun (s1,s2) -> \
edit_distance s1 s2 = edit_distance s2 s1)
Q.(let p = string_of_size Gen.(0 -- 20) in pair p p) (fun (s1,s2) -> \
let e = edit_distance s1 s2 in \
let e' = edit_distance ~cutoff:3 s1 s2 in \
(if e' < 3 then e=e' else e >= 3) && \
(if e <= 3 then e=e' else true))
*)
(*$= & ~printer:string_of_int
2 (edit_distance "hello" "helo!")
5 (edit_distance "abcde" "tuvwx")
2 (edit_distance ~cutoff:2 "abcde" "tuvwx")
1 (edit_distance ("a" ^ String.make 100 '_') ("b"^String.make 100 '_'))
1 (edit_distance ~cutoff:4 ("a" ^ String.make 1000 '_') ("b"^String.make 1000 '_'))
2 (edit_distance ~cutoff:3 ("a" ^ String.make 1000 '_' ^ "c")\
("b" ^ String.make 1000 '_' ^ "d"))
*)
(* test that building a from s, and mutating one char of s, yields
a string s' that is accepted by a.
--> generate triples (s, i, c) where c is a char, s a non empty string
and i a valid index in s.
*)
(*$QR
(
let gen = Q.Gen.(
3 -- 10 >>= fun len ->
0 -- (len-1) >>= fun i ->
string_size (return len) >>= fun s ->
char >|= fun c -> (s,i,c)
) in
let small (s,_,_) = String.length s in
Q.make ~small gen
)
(fun (s,i,c) ->
let s' = Bytes.of_string s in
Bytes.set s' i c;
edit_distance s (Bytes.to_string s') <= 1)
*)
let repeat s n =
assert (n>=0);
let len = String.length s in
@ -686,16 +505,6 @@ let prefix ~pre s =
check 0
)
(*$T
prefix ~pre:"aab" "aabcd"
not (prefix ~pre:"ab" "aabcd")
not (prefix ~pre:"abcd" "abc")
prefix ~pre:"abc" "abcde"
prefix ~pre:"" ""
prefix ~pre:"" "abc"
prefix ~pre:"abc" "abc"
*)
let suffix ~suf s =
let len = String.length suf in
if len > String.length s then false
@ -709,14 +518,6 @@ let suffix ~suf s =
check 0
)
(*$T
suffix ~suf:"cd" "abcd"
suffix ~suf:"" ""
suffix ~suf:"" "abc"
not (suffix ~suf:"cd" "abcde")
not (suffix ~suf:"abcd" "cd")
*)
let take n s =
if n < String.length s
then String.sub s 0 n
@ -729,34 +530,16 @@ let drop n s =
let take_drop n s = take n s, drop n s
(*$=
("ab", "cd") (take_drop 2 "abcd")
("abc", "") (take_drop 3 "abc")
("abc", "") (take_drop 5 "abc")
*)
let chop_suffix ~suf s =
if suffix ~suf s
then Some (String.sub s 0 (String.length s-String.length suf))
else None
(*$= & ~printer:Q.Print.(option string)
(Some "ab") (chop_suffix ~suf:"cd" "abcd")
None (chop_suffix ~suf:"cd" "abcde")
None (chop_suffix ~suf:"abcd" "cd")
*)
let chop_prefix ~pre s =
if prefix ~pre s
then Some (String.sub s (String.length pre) (String.length s-String.length pre))
else None
(*$= & ~printer:Q.Print.(option string)
(Some "cd") (chop_prefix ~pre:"aab" "aabcd")
None (chop_prefix ~pre:"ab" "aabcd")
None (chop_prefix ~pre:"abcd" "abc")
*)
let blit = String.blit
let fold f acc s =
@ -780,15 +563,6 @@ let pad ?(side=`Left) ?(c=' ') n s =
| `Left -> init n (fun i -> if i < pad_len then c else s.[i-pad_len])
| `Right -> init n (fun i -> if i < len_s then s.[i] else c)
(*$= & ~printer:Q.Print.string
" 42" (pad 4 "42")
"0042" (pad ~c:'0' 4 "42")
"4200" (pad ~side:`Right ~c:'0' 4 "42")
"hello" (pad 4 "hello")
"aaa" (pad ~c:'a' 3 "")
"aaa" (pad ~side:`Right ~c:'a' 3 "")
*)
let _to_gen s i0 len =
let i = ref i0 in
fun () ->
@ -835,11 +609,6 @@ let of_list l =
List.iter (Buffer.add_char buf) l;
Buffer.contents buf
(*$T
of_list ['a'; 'b'; 'c'] = "abc"
of_list [] = ""
*)
let of_array a =
init (Array.length a) (fun i -> a.(i))
@ -854,21 +623,6 @@ let lines_seq s = Split.seq_cpy ~drop:{Split.first=false; last=true} ~by:"\n" s
let lines s = Split.list_cpy ~drop:{Split.first=false; last=true} ~by:"\n" s
(*$= & ~printer:Q.Print.(list @@ Printf.sprintf "%S")
["ab"; "c"] (lines "ab\nc")
["ab"; "c"] (lines "ab\nc\n")
[] (lines "")
[""] (lines "\n")
[""; "a"] (lines "\na")
*)
(*$Q
Q.(printable_string) (fun s -> \
lines s = (lines_gen s |> Gen.to_list))
Q.(printable_string) (fun s -> \
lines s = (lines_iter s |> Iter.to_list))
*)
let concat_gen_buf ~sep g : Buffer.t =
let b = Buffer.create 256 in
let rec aux ~first () = match g () with
@ -909,15 +663,6 @@ let concat_seq ~sep seq =
let buf = concat_seq_buf ~sep seq in
Buffer.contents buf
(*$Q
Q.(small_list printable_string) (fun l -> \
concat_iter ~sep:"\n" (Iter.of_list l) = concat "\n" l)
Q.(small_list printable_string) (fun l -> \
concat_gen ~sep:"\n" (Gen.of_list l) = concat "\n" l)
Q.(small_list printable_string) (fun l -> \
concat_seq ~sep:"\n" (CCSeq.of_list l) = concat "\n" l)
*)
let unlines l =
let len = List.fold_left (fun n s -> n + 1 + String.length s) 0 l in
let buf = Bytes.create len in
@ -948,32 +693,10 @@ let unlines_seq seq =
Buffer.add_char buf '\n';
Buffer.contents buf
(*$= & ~printer:CCFun.id
"" (unlines [])
"ab\nc\n" (unlines ["ab"; "c"])
*)
(*$Q
Q.printable_string (fun s -> trim (unlines (lines s)) = trim s)
Q.printable_string (fun s -> trim (unlines_gen (lines_gen s)) = trim s)
*)
(*$Q
Q.(small_list small_string) (fun l -> \
let l = unlines l |> lines in \
l = (unlines l |> lines))
*)
let set s i c =
if i<0 || i>= String.length s then invalid_arg "CCString.set";
init (String.length s) (fun j -> if i=j then c else s.[j])
(*$T
set "abcd" 1 '_' = "a_cd"
set "abcd" 0 '-' = "-bcd"
(try ignore (set "abc" 5 '_'); false with Invalid_argument _ -> true)
*)
let iter = String.iter
let filter_map f s =
@ -985,11 +708,6 @@ let filter_map f s =
s;
Buffer.contents buf
(*$= & ~printer:Q.Print.string
"bcef" (filter_map \
(function 'c' -> None | c -> Some (Char.chr (Char.code c + 1))) "abcde")
*)
let filter f s =
let buf = Buffer.create (String.length s) in
iter
@ -997,14 +715,6 @@ let filter f s =
s;
Buffer.contents buf
(*$= & ~printer:Q.Print.string
"abde" (filter (function 'c' -> false | _ -> true) "abcdec")
*)
(*$Q
Q.printable_string (fun s -> filter (fun _ -> true) s = s)
*)
let uniq eq s =
if String.length s = 0 then s
else begin
@ -1019,10 +729,6 @@ let uniq eq s =
Buffer.contents buf
end
(*$= & ~printer:Q.Print.string
"abcde" (uniq CCShims_.Stdlib.(=) "abbccdeeeee")
*)
let flat_map ?sep f s =
let buf = Buffer.create (String.length s) in
iteri
@ -1064,24 +770,6 @@ let is_space_ = function
let ltrim s = drop_while is_space_ s
let rtrim s = rdrop_while is_space_ s
(*$= & ~printer:id
"abc " (ltrim " abc ")
" abc" (rtrim " abc ")
*)
(*$Q
Q.(printable_string) (fun s -> \
String.trim s = (s |> ltrim |> rtrim))
Q.(printable_string) (fun s -> ltrim s = ltrim (ltrim s))
Q.(printable_string) (fun s -> rtrim s = rtrim (rtrim s))
Q.(printable_string) (fun s -> \
let s' = ltrim s in \
if s'="" then Q.assume_fail() else s'.[0] <> ' ')
Q.(printable_string) (fun s -> \
let s' = rtrim s in \
if s'="" then Q.assume_fail() else s'.[String.length s'-1] <> ' ')
*)
let map2 f s1 s2 =
if length s1 <> length s2 then invalid_arg "CCString.map2";
init (String.length s1) (fun i -> f s1.[i] s2.[i])
@ -1122,18 +810,6 @@ let equal_caseless s1 s2: bool =
(fun c1 c2 -> CCChar.equal (CCChar.lowercase_ascii c1) (CCChar.lowercase_ascii c2))
s1 s2
(*$T
equal_caseless "foo" "FoO"
equal_caseless "helLo" "HEllO"
*)
(*$Q
Q.(pair printable_string printable_string) (fun (s1,s2) -> \
equal_caseless s1 s2 = (lowercase_ascii s1=lowercase_ascii s2))
Q.(printable_string) (fun s -> equal_caseless s s)
Q.(printable_string) (fun s -> equal_caseless (uppercase_ascii s) s)
*)
let to_hex (s:string) : string =
let i_to_hex (i:int) =
if i < 10 then Char.chr (i + Char.code '0')
@ -1167,20 +843,6 @@ let of_hex_exn (s:string) : string =
let of_hex s = try Some (of_hex_exn s) with Invalid_argument _ -> None
(*$= & ~printer:(Printf.sprintf "%S")
"0068656c6c6f20776f726c64" (to_hex "\000hello world")
"" (to_hex "")
"\000hello world" (of_hex_exn "0068656c6c6f20776f726c64")
"hello world" (of_hex_exn "68656C6C6F20776F726C64")
*)
(*$Q
Q.(string) (fun s -> \
of_hex_exn (to_hex s) = s)
Q.(string) (fun s -> \
CCString.for_all (function 'A'..'F'|'a'..'f'|'0'..'9' -> true | _ -> false) @@ to_hex s)
*)
let pp_buf buf s =
Buffer.add_char buf '"';
Buffer.add_string buf s;
@ -1199,8 +861,3 @@ module Infix = struct
end
include Infix
(*$T
"ab" < "abc"
"123" < "14"
*)

View file

@ -141,22 +141,6 @@ let to_seq ?(idx=0) s : uchar Seq.t =
let st = Dec.make ~idx s in
loop st
(*$= & ~cmp:(=) ~printer:Q.Print.(list (fun c -> string_of_int@@ Uchar.to_int c))
(to_list (of_string_exn "aébõ😀")) (to_seq (of_string_exn "aébõ😀") |> CCList.of_seq)
*)
(* make sure it's persisted correctly *)
(*$R
let s = (of_string_exn "aébõ😀") in
let seq = to_seq s in
let l = to_list s in
let testeq seq = assert_equal ~cmp:(=) l (CCList.of_seq seq) in
testeq seq;
testeq seq;
testeq seq;
*)
let iter ?idx f s = to_iter ?idx s f
let fold ?idx f acc s =
@ -318,168 +302,3 @@ let of_string_exn s =
else invalid_arg "CCUtf8_string.of_string_exn"
let of_string s = if is_valid s then Some s else None
(*$inject
let printer s = String.escaped (to_string s)
let pp_uchar (c:Uchar.t) = Printf.sprintf "0x%x" (Uchar.to_int c)
let arb_uchar =
let rec gen = lazy (
let open Q.Gen in
Q.Gen.int_range Uchar.(to_int min) Uchar.(to_int max) >>= fun n ->
try return (Uchar.of_int n)
with _ -> Lazy.force gen
) in
Q.make
~print:(fun c -> Printf.sprintf "<uchar '%d'>" (Uchar.to_int c))
(Lazy.force gen)
let uutf_is_valid s =
try
Uutf.String.fold_utf_8
(fun () _ -> function
| `Malformed _ -> raise Exit
| `Uchar _ -> ())
() s;
true
with Exit ->
false
let uutf_to_iter s f =
Uutf.String.fold_utf_8
(fun () _ -> function
| `Malformed _ -> f (Uchar.of_int 0xfffd)
| `Uchar c -> f c)
() s
let uutf_of_l l =
let buf = Buffer.create 32 in
List.iter (Uutf.Buffer.add_utf_8 buf) l;
Buffer.contents buf
*)
(*$R
let s = of_string_exn "このため、" in
let s' = to_iter s |> of_iter in
assert_equal ~cmp:equal ~printer s s'
*)
(*$QR
Q.small_string (fun s ->
Q.assume (CCString.for_all (fun c -> Char.code c < 128) s);
is_valid s)
*)
(*$QR & ~long_factor:10
Q.small_string (fun s ->
Q.assume (CCString.for_all (fun c -> Char.code c < 128) s);
s = (of_string_exn s |> to_iter|> of_iter|> to_string)
)
*)
(*$QR & ~long_factor:10
Q.string (fun s ->
Q.assume (CCString.for_all (fun c -> Char.code c < 128) s);
String.length s = List.length (of_string_exn s |> to_list)
)
*)
(*$QR & ~long_factor:10 ~count:20_000
Q.(small_list arb_uchar) (fun l ->
let s = of_list l in
l = to_list s)
*)
(*$QR & ~long_factor:10
Q.(small_list arb_uchar) (fun l ->
let s = of_list l in
l = (to_list @@ of_gen @@ to_gen s)
)
*)
(*$QR & ~long_factor:10
Q.(small_list arb_uchar) (fun l ->
let s = of_list l in
l = (to_list @@ of_iter @@ to_iter s)
)
*)
(*$T
not (is_valid "\192\181")
not (is_valid "\193\143")
not (is_valid "\224\151\167")
not (is_valid "\224\137\165")
is_valid "\240\151\189\163"
*)
(*$QR & ~long_factor:40
Q.string (fun s ->
Q.assume (is_valid s);
let s = of_string_exn s in
let s2 = s |> to_iter|> of_iter in
if s=s2 then true
else Q.Test.fail_reportf "s=%S, s2=%S" (to_string s)(to_string s2)
)
*)
(*$QR & ~long_factor:40
Q.string (fun s ->
Q.assume (is_valid s);
let s = of_string_exn s in
let s2 = s |> to_gen |> of_gen in
if s=s2 then true
else Q.Test.fail_reportf "s=%S, s2=%S" (to_string s)(to_string s2)
)
*)
(* compare with uutf *)
(*$QR & ~long_factor:40 ~count:50_000
Q.small_string (fun s ->
let v1 = is_valid s in
let v2 = uutf_is_valid s in
if v1=v2 then true
else Q.Test.fail_reportf "s:%S, valid: %B, uutf_valid: %B" s v1 v2
)
*)
(*$QR & ~long_factor:40 ~count:50_000
Q.(small_list arb_uchar) (fun l ->
let pp s = Q.Print.(list pp_uchar) s in
let uutf = uutf_of_l l in
let s = (of_list l:>string) in
if uutf = s then true
else Q.Test.fail_reportf "l: '%s', uutf: '%s', containers: '%s'"
(pp l) uutf s
)
*)
(*$QR & ~long_factor:40 ~count:50_000
Q.small_string (fun s ->
Q.assume (is_valid s && uutf_is_valid s);
let pp s = Q.Print.(list pp_uchar) s in
let l_uutf = uutf_to_iter s |> Iter.to_list in
let l_co = of_string_exn s |> to_iter |> Iter.to_list in
if l_uutf = l_co then true
else Q.Test.fail_reportf "uutf: '%s', containers: '%s', is_valid %B, uutf_is_valid %B"
(pp l_uutf) (pp l_co) (is_valid s) (uutf_is_valid s)
)
*)
(*$R
for i = 0 to 127 do
let c = Uchar.of_int i in
assert_equal 1 (n_bytes (of_list [c]))
done
*)
(*$QR
Q.(small_list arb_uchar) (fun l ->
of_list l = concat empty (List.map of_uchar l))
*)
(*$QR
Q.(pair small_nat arb_uchar) (fun (i,c) ->
make i c = concat empty (CCList.init i (fun _ -> of_uchar c)))
*)

View file

@ -54,20 +54,11 @@ let create_with ?(capacity=128) x =
vec
}
(*$T
(create_with ~capacity:200 1 |> capacity) >= 200
*)
let return x = {
size=1;
vec= [| x |];
}
(*$T
return 42 |> to_list = [42]
return 42 |> length = 1
*)
let make n x = {
size=n;
vec=Array.make n x;
@ -96,33 +87,6 @@ let resize_ v newcapacity x =
v.vec <- new_vec;
()
(*$T
let v = create_with ~capacity:10 1 in \
ensure v 200; capacity v >= 200
*)
(*$T
let v = create() in push v 0.; push v 1.; push v 2.; 3=length v
let v = create() in push v 1.; push v 2.; push v 3.; 6. = (get v 0 +. get v 1 +. get v 2)
let v = create() in push v 0; push v 1; push v 2; 3=length v
let v = create() in push v 1; push v 2; push v 3; 6 = (get v 0 + get v 1 + get v 2)
let v = create() in push v "a"; push v "b"; push v "c"; 3=length v
let v = create() in push v "a"; push v "b"; push v "c"; "abc" = String.concat "" (to_list v)
*)
(*$R
let v = create() in
push v 0.; push v 1.;
clear v;
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
truncate v 2;
assert_equal 1. (fold (+.) 0. v);
clear v;
assert_equal 0 (size v);
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
assert_equal (1. +. 7. +. 10. +. 12.) (fold (+.) 0. v);
*)
(* grow the array, using [x] as a filler if required *)
let grow_with_ v ~filler:x =
if array_is_empty_ v then (
@ -168,14 +132,6 @@ let ensure v size =
let[@inline] clear v =
v.size <- 0
(*$R
let v = of_iter Iter.(1 -- 10) in
OUnit2.assert_equal 10 (size v);
clear v;
OUnit2.assert_equal 0 (size v);
OUnit2.assert_bool "empty_after_clear" (Iter.is_empty (to_iter v));
*)
let clear_and_reset v =
v.size <- 0;
v.vec <- [||]
@ -202,11 +158,6 @@ let push v x =
if v.size = Array.length v.vec then grow_with_ v ~filler:x;
push_unsafe_ v x
(*$T
let v = create () in push v 1; to_list v = [1]
let v = of_list [1;2;3] in push v 4; to_list v = [1;2;3;4]
*)
let resize_with v f size =
if size<0 then invalid_arg "Vec.resize_with";
if Array.length v.vec = 0 then (
@ -221,17 +172,6 @@ let resize_with v f size =
v.size <- size
)
(*$T
let v = make 1 0 in resize_with v (fun i -> i) 5; to_list v = [0;1;2;3;4]
let v = make 1 0 in resize_with v (fun i -> i) 5; CCList.length (to_list v) = 5
let v = create_with ~capacity:2 0 in resize_with v (fun i -> i) 5; to_list v = [0;1;2;3;4]
let v = make 5 0 in resize_with v (fun i -> i) 5; to_list v = [0;0;0;0;0]
let v = make 5 0 in resize_with v (fun i -> i) 6; to_list v = [0;0;0;0;0;5]
let v = make 5 0 in try resize_with v (fun i -> i) (-1); false \
with Invalid_argument _ -> true
let v = make 5 0 in resize_with v (fun i -> i) 5; List.length (to_list v) = 5
*)
let resize_with_init v ~init size =
if size<0 then invalid_arg "Vec.resize_with_init";
if Array.length v.vec = 0 then (
@ -246,23 +186,6 @@ let resize_with_init v ~init size =
v.size <- size;
)
(*$T
let v = make 1 0 in resize_with_init v ~init:1 5; to_list v = [0;1;1;1;1]
let v = make 1 0 in resize_with_init v ~init:1 5; List.length (to_list v) = 5
let v = create_with ~capacity:2 0 in resize_with_init v ~init:1 5; to_list v = [1;1;1;1;1]
let v = make 5 0 in resize_with_init v ~init:1 5; to_list v = [0;0;0;0;0]
let v = make 3 0 in resize_with_init v ~init:1 5; to_list v = [0;0;0;1;1]
let v = make 5 0 in try resize_with_init v ~init:1 (-1); false \
with Invalid_argument _ -> true
let v = make 5 0 in resize_with_init v ~init:1 5; List.length (to_list v) = 5
*)
(* test for asymptotic behavior *)
(*$T
let v =make 1 0 in for i=0 to 100_000 do resize_with_init v ~init:10 i; done; true
*)
(** Add all elements of b to a *)
let append a b =
if array_is_empty_ a then (
@ -278,28 +201,6 @@ let append a b =
a.size <- a.size + b.size
)
(*$T
let v1 = init 5 (fun i->i) and v2 = init 5 (fun i->i+5) in \
append v1 v2; to_list v1 = CCList.(0--9)
let empty = create () and v2 = init 5 (fun i->i) in \
append empty v2; to_list empty = CCList.(0--4)
let v1 = init 5 (fun i->i) and empty = create () in \
append v1 empty; to_list v1 = CCList.(0--4)
let v = init 3 (fun i->i) in \
append v v; to_list v = [0; 1; 2; 0; 1; 2]
let empty = create () in \
append empty empty; to_list empty = []
*)
(*$R
let a = of_iter Iter.(1 -- 5) in
let b = of_iter Iter.(6 -- 10) in
append a b;
OUnit2.assert_equal 10 (size a);
OUnit2.assert_equal (Iter.to_array Iter.(1 -- 10)) (to_array a);
OUnit2.assert_equal (Iter.to_array Iter.(6 -- 10)) (to_array b);
*)
let[@inline] get v i =
if i < 0 || i >= v.size then invalid_arg "CCVector.get";
Array.unsafe_get v.vec i
@ -326,25 +227,6 @@ let remove_unordered v i =
v.size <- v.size - 1;
fill_with_junk_ v.vec v.size 1
(*$Q remove_and_shift
Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l -> \
let v1 = of_list l and v2 = of_list l in \
remove_and_shift v1 9; \
remove_unordered v2 9; \
to_list v1 = (to_list v2))
Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l -> \
let l = List.sort CCInt.compare l in \
let v = of_list l in\
remove_and_shift v 3; \
to_list v = (List.sort CCInt.compare (to_list v)))
Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l -> \
let l = List.sort CCInt.compare l in \
let v1 = of_list l and v2 = of_list l in \
remove_and_shift v1 3; \
remove_unordered v2 3; \
to_list v1 = (List.sort CCInt.compare (to_list v2)))
*)
let insert v i x =
(* Note that we can insert at i=v.size *)
if i < 0 || i > v.size then invalid_arg "CCVector.insert";
@ -355,14 +237,6 @@ let insert v i x =
v.vec.(i) <- x;
v.size <- v.size + 1
(*$T
let v = (1 -- 5) in insert v 3 9; to_list v = [1;2;3;9;4;5]
let v = create () in insert v 0 2; to_list v = [2]
let v = (1 -- 3) in remove_and_shift v 1; insert v 1 5; to_list v = [1;5;3]
let v = (1 -- 3) in remove_and_shift v 0; insert v 2 5; to_list v = [2;3;5]
let v = (1 -- 3) in insert v 3 5; to_list v = [1;2;3;5]
*)
let[@inline] append_iter a i = i (fun x -> push a x)
let append_seq a seq = Seq.iter (fun x -> push a x) seq
@ -378,17 +252,6 @@ let append_array a b =
a.size <- a.size + len_b
)
(*$T
let v1 = init 5 (fun i->i) and v2 = Array.init 5 (fun i->i+5) in \
append_array v1 v2; to_list v1 = CCList.(0--9)
let empty = create () in \
append_array empty CCArray.(0--5); to_list empty = CCList.(0--5)
let v1 = init 5 (fun i->i) in \
append_array v1 [| |]; to_list v1 = CCList.(0--4)
let empty = create () in \
append_array empty [| |]; to_list empty = []
*)
let append_list a b = match b with
| [] -> ()
| x :: _ ->
@ -399,45 +262,10 @@ let append_list a b = match b with
List.iter (push_unsafe_ a) b;
()
(*$Q
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_list v l2; \
to_list v = (l1 @ l2))
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_list v l2; \
length v = List.length l1 + List.length l2)
*)
let rec append_gen a b = match b() with
| None -> ()
| Some x -> push a x; append_gen a b
(*$Q
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_gen v (Gen.of_list l2); \
to_list v = (l1 @ l2))
Q.(pair (list int)(list int)) (fun (l1,l2) -> \
let v = of_list l1 in append_gen v (Gen.of_list l2); \
length v = List.length l1 + List.length l2)
*)
(*$inject
let gen x =
let small = length in
let print = CCOption.map (fun p x -> Q.Print.list p (CCVector.to_list x)) x.Q.print in
Q.make ?print ~small Q.Gen.(list x.Q.gen >|= of_list)
*)
(*$QR
(Q.pair (gen Q.int) (gen Q.int)) (fun (v1,v2) ->
let l1 = to_list v1 in
append v1 v2;
Iter.to_list (to_iter v1) =
Iter.(to_list (append (of_list l1) (to_iter v2)))
)
*)
let equal eq v1 v2 =
v1.size = v2.size
&&
@ -447,25 +275,6 @@ let equal eq v1 v2 =
in
check 0
(*$T
equal (=) (create ()) (create ())
equal (=) (return 42) (return 42)
not (equal (=) (create ()) (return 42))
not (equal (=) (return 42) (create ()))
*)
(*$Q
Q.(let g = list_of_size Gen.(0--10) small_int in pair g g) (fun (l1,l2) -> \
equal (=) (of_list l1) (of_list l2) = (l1=l2))
*)
(*$QR
Q.(pair (small_list small_int)(small_list small_int)) (fun (l1,l2) ->
let v1 = of_list l1 in
let v2 = of_list l2 in
equal (=) v1 v2 = (l1=l2))
*)
let compare cmp v1 v2 =
let n = min v1.size v2.size in
let rec check i =
@ -477,13 +286,6 @@ let compare cmp v1 v2 =
)
in check 0
(*$QR
Q.(pair (small_list small_int)(small_list small_int)) (fun (l1,l2) ->
let v1 = of_list l1 in
let v2 = of_list l2 in
compare Stdlib.compare v1 v2 = CCList.compare Stdlib.compare l1 l2)
*)
exception Empty
let pop_exn v =
@ -506,40 +308,11 @@ let[@inline] top_exn v =
if v.size = 0 then raise Empty;
Array.unsafe_get v.vec (v.size-1)
(*$T
1 -- 10 |> top = Some 10
create () |> top = None
1 -- 10 |> top_exn = 10
*)
let[@inline] copy v = {
size = v.size;
vec = Array.sub v.vec 0 v.size;
}
(*$T
(let v = of_list [1;2;3] in let v' = copy v in \
to_list v' = [1;2;3])
create () |> copy |> is_empty
*)
(*$R
let v = of_iter Iter.(1 -- 100) in
OUnit2.assert_equal 100 (size v);
let v' = copy v in
OUnit2.assert_equal 100 (size v');
clear v';
OUnit2.assert_bool "empty" (is_empty v');
OUnit2.assert_bool "not_empty" (not (is_empty v));
*)
(*$QR
Q.(small_list small_int) (fun l ->
let v = of_list l in
let v' = copy v in
equal (=) v v')
*)
let truncate v n =
let old_size = v.size in
if n < old_size then (
@ -548,23 +321,6 @@ let truncate v n =
fill_with_junk_ v.vec n (old_size-n);
)
(*$R
let v = of_iter Iter.(1 -- 10) in
truncate v 5;
OUnit2.assert_equal [1;2;3;4;5] (to_list v);
*)
(*$QR
(gen Q.small_int) (fun v ->
let n = size v / 2 in
let l = to_list v in
let h = Iter.(to_list (take n (of_list l))) in
let v' = copy v in
truncate v' n;
h = to_list v'
)
*)
let shrink_to_fit v : unit =
if v.size = 0 then (
v.vec <- [| |]
@ -572,14 +328,6 @@ let shrink_to_fit v : unit =
v.vec <- Array.sub v.vec 0 v.size
)
(*$QR
(gen Q.small_int) (fun v ->
let v' = copy v in
shrink_to_fit v;
to_list v = to_list v'
)
*)
let sort' cmp v =
(* possibly copy array (to avoid junk at its end), then sort the array *)
let a =
@ -597,15 +345,6 @@ let sort cmp v =
Array.sort cmp v'.vec;
v'
(*$QR
(gen Q.small_int) (fun v ->
let v' = copy v in
sort' Stdlib.compare v';
let l = to_list v' in
List.sort Stdlib.compare l = l
)
*)
let uniq_sort cmp v =
sort' cmp v;
let n = v.size in
@ -628,18 +367,6 @@ let uniq_sort cmp v =
then traverse v.vec.(0) 1 1
(* start at 1, to get the first element in hand *)
(*$T
let v = of_list [1;4;5;3;2;4;1] in \
uniq_sort Stdlib.compare v; to_list v = [1;2;3;4;5]
*)
(*$QR & ~long_factor:10
Q.(small_list small_int) (fun l ->
let v = of_list l in
uniq_sort Stdlib.compare v;
to_list v = (CCList.sort_uniq ~cmp:Stdlib.compare l))
*)
let iter k v =
let n = v.size in
for i = 0 to n-1 do
@ -652,11 +379,6 @@ let iteri k v =
k i (Array.unsafe_get v.vec i)
done
(*$T
let v = (0--6) in \
iteri (fun i x -> if i = 3 then remove_unordered v i) v; length v = 6
*)
let map f v =
if array_is_empty_ v
then create ()
@ -665,17 +387,6 @@ let map f v =
{ size=v.size; vec; }
)
(*$T
let v = create() in push v 1; push v 2; push v 3; \
to_list (map string_of_int v) = ["1"; "2"; "3"]
*)
(*$QR
Q.(pair (fun1 Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (map f v) = List.map f l)
*)
let mapi f v =
if array_is_empty_ v
then create ()
@ -684,30 +395,11 @@ let mapi f v =
{ size=v.size; vec; }
)
(*$T mapi
let v = create() in push v 1; push v 2; push v 3; \
to_list (mapi (fun i e -> Printf.sprintf "%i %i" i e) v) = ["0 1"; "1 2"; "2 3"]
*)
(*$QR mapi
Q.(pair (fun2 Observable.int Observable.int small_int) (small_list small_int))
(fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (mapi f v) = List.mapi f l)
*)
let map_in_place f v =
iteri
(fun i x -> Array.unsafe_set v.vec i (f x))
v
(*$QR
Q.(pair (fun1 Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
map_in_place f v;
to_list v = List.map f l)
*)
let filter_in_place p v =
let i = ref 0 in (* cur element *)
@ -726,18 +418,6 @@ let filter_in_place p v =
fill_with_junk_ v.vec !j (v.size - !j);
v.size <- !j
(*$T
let v = 1 -- 10 in filter_in_place (fun x->x<4) v; \
to_list v = [1;2;3]
*)
(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
filter_in_place f v;
to_list v = List.filter f l)
*)
let filter p v =
if array_is_empty_ v then (
create ()
@ -749,17 +429,6 @@ let filter p v =
v'
)
(*$T
filter (fun x-> x mod 2=0) (of_list [1;2;3;4;5]) |> to_list = [2;4]
filter (fun x-> x mod 2=0) (1 -- 1_000_000) |> length = 500_000
*)
(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (filter f v) = List.filter f l)
*)
let fold f acc v =
let rec fold acc i =
if i = v.size then acc
@ -768,17 +437,6 @@ let fold f acc v =
fold (f acc x) (i+1)
in fold acc 0
(*$T
fold (+) 0 (of_list [1;2;3;4;5]) = 15
fold (+) 0 (create ()) = 0
*)
(*$QR
Q.(pair (fun2 Observable.int Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
fold f 0 v = List.fold_left f 0 l)
*)
let exists p v =
let n = v.size in
let rec check i =
@ -786,12 +444,6 @@ let exists p v =
else p v.vec.(i) || check (i+1)
in check 0
(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
exists f v = List.exists f l)
*)
let for_all p v =
let n = v.size in
let rec check i =
@ -799,12 +451,6 @@ let for_all p v =
else p v.vec.(i) && check (i+1)
in check 0
(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
for_all f v = List.for_all f l)
*)
let member ~eq x v =
exists (eq x) v
@ -828,12 +474,6 @@ let find p v =
try Some (find_internal_ p v)
with Not_found -> None
(*$QR
Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
find f v = CCList.find_pred f l)
*)
let find_map f v =
let n = v.size in
let rec search i =
@ -844,13 +484,6 @@ let find_map f v =
in
search 0
(*$Q
Q.(list small_int) (fun l -> \
let v = of_list l in \
let f x = x>30 && x < 35 in \
find_map (fun x -> if f x then Some x else None) v = find f v)
*)
let filter_map f v =
let v' = create () in
iter
@ -860,12 +493,6 @@ let filter_map f v =
v;
v'
(*$QR
Q.(pair (fun1 Observable.int (option bool)) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (filter_map f v) = CCList.filter_map f l)
*)
let filter_map_in_place f v =
let i = ref 0 in (* cur element *)
let j = ref 0 in (* cur insertion point *)
@ -884,26 +511,6 @@ let filter_map_in_place f v =
fill_with_junk_ v.vec !j (v.size - !j);
v.size <- !j
(*$QR
Q.(pair (fun1 Observable.int (option small_int)) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
filter_map_in_place f v;
to_list v = CCList.filter_map f l)
*)
(* check it frees memory properly *)
(*$R
let s = "coucou" ^ "lol" in
let w = Weak.create 1 in
Weak.set w 0 (Some s);
let v = of_list ["a"; s] in
filter_in_place (fun s -> String.length s <= 1) v;
assert_equal 1 (length v);
assert_equal "a" (get v 0);
Gc.full_major();
assert_equal None (Weak.get w 0);
*)
let flat_map f v =
let v' = create () in
iter (fun x -> iter (push v') (f x)) v;
@ -944,13 +551,6 @@ let monoid_product f a1 a2 : _ t =
let j = i_prod / na1 in
f a1.vec.(i) a2.vec.(j))
(*$= & ~cmp:(=) ~printer:Q.Print.(list int)
[ 11; 12; 21; 22 ] (List.sort CCInt.compare @@ \
to_list @@ monoid_product (+) (of_list [10; 20]) (of_list [1; 2]))
[ 11; 12; 13; 14 ] (List.sort CCInt.compare @@ \
to_list @@ monoid_product (+) (of_list [10]) (of_list [1; 2; 3; 4]))
*)
let (>>=) x f = flat_map f x
let (>|=) x f = map f x
@ -968,46 +568,17 @@ let rev_in_place v =
done
)
(*$QR
Q.(small_list small_int) (fun l ->
let v = of_list l in
rev_in_place v;
to_list v = List.rev l)
*)
let rev v =
let v' = copy v in
rev_in_place v';
v'
(*$T
rev (of_list [1;2;3;4]) |> to_list = [4;3;2;1]
rev (of_list [1;2;3;4;5]) |> to_list = [5;4;3;2;1]
rev (create ()) |> to_list = []
*)
(*$QR
Q.(small_list small_int) (fun l ->
let v = of_list l in
to_list (rev v) = List.rev l)
*)
let rev_iter f v =
let n = v.size in
for i = n-1 downto 0 do
f (Array.unsafe_get v.vec i)
done
(*$T
let v = of_list [1;2;3] in (fun f->rev_iter f v) |> Iter.to_list = [3;2;1]
*)
(*$Q
Q.(list int) (fun l -> \
let v = of_list l in \
(fun f->rev_iter f v) |> Iter.to_list = List.rev l)
*)
let size v = v.size
let length v = v.size
@ -1024,10 +595,6 @@ let of_seq ?(init=create ()) seq =
append_seq init seq;
init
(*$T
of_iter Iter.(1 -- 10) |> to_list = CCList.(1 -- 10)
*)
let to_iter v k = iter k v
let to_iter_rev v k =
@ -1050,11 +617,6 @@ let to_seq_rev v =
in
aux (size v-1)
(*$Q
Q.(list int) (fun l -> \
let v= of_list l in v |> to_iter_rev |> Iter.to_rev_list = l)
*)
let slice_iter v start len =
assert (start >= 0 && len >= 0);
fun k ->
@ -1064,12 +626,6 @@ let slice_iter v start len =
k x
done
(*$T
slice_iter (of_list [0;1;2;3;4]) 1 3 |> CCList.of_iter = [1;2;3]
slice_iter (of_list [0;1;2;3;4]) 1 4 |> CCList.of_iter = [1;2;3;4]
slice_iter (of_list [0;1;2;3;4]) 0 5 |> CCList.of_iter = [0;1;2;3;4]
*)
let slice v = (v.vec, 0, v.size)
let (--) i j =
@ -1077,28 +633,12 @@ let (--) i j =
then init (i-j+1) (fun k -> i-k)
else init (j-i+1) (fun k -> i+k)
(*$T
(1 -- 4) |> to_list = [1;2;3;4]
(4 -- 1) |> to_list = [4;3;2;1]
(0 -- 0) |> to_list = [0]
*)
(*$Q
Q.(pair small_int small_int) (fun (a,b) -> \
(a -- b) |> to_list = CCList.(a -- b))
*)
let (--^) i j =
if i=j then create()
else if i>j
then init (i-j) (fun k -> i-k)
else init (j-i) (fun k -> i+k)
(*$Q
Q.(pair small_int small_int) (fun (a,b) -> \
(a --^ b) |> to_list = CCList.(a --^ b))
*)
let of_array a =
if Array.length a = 0
then create ()
@ -1116,10 +656,6 @@ let of_list l = match l with
List.iter (push_unsafe_ v) l;
v
(*$T
of_list CCList.(1--300_000) |> to_list = CCList.(1--300_000)
*)
let to_array v =
Array.sub v.vec 0 v.size
@ -1142,10 +678,6 @@ let to_gen v =
Some x
) else None
(*$T
let v = (1--10) in to_list v = Gen.to_list (to_gen v)
*)
let to_string ?(start="") ?(stop="") ?(sep=", ") item_to_string v =
start ^ (to_list v |> List.map item_to_string |> String.concat sep) ^ stop

View file

@ -18,6 +18,7 @@ module Test = struct
count: int option;
arb: 'a Q.arbitrary;
prop: 'a -> bool;
long_factor: int option;
} -> run
type t = {
@ -45,7 +46,7 @@ module Test = struct
in
Error msg
)
| Q {count; arb; prop} ->
| Q {count; arb; prop; long_factor} ->
(* create a random state from the seed *)
let rand =
@ -54,7 +55,7 @@ module Test = struct
in
let module Fmt = CCFormat in
let cell = Q.Test.make_cell ?count ~name:(str_loc self) arb prop in
let cell = Q.Test.make_cell ?count ?long_factor ~name:(str_loc self) arb prop in
let pp_cex out (cx: _ Q.TestResult.counter_ex) =
let {Q.TestResult.instance; shrink_steps=n; msg_l} = cx in
@ -98,7 +99,7 @@ module type S = sig
val eq : ?cmp:'a eq -> ?printer:'a print -> 'a -> 'a -> unit
val q : ?count:int -> 'a Q.arbitrary -> ('a -> bool) -> unit
val q : ?count:int -> ?long_factor:int -> 'a Q.arbitrary -> ('a -> bool) -> unit
val assert_equal :
?printer:('a -> string) -> ?cmp:('a -> 'a -> bool) ->
@ -130,8 +131,8 @@ module Make_test(X:sig val file: string end) = struct
let eq ?cmp ?printer lhs rhs : unit =
add_ @@ mk @@ Test.Eq {eq=cmp; print=printer; lhs; rhs}
let q ?count arb prop : unit =
add_ @@ mk @@ Test.Q {arb; prop; count}
let q ?count ?long_factor arb prop : unit =
add_ @@ mk @@ Test.Q {arb; prop; count; long_factor}
let assert_equal ?printer ?(cmp=(=)) x y : unit =
if not @@ cmp x y then (

View file

@ -13,7 +13,7 @@ module type S = sig
val eq : ?cmp:'a eq -> ?printer:'a print -> 'a -> 'a -> unit
val q : ?count:int -> 'a Q.arbitrary -> ('a -> bool) -> unit
val q : ?count:int -> ?long_factor:int -> 'a Q.arbitrary -> ('a -> bool) -> unit
val assert_equal :
?printer:('a -> string) -> ?cmp:('a -> 'a -> bool) ->

View file

@ -50,12 +50,6 @@ let escape_str s =
Buffer.contents buf
) else s
(*$T
escape_str "foo" = "foo"
escape_str "foo bar" = "'foo bar'"
escape_str "fo'o b'ar" = "'fo'\\''o b'\\''ar'"
*)
let read_all ?(size=1024) ic =
let buf = ref (Bytes.create size) in
let len = ref 0 in
@ -113,12 +107,6 @@ let call_full ?bufsize ?stdin ?env cmd =
method errcode = int_of_process_status status
end)
(*$T
call_full ~stdin:(`Str "abc") "cat" |> stdout = "abc"
call_full "echo %s" (escape_str "a'b'c") |> stdout = "a'b'c\n"
call_full "echo %s" "a'b'c" |> stdout = "abc\n"
*)
let call ?bufsize ?stdin ?env cmd =
call_full_inner ?bufsize ?stdin ?env cmd
~f:(fun (out,err,status) -> out, err, int_of_process_status status)
@ -127,12 +115,6 @@ let call_stdout ?bufsize ?stdin ?env cmd =
call_full_inner ?bufsize ?stdin ?env cmd
~f:(fun (out,_err,_status) -> out)
(*$T
call_stdout ~stdin:(`Str "abc") "cat" = "abc"
call_stdout "echo %s" (escape_str "a'b'c") = "a'b'c\n"
call_stdout "echo %s" "a'b'c" = "abc\n"
*)
type line = string
type async_call_result =
@ -270,29 +252,6 @@ let with_file_lock ~kind filename f =
Unix.close lock_file;
raise e
(*$R
let m = 200 in
let n = 50 in
let write_atom filename s =
with_file_lock ~kind:`Write filename
(fun () ->
CCIO.with_out ~flags:[Open_append; Open_creat]
filename (fun oc -> output_string oc s; flush oc))
in
let f filename =
for j=1 to m do
write_atom filename "foo\n"
done
in
CCIO.File.with_temp ~prefix:"containers_" ~suffix:".txt"
(fun filename ->
let a = Array.init n (fun _ -> Thread.create f filename) in
Array.iter Thread.join a;
let lines = CCIO.with_in filename CCIO.read_lines_l in
assert_equal ~printer:string_of_int (n * m) (List.length lines);
assert_bool "all valid" (List.for_all ((=) "foo") lines))
*)
module Infix = struct
let (?|) fmt = call_full fmt
@ -334,15 +293,3 @@ let with_temp_dir ?(mode=0o700) ?dir pat (f: string -> 'a) : 'a =
)
in
loop 1000
(*$R
let filename = with_temp_dir "test_containers"
(fun dir ->
let name = Filename.concat dir "test" in
CCIO.with_out name (fun oc -> output_string oc "content"; flush oc);
assert_bool ("file exists:"^name) (Sys.file_exists name);
name)
in
assert_bool ("file does not exist"^filename) (not (Sys.file_exists filename));
()
*)

5
tests/core/compat/dune Normal file
View file

@ -0,0 +1,5 @@
(tests
(names t_compat)
(flags :standard -nolabels)
(libraries containers))

View file

@ -0,0 +1,9 @@
(* test consistency of interfaces *)
module type L = module type of CCEqual
module type LL = module type of CCEqualLabels ;;
ignore (module CCEqualLabels : L);;
ignore (module CCEqual : LL);;

View file

@ -1,4 +1,6 @@
(test
(name t)
(flags :standard -strict-sequence -warn-error -a+8)
(libraries containers containers_testlib))
(modes native)
(libraries containers containers.bencode containers.unix threads
containers_testlib iter gen uutf))

View file

@ -13,4 +13,25 @@ Containers_testlib.run_all ~descr:"containers" [
T_format.get();
T_fun.get ();
T_hash.get();
T_hashtbl.get();
T_heap.get();
T_IO.get();
T_int.get();
T_int32.get();
T_int64.get();
T_map.get();
T_nativeint.get();
T_option.get();
T_ord.get();
T_parse.get();
T_random.get();
T_result.get();
T_set.get();
T_seq.get();
T_sexp.get();
T_string.get();
T_utf8string.get();
T_vector.get();
T_bencode.get();
T_unix.get();
];;

69
tests/core/t_IO.ml Normal file
View file

@ -0,0 +1,69 @@
open CCIO
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () ->
let s = String.make 200 'y' in
let s = Printf.sprintf "a\nb\n %s\nlast line\n" s in
File.with_temp ~prefix:"test_containers" ~suffix:""
(fun name ->
with_out name @@ fun oc ->
output_string oc s;
flush oc;
let s' = with_in name read_all in
assert_equal ~printer:(fun s->s) s s'
);
true;;
q Q.(list_of_size Gen.(0 -- 40) printable_string) (fun l ->
let l' = ref [] in
File.with_temp ~prefix:"test_containers" ~suffix:""
(fun name ->
with_out name @@ fun oc ->
write_lines_l oc l;
flush oc;
l' := with_in name read_lines_l;
);
String.concat "\n" l = String.concat "\n" !l'
);;
q Q.(list_of_size Gen.(0 -- 40) printable_string) (fun l ->
let l' = ref [] in
File.with_temp ~prefix:"test_containers" ~suffix:""
(fun name ->
with_out name @@ fun oc ->
write_lines oc (Gen.of_list l);
flush oc;
l' := with_in name (fun ic -> read_lines_gen ic |> Gen.to_list);
);
String.concat "\n" l = String.concat "\n" !l'
);;
q Q.(list_of_size Gen.(0 -- 40) printable_string) (fun l ->
let s = ref "" in
File.with_temp ~prefix:"test_containers1" ~suffix:""
(fun name1 ->
with_out name1 @@ fun oc1 ->
write_gen ~sep:"" oc1 (Gen.of_list l);
flush oc1;
File.with_temp ~prefix:"test_containers2" ~suffix:""
(fun name2 ->
with_out name2 @@ fun oc2 ->
CCIO.with_in name1 (fun ic1 -> copy_into ic1 oc2);
flush oc2;
s := with_in name2 read_all;);
);
String.concat "" l = !s
);;
t @@ fun () ->
File.walk "."
|> Gen.for_all
(function
| `File, f -> not (Sys.is_directory f)
| `Dir, f -> Sys.is_directory f
)
;;

57
tests/core/t_bencode.ml Normal file
View file

@ -0,0 +1,57 @@
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
open Containers_bencode;;
eq ~printer:to_string_debug
(map_of_list []) (Decode.of_string_exn "de");;
eq ~printer:to_string_debug
(list [int 1; int 2; string "foo"]) (Decode.of_string_exn "li1ei2e3:fooe");;
module B = Containers_bencode
let rec size = function
| Int _ | String _ -> 1
| List l -> List.fold_left (fun n x -> n + size x) 0 l
| Map m -> Str_map.fold(fun _ v n -> size v + n) m 0
let g_rand_b =
Q.Gen.(
sized_size (0--7) @@ fix @@ fun self n ->
let str n = string_size ~gen:char (0 -- n) in
let base = [
int >|= B.int;
str 100 >|= B.string;
] in
match n with
| 0 -> oneof base
| n ->
frequency @@
List.map (fun x -> 2, x) base @
[ 1, list_size (0 -- 10) (self (n-1)) >|= B.list;
1, list_size (0 -- 10) (pair (str 10) (self (n-1)) ) >|= B.map_of_list;
]
)
let rec shrink_b self = Q.(Iter.(
match self with
| Int i -> Shrink.int64 i >|= B.int64
| String s -> Shrink.string s >|= B.string
| List l -> Shrink.list ~shrink:shrink_b l >|= B.list
| Map l ->
let l = Str_map.fold (fun k v l -> (k,v) :: l) l [] in
Shrink.list ~shrink:(fun (k,v) ->
(Shrink.string k >|= fun k -> k,v) <+>
(shrink_b v >|= fun v -> k,v))
l
>|= B.map_of_list
))
let rand_b = Q.make ~print:to_string_debug ~stats:["size", size]
~shrink:shrink_b g_rand_b ;;
q rand_b (fun b ->
let s=Encode.to_string b in
equal (Decode.of_string_exn s) b) ;;

View file

@ -5,4 +5,4 @@ module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
q Q.(let p = small_list (pair small_int bool) in pair p p) (fun (l1,l2) ->
CCEqual.(list (pair int bool)) l1 l2 = (l1=l2));;
(list (pair int bool)) l1 l2 = (l1=l2));;

55
tests/core/t_hashtbl.ml Normal file
View file

@ -0,0 +1,55 @@
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
open CCHashtbl;;
eq "c" (let tbl = of_list [1,"a"; 2,"b"] in get_or tbl 3 ~default:"c");;
eq "b" (let tbl = of_list [1,"a"; 2,"b"] in get_or tbl 2 ~default:"c");;
t @@ fun () -> of_list [1,"a"; 2,"b"] |> map_list (fun x y -> string_of_int x ^ y)
|> List.sort Stdlib.compare = ["1a"; "2b"];;
t @@ fun () ->
let tbl = Hashtbl.create 32 in
update tbl ~f:(fun _ _ -> Some "1") ~k:1;
assert_equal (Some "1") (get tbl 1);
update tbl ~f:(fun _ v->match v with Some _ -> assert false | None -> Some "2") ~k:2;
assert_equal (Some "2") (get tbl 2);
assert_equal 2 (Hashtbl.length tbl);
update tbl ~f:(fun _ _ -> None) ~k:1;
assert_equal None (get tbl 1);
true
;;
t @@ fun () ->
let tbl = Hashtbl.create 32 in
let v1 = get_or_add tbl ~f:(fun _ -> "1") ~k:1 in
assert_equal "1" v1;
assert_equal (Some "1") (get tbl 1);
let v2 = get_or_add tbl ~f:(fun _ ->"2") ~k:2 in
assert_equal "2" v2;
assert_equal (Some "2") (get tbl 2);
assert_equal "2" (get_or_add tbl ~f:(fun _ -> assert false) ~k:2);
assert_equal 2 (Hashtbl.length tbl);
true
;;
module TI = Make(CCInt);;
eq "c" (let tbl = TI.of_list [1,"a"; 2,"b"] in TI.get_or tbl 3 ~default:"c");;
eq "b" (let tbl = TI.of_list [1,"a"; 2,"b"] in TI.get_or tbl 2 ~default:"c");;
t @@ fun () ->
let tbl = TI.create 32 in
TI.incr tbl 1 ;
TI.incr tbl 2;
TI.incr tbl 1;
assert_equal 2 (TI.find tbl 1);
assert_equal 1 (TI.find tbl 2);
assert_equal 2 (TI.length tbl);
TI.decr tbl 2;
assert_equal 0 (TI.get_or tbl 2 ~default:0);
assert_equal 1 (TI.length tbl);
assert(not (TI.mem tbl 2));
true;;

87
tests/core/t_heap.ml Normal file
View file

@ -0,0 +1,87 @@
open CCHeap
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
module H = CCHeap.Make(struct
type t = int
let leq x y = x<=y
end)
let rec is_sorted l = match l with
| [_]
| [] -> true
| x::((y::_) as l') -> x <= y && is_sorted l'
let extract_list = H.to_list_sorted;;
t @@ fun () ->
let h = H.of_list [5;3;4;1;42;0] in
let h, x = H.take_exn h in
assert_equal ~printer:string_of_int 0 x;
let h, x = H.take_exn h in
assert_equal ~printer:string_of_int 1 x;
let h, x = H.take_exn h in
assert_equal ~printer:string_of_int 3 x;
let h, x = H.take_exn h in
assert_equal ~printer:string_of_int 4 x;
let h, x = H.take_exn h in
assert_equal ~printer:string_of_int 5 x;
let h, x = H.take_exn h in
assert_equal ~printer:string_of_int 42 x;
assert_raises (function H.Empty ->true| _ -> false)(fun () -> H.take_exn h);
true;;
q ~count:30
Q.(list_of_size Gen.(return 1_000) int) (fun l ->
(* put elements into a heap *)
let h = H.of_iter (Iter.of_list l) in
assert_equal 1_000 (H.size h);
let l' = extract_list h in
is_sorted l'
)
;;
(* test filter *)
q ~count:30
Q.(list_of_size Gen.(return 1_000) int) (fun l ->
(* put elements into a heap *)
let h = H.of_iter (Iter.of_list l) in
let h = H.filter (fun x->x mod 2=0) h in
assert
(H.to_iter h |> Iter.for_all (fun x -> x mod 2 = 0));
let l' = extract_list h in
is_sorted l'
);;
q Q.(list_of_size Gen.(return 1_000) int) (fun l ->
(* put elements into a heap *)
let h = H.of_iter (Iter.of_list l) in
let l' = H.to_iter_sorted h |> Iter.to_list in
is_sorted l'
) ;;
q Q.(list int) (fun l ->
extract_list (H.of_list l) =
extract_list (H.of_gen (CCList.to_gen l))) ;;
q Q.(list int) (fun l ->
let h = H.of_list l in
(H.to_gen h |> CCList.of_gen |> List.sort Stdlib.compare)
= (H.to_list h |> List.sort Stdlib.compare)) ;;
q Q.(list int) (fun l ->
let h = H.of_list l in
(H.to_string string_of_int h)
= (List.sort Stdlib.compare l |> List.map string_of_int |> String.concat ","));;
q Q.(list int) (fun l ->
let h = H.of_list l in
(H.to_string ~sep:" " string_of_int h)
= (List.sort Stdlib.compare l |> List.map string_of_int |> String.concat " "));;
q Q.(list_of_size Gen.(return 1_000) int) (fun l ->
let module H' = Make_from_compare(CCInt) in
let h = H'.of_list l in
let l' = H'.to_list_sorted h in
is_sorted l'
);;

132
tests/core/t_int.ml Normal file
View file

@ -0,0 +1,132 @@
open CCInt
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
eq ~printer:Q.Print.(list int) [0;1;2;3;4;5] (range 0 5 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [0] (range 0 0 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [5;4;3;2] (range 5 2 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [] (range' 0 0 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [0;1;2;3;4] (range' 0 5 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [5;4;3] (range' 5 2 |> Iter.to_list);;
t @@ fun () -> pow 2 10 = 1024;;
t @@ fun () -> pow 2 15 = 32768;;
t @@ fun () -> pow 10 5 = 100000;;
t @@ fun () -> pow 1 0 = 1;;
t @@ fun () -> pow 0 1 = 0;;
t @@ fun () -> (floor_div 3 5 = 0);;
t @@ fun () -> (floor_div 5 5 = 1);;
t @@ fun () -> (floor_div 20 5 = 4);;
t @@ fun () -> (floor_div 12 5 = 2);;
t @@ fun () -> (floor_div 0 5 = 0);;
t @@ fun () -> (floor_div (-1) 5 = -1);;
t @@ fun () -> (floor_div (-5) 5 = -1);;
t @@ fun () -> (floor_div (-12) 5 = -3);;
t @@ fun () -> (floor_div 0 (-5) = 0);;
t @@ fun () -> (floor_div 3 (-5) = -1);;
t @@ fun () -> (floor_div 5 (-5) = -1);;
t @@ fun () -> (floor_div 9 (-5) = -2);;
t @@ fun () -> (floor_div 20 (-5) = -4);;
t @@ fun () -> (floor_div (-2) (-5) = 0);;
t @@ fun () -> (floor_div (-8) (-5) = 1);;
t @@ fun () -> (floor_div (-35) (-5) = 7);;
t @@ fun () -> try ignore (floor_div 12 0); false with Division_by_zero -> true;;
t @@ fun () -> try ignore (floor_div (-12) 0); false with Division_by_zero -> true;;
q (Q.pair Q.small_signed_int Q.pos_int)
(fun (n, m) -> floor_div n m = int_of_float @@ floor (float n /. float m));;
q (Q.pair Q.small_signed_int Q.pos_int)
(fun (n, m) -> floor_div n (-m) = int_of_float @@ floor (float n /. float (-m)));;
t @@ fun () -> (rem 3 5 = 3);;
t @@ fun () -> (rem 5 5 = 0);;
t @@ fun () -> (rem 9 5 = 4);;
t @@ fun () -> (rem (-1) 5 = 4);;
t @@ fun () -> (rem (-5) 5 = 0);;
t @@ fun () -> (rem (-20) 5 = 0);;
t @@ fun () -> (rem (-9) 5 = 1);;
t @@ fun () -> (rem 0 5 = 0);;
t @@ fun () -> (rem 0 (-5) = 0);;
t @@ fun () -> (rem 3 (-5) = -2);;
t @@ fun () -> (rem 5 (-5) = 0);;
t @@ fun () -> (rem 9 (-5) = -1);;
t @@ fun () -> (rem (-2) (-5) = -2);;
t @@ fun () -> (rem (-8) (-5) = -3);;
t @@ fun () -> (rem (-35) (-5) = 0);;
t @@ fun () -> try ignore (rem 12 0); false with Division_by_zero -> true;;
t @@ fun () -> try ignore (rem (-12) 0); false with Division_by_zero -> true;;
q (Q.pair Q.int Q.pos_int) (fun (n, m) -> let y = rem n m in y >= 0 && y < m);;
q (Q.pair Q.int Q.pos_int) (fun (n, m) -> let y = rem n (-m) in y > (-m) && y <= 0);;
q (Q.pair Q.int Q.pos_int) (fun (n, m) -> n = m * floor_div n m + rem n m);;
q (Q.pair Q.int Q.pos_int) (fun (n, m) -> n = (-m) * floor_div n (-m) + rem n (-m));;
eq None (of_string "moo");;
eq (Some 42) (of_string "42");;
eq 1 (of_float 1.2);;
eq ~printer:CCFun.id "0b111" (to_string_binary 7);;
eq ~printer:CCFun.id "-0b111" (to_string_binary (-7));;
eq ~printer:CCFun.id "0b0" (to_string_binary 0);;
q ~count:10_000
Q.int (fun n -> n = int_of_string (to_string_binary n));;
(* note: the last test checks that no error occurs due to overflows. *)
eq ~printer:Q.Print.(list int) [0] (range_by ~step:1 0 0 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [] (range_by ~step:1 5 0 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [] (range_by ~step:2 1 0 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [0;2;4] (range_by ~step:2 0 4 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [0;2;4] (range_by ~step:2 0 5 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [0] (range_by ~step:~-1 0 0 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [] (range_by ~step:~-1 0 5 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [] (range_by ~step:~-2 0 1 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [5;3;1] (range_by ~step:~-2 5 1 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [5;3;1] (range_by ~step:~-2 5 0 |> Iter.to_list);;
eq ~printer:Q.Print.(list int) [0] (range_by ~step:max_int 0 2 |> Iter.to_list);;
q Q.(pair small_int small_int) (fun (i,j) ->
let i = min i j and j = max i j in
CCList.equal CCInt.equal
(CCInt.range_by ~step:1 i j |> Iter.to_list)
(CCInt.range i j |> Iter.to_list) );;
eq 0 (popcount 0);;
eq 1 (popcount 1);;
eq (Sys.word_size-2) (popcount max_int);;
eq 1 (popcount min_int);;
eq 10 (popcount 0b1110010110110001010);;
eq 5 (popcount 0b1101110000000000);;
let simple_popcnt i =
let rec loop n i =
if i=0 then n
else if i land 0b1 = 1 then loop (n+1) (i lsr 1)
else loop n (i lsr 1)
in
loop 0 i ;;
eq 0 (simple_popcnt 0);;
eq 1 (simple_popcnt 1);;
eq (Sys.word_size-2) (simple_popcnt max_int);;
eq 1 (simple_popcnt min_int);;
eq 5 (simple_popcnt 0b1101110000000000);;
q ~count:3_000 ~long_factor:10
Q.(let g = int in
set_gen (Gen.graft_corners g.gen [min_int; max_int; 0; -1; 1] ()) g)
(fun i ->
if simple_popcnt i <> popcount i then (
Q.Test.fail_reportf "on %d: simple-popcount=%d, popcount=%d"
i (simple_popcnt i) (popcount i)
);
true);;

66
tests/core/t_int32.ml Normal file
View file

@ -0,0 +1,66 @@
open CCInt32
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () -> pow 2l 10l = 1024l;;
t @@ fun () -> pow 2l 15l = 32768l;;
t @@ fun () -> pow 10l 5l = 100000l;;
t @@ fun () -> pow 42l 0l = 1l;;
t @@ fun () -> pow 0l 1l = 0l;;
t @@ fun () -> (floor_div 3l 5l = 0l);;
t @@ fun () -> (floor_div 5l 5l = 1l);;
t @@ fun () -> (floor_div 20l 5l = 4l);;
t @@ fun () -> (floor_div 12l 5l = 2l);;
t @@ fun () -> (floor_div 0l 5l = 0l);;
t @@ fun () -> (floor_div (-1l) 5l = -1l);;
t @@ fun () -> (floor_div (-5l) 5l = -1l);;
t @@ fun () -> (floor_div (-12l) 5l = -3l);;
t @@ fun () -> (floor_div 0l (-5l) = 0l);;
t @@ fun () -> (floor_div 3l (-5l) = -1l);;
t @@ fun () -> (floor_div 5l (-5l) = -1l);;
t @@ fun () -> (floor_div 9l (-5l) = -2l);;
t @@ fun () -> (floor_div 20l (-5l) = -4l);;
t @@ fun () -> (floor_div (-2l) (-5l) = 0l);;
t @@ fun () -> (floor_div (-8l) (-5l) = 1l);;
t @@ fun () -> (floor_div (-35l) (-5l) = 7l);;
t @@ fun () -> try ignore (floor_div 12l 0l); false with Division_by_zero -> true;;
t @@ fun () -> try ignore (floor_div (-12l) 0l); false with Division_by_zero -> true;;
q (Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat))
(fun (n, m) -> let m = m + 1l in
floor_div n m = of_float @@ floor (to_float n /. to_float m));;
q (Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat))
(fun (n, m) -> let m = m + 1l in
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)));;
let eq' = eq ~printer:Q.Print.(list to_string);;
eq' [0l;1l;2l;3l;4l;5l] (range 0l 5l |> Iter.to_list);;
eq' [0l] (range 0l 0l |> Iter.to_list);;
eq' [5l;4l;3l;2l] (range 5l 2l |> Iter.to_list);;
(* note: the last test checks that no error occurs due to overflows. *)
let eq'= eq~printer:Q.Print.(list to_string);;
eq' [0l] (range_by ~step:1l 0l 0l |> Iter.to_list);;
eq' [] (range_by ~step:1l 5l 0l |> Iter.to_list);;
eq' [] (range_by ~step:2l 1l 0l |> Iter.to_list);;
eq' [0l;2l;4l] (range_by ~step:2l 0l 4l |> Iter.to_list);;
eq' [0l;2l;4l] (range_by ~step:2l 0l 5l |> Iter.to_list);;
eq' [0l] (range_by ~step:(neg 1l) 0l 0l |> Iter.to_list);;
eq' [] (range_by ~step:(neg 1l) 0l 5l |> Iter.to_list);;
eq' [] (range_by ~step:(neg 2l) 0l 1l |> Iter.to_list);;
eq' [5l;3l;1l] (range_by ~step:(neg 2l) 5l 1l |> Iter.to_list);;
eq' [5l;3l;1l] (range_by ~step:(neg 2l) 5l 0l |> Iter.to_list);;
eq' [0l] (range_by ~step:max_int 0l 2l |> Iter.to_list);;
q Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) ->
let i = min i j and j = max i j in
CCList.equal CCInt32.equal
(CCInt32.range_by ~step:1l i j |> Iter.to_list)
(CCInt32.range i j |> Iter.to_list) );;
eq ~printer:CCFun.id "0b111" (to_string_binary 7l);;
eq ~printer:CCFun.id "-0b111" (to_string_binary (-7l));;
eq ~printer:CCFun.id "0b0" (to_string_binary 0l);;

65
tests/core/t_int64.ml Normal file
View file

@ -0,0 +1,65 @@
open CCInt64
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () -> pow 2L 10L = 1024L;;
t @@ fun () -> pow 2L 15L = 32768L;;
t @@ fun () -> pow 10L 5L = 100000L;;
t @@ fun () -> pow 42L 0L = 1L;;
t @@ fun () -> pow 0L 1L = 0L;;
t @@ fun () -> (floor_div 3L 5L = 0L);;
t @@ fun () -> (floor_div 5L 5L = 1L);;
t @@ fun () -> (floor_div 20L 5L = 4L);;
t @@ fun () -> (floor_div 12L 5L = 2L);;
t @@ fun () -> (floor_div 0L 5L = 0L);;
t @@ fun () -> (floor_div (-1L) 5L = -1L);;
t @@ fun () -> (floor_div (-5L) 5L = -1L);;
t @@ fun () -> (floor_div (-12L) 5L = -3L);;
t @@ fun () -> (floor_div 0L (-5L) = 0L);;
t @@ fun () -> (floor_div 3L (-5L) = -1L);;
t @@ fun () -> (floor_div 5L (-5L) = -1L);;
t @@ fun () -> (floor_div 9L (-5L) = -2L);;
t @@ fun () -> (floor_div 20L (-5L) = -4L);;
t @@ fun () -> (floor_div (-2L) (-5L) = 0L);;
t @@ fun () -> (floor_div (-8L) (-5L) = 1L);;
t @@ fun () -> (floor_div (-35L) (-5L) = 7L);;
t @@ fun () -> try ignore (floor_div 12L 0L); false with Division_by_zero -> true;;
t @@ fun () -> try ignore (floor_div (-12L) 0L); false with Division_by_zero -> true;;
q (Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat))
(fun (n, m) -> let m = m + 1L in
floor_div n m = of_float @@ floor (to_float n /. to_float m));;
q (Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat))
(fun (n, m) -> let m = m + 1L in
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)));;
eq ~printer:Q.Print.(list to_string) [0L;1L;2L;3L;4L;5L] (range 0L 5L |> Iter.to_list);;
eq ~printer:Q.Print.(list to_string) [0L] (range 0L 0L |> Iter.to_list);;
eq ~printer:Q.Print.(list to_string) [5L;4L;3L;2L] (range 5L 2L |> Iter.to_list);;
(* note: the last test checks that no error occurs due to overflows. *)
let eq' = eq ~printer:Q.Print.(list to_string);;
eq' [0L] (range_by ~step:1L 0L 0L |> Iter.to_list);;
eq' [] (range_by ~step:1L 5L 0L |> Iter.to_list);;
eq' [] (range_by ~step:2L 1L 0L |> Iter.to_list);;
eq' [0L;2L;4L] (range_by ~step:2L 0L 4L |> Iter.to_list);;
eq' [0L;2L;4L] (range_by ~step:2L 0L 5L |> Iter.to_list);;
eq' [0L] (range_by ~step:(neg 1L) 0L 0L |> Iter.to_list);;
eq' [] (range_by ~step:(neg 1L) 0L 5L |> Iter.to_list);;
eq' [] (range_by ~step:(neg 2L) 0L 1L |> Iter.to_list);;
eq' [5L;3L;1L] (range_by ~step:(neg 2L) 5L 1L |> Iter.to_list);;
eq' [5L;3L;1L] (range_by ~step:(neg 2L) 5L 0L |> Iter.to_list);;
eq' [0L] (range_by ~step:max_int 0L 2L |> Iter.to_list);;
q Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) ->
let i = min i j and j = max i j in
CCList.equal CCInt64.equal
(CCInt64.range_by ~step:1L i j |> Iter.to_list)
(CCInt64.range i j |> Iter.to_list) );;
eq ~printer:CCFun.id "0b111" (to_string_binary 7L);;
eq ~printer:CCFun.id "-0b111" (to_string_binary (-7L));;
eq ~printer:CCFun.id "0b0" (to_string_binary 0L);;

27
tests/core/t_map.ml Normal file
View file

@ -0,0 +1,27 @@
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
open CCMap;;
module M = CCMap.Make(String);;
let eq' = eq ~printer:CCFormat.(to_string @@ Dump.(list (pair string int)));;
eq' ["a", 1; "b", 20]
(M.of_list ["b", 2; "c", 3]
|> M.update "a" (function _ -> Some 1)
|> M.update "c" (fun _ -> None)
|> M.update "b" (CCOption.map (fun x -> x * 10))
|> M.to_list |> List.sort CCOrd.poly);;
module M2 = Make(CCInt);;
q Q.(list (pair small_int small_int)) M2.(fun l ->
to_list (of_list l) = to_list (of_list_with ~f:(fun _ v _ ->v) l));;
q Q.(list (pair small_int small_int)) M2.(fun l ->
to_list (of_iter @@ Iter.of_list l) =
to_list (of_iter_with ~f:(fun _ v _ ->v) @@ Iter.of_list l));;
q Q.(list (pair small_int small_int)) M2.(fun l ->
to_list (of_seq @@ CCSeq.of_list l) =
to_list (of_seq_with ~f:(fun _ v _ ->v) @@ CCSeq.of_list l));;

67
tests/core/t_nativeint.ml Normal file
View file

@ -0,0 +1,67 @@
open CCNativeint
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () -> pow 2n 10n = 1024n;;
t @@ fun () -> pow 2n 15n = 32768n;;
t @@ fun () -> pow 10n 5n = 100000n;;
t @@ fun () -> pow 42n 0n = 1n;;
t @@ fun () -> pow 0n 1n = 0n;;
t @@ fun () -> (floor_div 3n 5n = 0n);;
t @@ fun () -> (floor_div 5n 5n = 1n);;
t @@ fun () -> (floor_div 20n 5n = 4n);;
t @@ fun () -> (floor_div 12n 5n = 2n);;
t @@ fun () -> (floor_div 0n 5n = 0n);;
t @@ fun () -> (floor_div (-1n) 5n = -1n);;
t @@ fun () -> (floor_div (-5n) 5n = -1n);;
t @@ fun () -> (floor_div (-12n) 5n = -3n);;
t @@ fun () -> (floor_div 0n (-5n) = 0n);;
t @@ fun () -> (floor_div 3n (-5n) = -1n);;
t @@ fun () -> (floor_div 5n (-5n) = -1n);;
t @@ fun () -> (floor_div 9n (-5n) = -2n);;
t @@ fun () -> (floor_div 20n (-5n) = -4n);;
t @@ fun () -> (floor_div (-2n) (-5n) = 0n);;
t @@ fun () -> (floor_div (-8n) (-5n) = 1n);;
t @@ fun () -> (floor_div (-35n) (-5n) = 7n);;
t @@ fun () -> try ignore (floor_div 12n 0n); false with Division_by_zero -> true;;
t @@ fun () -> try ignore (floor_div (-12n) 0n); false with Division_by_zero -> true;;
q (Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat))
(fun (n, m) -> let m = m + 1n in
floor_div n m = of_float @@ floor (to_float n /. to_float m));;
q (Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat))
(fun (n, m) -> let m = m + 1n in
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)));;
let eq' = eq ~printer:Q.Print.(list to_string);;
eq' [0n;1n;2n;3n;4n;5n] (range 0n 5n |> Iter.to_list);;
eq' [0n] (range 0n 0n |> Iter.to_list);;
eq' [5n;4n;3n;2n] (range 5n 2n |> Iter.to_list);;
(* note: the last test checks that no error occurs due to overflows. *)
let eq' = eq ~printer:Q.Print.(list to_string);;
eq' [0n] (range_by ~step:1n 0n 0n |> Iter.to_list);;
eq' [] (range_by ~step:1n 5n 0n |> Iter.to_list);;
eq' [] (range_by ~step:2n 1n 0n |> Iter.to_list);;
eq' [0n;2n;4n] (range_by ~step:2n 0n 4n |> Iter.to_list);;
eq' [0n;2n;4n] (range_by ~step:2n 0n 5n |> Iter.to_list);;
eq' [0n] (range_by ~step:(neg 1n) 0n 0n |> Iter.to_list);;
eq' [] (range_by ~step:(neg 1n) 0n 5n |> Iter.to_list);;
eq' [] (range_by ~step:(neg 2n) 0n 1n |> Iter.to_list);;
eq' [5n;3n;1n] (range_by ~step:(neg 2n) 5n 1n |> Iter.to_list);;
eq' [5n;3n;1n] (range_by ~step:(neg 2n) 5n 0n |> Iter.to_list);;
eq' [0n] (range_by ~step:max_int 0n 2n |> Iter.to_list);;
q Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) ->
let i = min i j and j = max i j in
CCList.equal CCNativeint.equal
(CCNativeint.range_by ~step:1n i j |> Iter.to_list)
(CCNativeint.range i j |> Iter.to_list) );;
eq ~printer:CCFun.id "0b111" (to_string_binary 7n);;
eq ~printer:CCFun.id "-0b111" (to_string_binary (-7n));;
eq ~printer:CCFun.id "0b0" (to_string_binary 0n);;

25
tests/core/t_option.ml Normal file
View file

@ -0,0 +1,25 @@
open CCOption
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
eq None (filter ((=) 0) (Some 1));;
eq (Some 0) (filter ((=) 0) (Some 0));;
eq None (filter (fun _ -> true) None);;
eq (try get_exn_or "ohno" (None:unit option); false with Invalid_argument s->s= "ohno");;
t @@ fun () -> 123 = get_exn_or "yes" (Some 123);;
t @@ fun () -> sequence_l [None; Some 1; Some 2] = None;;
t @@ fun () -> sequence_l [Some 1; Some 2; Some 3] = Some [1;2;3];;
t @@ fun () -> sequence_l [] = Some [];;
t @@ fun () -> choice_iter (Iter.of_list [None; Some 1; Some 2]) = Some 1;;
t @@ fun () -> choice_iter Iter.empty = None;;
t @@ fun () -> choice_iter (Iter.repeat None |> Iter.take 100) = None;;
t @@ fun () -> choice_seq (CCSeq.of_list [None; Some 1; Some 2]) = Some 1;;
t @@ fun () -> choice_seq CCSeq.empty = None;;
t @@ fun () -> choice_seq (CCSeq.repeat None |> CCSeq.take 100) = None;;
t @@ fun () -> flatten None = None;;
t @@ fun () -> flatten (Some None) = None;;
t @@ fun () -> flatten (Some (Some 1)) = Some 1;;
t @@ fun () -> return_if false 1 = None;;
t @@ fun () -> return_if true 1 = Some 1;;

43
tests/core/t_ord.ml Normal file
View file

@ -0,0 +1,43 @@
open CCOrd
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () -> equiv 1 2;;
t @@ fun () -> equiv ~-1 ~-10;;
t @@ fun () -> equiv 0 0;;
t @@ fun () -> equiv ~-1 ~-1;;
t @@ fun () -> not (equiv 0 1);;
t @@ fun () -> not (equiv 1 ~-1);;
t @@ fun () -> not (equiv 1 0);;
q Q.(pair int int) (fun (x,y) ->
(equiv x y) = (equiv y x));;
q Q.(triple int int int) (fun (x,y,z) ->
if (equiv x y && equiv y z) then (equiv x z) else true);;
t @@ fun () -> bool true false > 0;;
t @@ fun () -> bool false true < 0;;
t @@ fun () -> bool true true = 0;;
t @@ fun () -> bool false false = 0;;
q Q.(option int) (fun o -> option int None o <= 0);;
t @@ fun () -> pair int string (1, "b") (2, "a") < 0;;
t @@ fun () -> pair int string (1, "b") (0, "a") > 0;;
t @@ fun () -> pair int string (1, "b") (1, "b") = 0;;
t @@ fun () -> list int [1;2;3] [1;2;3;4] < 0;;
t @@ fun () -> list int [1;2;3;4] [1;2;3] > 0;;
t @@ fun () -> list int [1;2;3;4] [1;3;4] < 0;;
q Q.(pair (list int)(list int)) CCOrd.(fun (l1,l2) ->
equiv (list int l1 l2) (Stdlib.compare l1 l2));;
t @@ fun () -> array int [|1;2;3|] [|1;2;3;4|] < 0;;
t @@ fun () -> array int [|1;2;3;4|] [|1;2;3|] > 0;;
t @@ fun () -> array int [|1;2;3;4|] [|1;3;4|] < 0;;
q
Q.(pair (array int)(array int)) CCOrd.(fun (a1,a2) ->
equiv (array int a1 a2) (list int (Array.to_list a1) (Array.to_list a2)));;

214
tests/core/t_parse.ml Normal file
View file

@ -0,0 +1,214 @@
module Tst = (val Containers_testlib.make ~__FILE__ ())
include Tst;;
open CCParse
module T = struct
type tree = L of int | N of tree * tree
end
open T
let mk_leaf x = L x
let mk_node x y = N(x,y)
let ptree = fix @@ fun self ->
skip_space *>
( (char '(' *> (pure mk_node <*> self <*> self) <* char ')')
<|>
(U.int >|= mk_leaf) )
let ptree' = fix_memo @@ fun self ->
skip_space *>
( (char '(' *> (pure mk_node <*> self <*> self) <* char ')')
<|>
(U.int >|= mk_leaf) )
let rec pptree = function
| N (a,b) -> Printf.sprintf "N (%s, %s)" (pptree a) (pptree b)
| L x -> Printf.sprintf "L %d" x
let errpp pp = function
| Ok x -> "Ok " ^ pp x
| Error s -> "Error " ^ s
let errpptree = errpp pptree
let erreq eq x y = match x, y with
| Ok x, Ok y -> eq x y
| Error _ , Error _ -> true
| _ -> false ;;
(* ### start tests ### *)
eq ~printer:errpptree (Ok (N (L 1, N (L 2, L 3))))
(parse_string ptree "(1 (2 3))" );;
eq ~printer:errpptree (Ok (N (N (L 1, L 2), N (L 3, N (L 4, L 5)))))
(parse_string ptree "((1 2) (3 (4 5)))" );;
eq ~printer:errpptree (Ok (N (L 1, N (L 2, L 3))))
(parse_string ptree' "(1 (2 3))" );;
eq ~printer:errpptree (Ok (N (N (L 1, L 2), N (L 3, N (L 4, L 5)))))
(parse_string ptree' "((1 2) (3 (4 5)))" );;
t @@ fun () ->
let p = U.list ~sep:"," U.word in
let printer = function
| Ok l -> "Ok " ^ CCFormat.(to_string (Dump.list string_quoted)) l
| Error s -> "Error " ^ s
in
assert_equal ~printer
(Ok ["abc"; "de"; "hello"; "world"])
(parse_string p "[abc , de, hello ,world ]");
true;;
t @@ fun () ->
let test n =
let p = CCParse.(U.list ~sep:"," U.int) in
let l = CCList.(1 -- n) in
let l_printed =
CCFormat.(to_string (within "[" "]" (list ~sep:(return ",") int))) l in
let l' = CCParse.parse_string_exn p l_printed in
assert_equal ~printer:Q.Print.(list int) l l'
in
test 300_000;
true ;;
t @@ fun () ->
let open CCParse.Infix in
let module P = CCParse in
let parens p = P.char '(' *> p <* P.char ')' in
let add = P.char '+' *> P.return (+) in
let sub = P.char '-' *> P.return (-) in
let mul = P.char '*' *> P.return ( * ) in
let div = P.char '/' *> P.return ( / ) in
let integer =
P.chars1_if (function '0'..'9'->true|_->false) >|= int_of_string in
let chainr1 e op =
P.fix (fun r ->
e >>= fun x -> (op <*> P.return x <*> r) <|> P.return x) in
let expr : int P.t =
P.fix (fun expr ->
let factor = parens expr <|> integer in
let term = chainr1 factor (mul <|> div) in
chainr1 term (add <|> sub)) in
assert_equal (Ok 6) (P.parse_string expr "4*1+2");
assert_equal (Ok 12) (P.parse_string expr "4*(1+2)");
true;;
let eq' = eq ~printer:(errpp Q.Print.bool) ~cmp:(erreq (=)) ;;
eq' (Ok true) (parse_string (U.bool <* eoi) "true");;
eq' (Error "") (parse_string (U.bool <* eoi) "true ");;
eq' (Ok true) (parse_string (U.bool <* skip_white <* eoi) "true");;
let eq' = eq ~printer:Q.Print.(pair int int);;
eq' (0,5) (let p = any_char_n 5 *> pos in
match parse_string p "abcde " with
| Ok p -> Position.line_and_column p
| Error _ -> assert false);;
eq ~printer:Q.Print.(list @@ pair int int)
[(0,2); (1,3); (2,1); (3,0); (4,0); (5,2)]
(let p = each_line (skip_space *> pos) in
match parse_string p " a\n b\nc\n\n\n a" with
| Ok ps -> List.map Position.line_and_column ps
| Error _ -> assert false);;
let eq' = eq ~printer:(errpp Q.Print.string) ~cmp:(erreq (=));;
eq' (Ok "abcd") (parse_string all_str "abcd");;
eq' (Ok "cd") (parse_string (string "ab" *> all_str) "abcd");;
eq' (Ok "") (parse_string (string "ab" *> all_str) "ab");;
eq ~printer:(errpp Q.Print.(pair string string)) ~cmp:(erreq (=))
(Ok ("foobar", "")) (parse_string (both all_str all_str) "foobar");;
q Q.(printable_string) (fun s ->
let pred = (function 'a'..'z' | 'A' .. 'Z' | '{' | '}' -> true | _ -> false) in
let p1 = chars1_if pred in
let p2 = take1_if pred >|= Slice.to_string in
parse_string p1 s = parse_string p2 s);;
t @@ fun () ->
let pred = (function 'a'..'z' | 'A' .. 'Z' | '{' | '}' -> true | _ -> false) in
parse_string (chars_if pred) "coucou{lol} 123" = Ok "coucou{lol}" ;;
t @@ fun () ->
let p0 = skip_white *> U.int in
let p = (skip_white *> char '(' *> many p0) <* (skip_white <* char ')') in
let printer = CCFormat.(to_string @@ Dump.result @@ Dump.list int) in
assert_equal ~printer
(Ok [1;2;3]) (parse_string p "(1 2 3)");
assert_equal ~printer
(Ok [1;2; -30; 4]) (parse_string p "( 1 2 -30 4 )");
true;;
let aword = chars1_if (function 'a'..'z'|'A'..'Z'->true|_ -> false);;
eq ~printer:(errpp Q.Print.(list string))
(Ok ["a";"b";"c"])
(parse_string (optional (char '/') *> sep ~by:(char '/') aword) "/a/b/c");;
eq ~printer:(errpp Q.Print.(list string))
(Ok ["a";"b";"c"])
(parse_string (optional (char '/') *> sep ~by:(char '/') aword) "a/b/c");;
eq ~printer:(errpp Q.Print.(string))
(Ok "abc") (parse_string (lookahead (string "ab") *> (string "abc")) "abcd");;
eq ~printer:(errpp Q.Print.(string))
(Ok "1234") (parse_string line_str "1234\nyolo");;
eq ~printer:(errpp Q.Print.(pair String.escaped String.escaped))
(Ok ("1234", "yolo")) (parse_string (line_str ||| line_str) "1234\nyolo\nswag");;
eq ~printer:(errpp Q.Print.(list string)) ~cmp:(erreq (=))
(Ok ["a";"b";"c";"d,e,f"])
(parse_string (split_list_at_most ~on_char:',' 3 >|= List.map Slice.to_string) "a,b,c,d,e,f");;
eq ~printer:(errpp Q.Print.(list string)) ~cmp:(erreq (=))
(Ok ["a";"bc"])
(parse_string (split_list_at_most ~on_char:',' 3 >|= List.map Slice.to_string) "a,bc");;
eq ~printer:(errpp Q.Print.(list @@ list int))
(Ok ([[1;1];[2;2];[3;3];[]]))
(parse_string (each_line (sep ~by:skip_space U.int)) "1 1\n2 2\n3 3\n");;
let eq' = eq ~printer:(errpp Q.Print.int) ~cmp:(erreq (=)) ;;
eq' (Ok 42) (parse_string U.int " 42");;
eq' (Ok 2) (parse_string U.int "2");;
eq' (Error "") (parse_string U.int "abc");;
eq' (Error "") (parse_string U.int "");;
let eq' = eq ~printer:(errpp Q.Print.int) ~cmp:(erreq (=));;
eq' (Ok 15) (parse_string (U.in_paren (U.in_paren U.int)) "( ( 15) )");;
eq' (Ok 2) (parse_string (U.in_paren U.int) "(2)");;
eq' (Error "") (parse_string (U.in_paren U.int) "2");;
eq' (Error "") (parse_string (U.in_paren U.int) "");;
eq' (Ok 2) (parse_string (U.in_parens_opt U.int) "((((2))))");;
eq' (Ok 2) (parse_string (U.in_parens_opt U.int) "2");;
eq' (Ok 200) (parse_string (U.in_parens_opt U.int) "( ( 200 ) )");;
let eq' = eq ~printer:(errpp Q.Print.(option int)) ~cmp:(erreq (=));;
eq' (Ok (Some 12)) (parse_string U.(option int) " Some 12");;
eq' (Ok None) (parse_string U.(option int) " None");;
eq' (Ok (Some 0)) (parse_string U.(option int) "Some 0");;
eq' (Ok (Some 0)) (parse_string U.(in_parens_opt @@ option int) "(( Some 0) )");;
let eq' = eq ~printer:(errpp Q.Print.int) ~cmp:(erreq (=)) ;;
eq' (Ok 16) (parse_string U.hexa_int "0x10");;
eq' (Ok 16) (parse_string U.hexa_int "10");;
eq' (Error "") (parse_string U.hexa_int "x10");;
eq' (Error "") (parse_string U.hexa_int "0xz");;
eq ~printer:(errpp Q.Print.bool) ~cmp:(erreq (=))
(Ok true) (parse_string U.bool "true");;
eq ~printer:(errpp Q.Print.bool) ~cmp:(erreq (=))
(Ok false) (parse_string U.bool "false");;
eq ~printer:Q.Print.(errpp (pair int int))
(Ok(1,2)) U.(parse_string (pair int int) "(1 , 2 )");;

19
tests/core/t_random.ml Normal file
View file

@ -0,0 +1,19 @@
open CCRandom
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
q Q.(list small_int) (fun l ->
l=[] || List.mem (run (pick_list l)) l);;
q Q.(pair small_int small_int) (fun (i,j) ->
let len, n = 2+min i j, max i j in
let l = QCheck.Gen.generate1 (split_list n ~len) in
match l with None -> true | Some l -> l<> [] && List.for_all (fun x->x>0) l);;
t @@ fun () ->
let open Containers in
ignore (List.random_choose [1;2;3] (Random.get_state()) : int);
true;;

32
tests/core/t_result.ml Normal file
View file

@ -0,0 +1,32 @@
open CCResult
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () -> (Error "ohno 42") = (fail_printf "ohno %d" 42);;
t @@ fun () -> (Error "ohno 42") = (fail_fprintf "ohno %d" 42);;
eq (Error "error\ncontext:message(number 42, foo: true)")
(add_ctxf "message(number %d, foo: %B)" 42 true (Error "error"));;
t @@ fun () ->
let called_with = ref None in
let f e = called_with := Some e in
iter_err f (Ok 1);
assert (!called_with = None);
iter_err f (Error 1);
assert (!called_with = Some 1);
true ;;
t @@ fun () -> get_or_failwith (Ok 1) = 1;;
t @@ fun () -> try ignore @@ get_or_failwith (Error "e"); false with Failure msg -> msg = "e";;
eq (get_lazy (fun _ -> 2) (Ok 1)) (1);;
eq (get_lazy (fun _ -> 2) (Error "error")) (2);;
eq 42 (fold_ok (+) 2 (Ok 40));;
eq 40 (fold_ok (+) 40 (Error "foo"));;
eq (Ok []) (flatten_l []);;
eq (Ok [1;2;3]) (flatten_l [Ok 1; Ok 2; Ok 3]);;
eq (Error "ohno") (flatten_l [Ok 1; Error "ohno"; Ok 2; Ok 3; Error "wut"]);;

88
tests/core/t_seq.ml Normal file
View file

@ -0,0 +1,88 @@
open CCSeq
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () -> repeat ~n:4 0 |> to_list = [0;0;0;0];;
t @@ fun () -> repeat ~n:0 1 |> to_list = [];;
t @@ fun () -> repeat 1 |> take 20 |> to_list = (repeat ~n:20 1 |> to_list);;
t @@ fun () -> of_list [1;2;3;4] |> take_while (fun x->x < 4) |> to_list = [1;2;3];;
q (Q.pair (Q.list Q.small_int) Q.small_int) (fun (l,n) ->
let s = of_list l in let s1, s2 = take n s, drop n s in
append s1 s2 |> to_list = l );;
t @@ fun () -> (map ((+) 1) (1 -- 5) |> to_list) = (2 -- 6 |> to_list);;
t @@ fun () -> mapi (fun i x -> i,x) (1 -- 3) |> to_list = [0, 1; 1, 2; 2, 3];;
t @@ fun () -> fmap (fun x -> if x mod 2=0 then Some (x*3) else None) (1--10) |> to_list
= [6;12;18;24;30];;
t @@ fun () -> cycle (of_list [1;2]) |> take 5 |> to_list = [1;2;1;2;1];;
t @@ fun () -> cycle (of_list [1; ~-1]) |> take 100_000 |> fold (+) 0 = 0;;
t @@ fun () -> let f = function 10 -> None | x -> Some (x, x+1) in
unfold f 0 |> to_list = [0;1;2;3;4;5;6;7;8;9];;
t @@ fun () -> for_all ((=) 1) (of_list []) = true;;
t @@ fun () -> for_all ((=) 1) (of_list [0]) = false;;
t @@ fun () -> for_all ((=) 1) (of_list [1]) = true;;
t @@ fun () -> for_all ((=) 1) (of_list [1; 0]) = false;;
t @@ fun () -> for_all ((=) 1) (of_list [0; 1]) = false;;
t @@ fun () -> for_all ((=) 1) (of_list [1; 1]) = true;;
t @@ fun () -> let l () = Cons (0, fun () -> failwith "no second element") in
try ignore (for_all ((=) 1) l); true with Failure _ -> false;;
t @@ fun () -> exists ((=) 1) (of_list []) = false;;
t @@ fun () -> exists ((=) 1) (of_list [0]) = false;;
t @@ fun () -> exists ((=) 1) (of_list [1]) = true;;
t @@ fun () -> exists ((=) 1) (of_list [1; 0]) = true;;
t @@ fun () -> exists ((=) 1) (of_list [0; 1]) = true;;
t @@ fun () -> exists ((=) 1) (of_list [0; 0]) = false;;
t @@ fun () -> let l () = Cons (1, fun () -> failwith "no second element") in
try ignore (exists ((=) 1) l); true with Failure _ -> false;;
t @@ fun () -> of_list [1;1;1;2;2;3;3;1] |> group (=)
|> map to_list |> to_list = [[1;1;1]; [2;2]; [3;3]; [1]];;
t @@ fun () -> range 0 5 |> to_list = [0;1;2;3;4;5];;
t @@ fun () -> range 0 0 |> to_list = [0];;
t @@ fun () -> range 5 2 |> to_list = [5;4;3;2];;
t @@ fun () -> 1 --^ 5 |> to_list = [1;2;3;4];;
t @@ fun () -> 5 --^ 1 |> to_list = [5;4;3;2];;
t @@ fun () -> 1 --^ 2 |> to_list = [1];;
t @@ fun () -> 0 --^ 0 |> to_list = [];;
q Q.(list (pair int int)) (fun l ->
let l = of_list l in let a, b = unzip l in equal (=) l (zip a b));;
eq [0,'a'; 1, 'b'; 2, 'c'] (of_string "abcde" |> zip_i |> take 3 |> to_list);;
q Q.(array int) (fun a -> of_array a |> to_array = a);;
t @@ fun () -> of_array [| 1; 2; 3 |] |> to_list = [1;2;3];;
t @@ fun () -> of_list [1;2;3] |> to_array = [| 1; 2; 3; |];;
t @@ fun () ->
let r = ref 1 in
let s = unfold (fun i -> if i < 3 then let x = !r in incr r; Some (x, succ i) else None) 0 in
to_array s = [| 1; 2; 3; |];;
t @@ fun () ->
let g = let n = ref 0 in fun () -> Some (incr n; !n) in
let l = of_gen g in
assert_equal [1;2;3;4;5;6;7;8;9;10] (take 10 l |> to_list);
assert_equal [1;2;3;4;5;6;7;8;9;10] (take 10 l |> to_list);
assert_equal [11;12] (drop 10 l |> take 2 |> to_list);
true;;
t @@ fun () ->
let printer = Q.Print.(list int) in
let gen () =
let rec l = let r = ref 0 in fun () -> incr r; Cons (!r, l) in l
in
let l1 = gen () in
assert_equal ~printer [1;2;3;4] (take 4 l1 |> to_list);
assert_equal ~printer [5;6;7;8] (take 4 l1 |> to_list);
let l2 = gen () |> memoize in
assert_equal ~printer [1;2;3;4] (take 4 l2 |> to_list);
assert_equal ~printer [1;2;3;4] (take 4 l2 |> to_list);
true;;
t @@ fun () -> interleave (of_list [1;3;5]) (of_list [2;4;6]) |> to_list = [1;2;3;4;5;6];;
t @@ fun () -> fair_app (of_list [(+)1; ( * ) 3]) (of_list [1; 10])
|> to_list |> List.sort Stdlib.compare = [2; 3; 11; 30];;

22
tests/core/t_set.ml Normal file
View file

@ -0,0 +1,22 @@
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
module S = CCSet.Make(struct
type t = int
let compare x y = Stdlib.compare x y
end);;
eq ~printer:(fun s -> s)
(S.to_string string_of_int (S.of_list [4; 3])) "3,4";;
q Q.(list int) (fun l ->
let s = S.of_list l in
(S.to_string string_of_int s)
= (CCList.sort_uniq ~cmp:CCInt.compare l
|> List.map string_of_int |> String.concat ","));;
q Q.(list int) (fun l ->
let s = S.of_list l in
(S.to_string ~sep:" " string_of_int s)
= (CCList.sort_uniq ~cmp:CCInt.compare l
|> List.map string_of_int |> String.concat " "));;

80
tests/core/t_sexp.ml Normal file
View file

@ -0,0 +1,80 @@
open CCSexp
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
t @@ fun () -> CCResult.to_opt (parse_string "(abc d/e/f \"hello \\\" () world\" )") <> None;;
t @@ fun () -> CCResult.to_opt (parse_string "(abc ( d e ffff ) \"hello/world\")") <> None;;
t @@ fun () -> CCResult.to_opt (parse_string "\"\123\bcoucou\"") <> None;;
let eq' = eq ~printer:(function Ok x -> to_string x | Error e -> "error " ^ e);;
eq' (parse_string "(a b)") (Ok (`List [`Atom "a"; `Atom "b"]));;
eq' (parse_string "(a\n ;coucou\n b)") (Ok (`List [`Atom "a"; `Atom "b"]));;
eq' (parse_string "(a #; (foo bar\n (1 2 3)) b)") (Ok (`List [`Atom "a"; `Atom "b"]));;
eq' (parse_string "#; (a b) (c d)") (Ok (`List [`Atom "c"; `Atom "d"]));;
eq' (parse_string "#; (a b) 1") (Ok (`Atom "1"));;
let eq' = eq ~printer:(function Ok x -> String.concat ";" @@ List.map to_string x | Error e -> "error " ^ e) ;;
eq' (parse_string_list "(a b)(c)") (Ok [`List [`Atom "a"; `Atom "b"]; `List [`Atom "c"]]);;
eq' (parse_string_list " ") (Ok []);;
eq' (parse_string_list "(a\n ;coucou\n b)") (Ok [`List [`Atom "a"; `Atom "b"]]);;
eq' (parse_string_list "#; (a b) (c d) e ") (Ok [`List [`Atom "c"; `Atom "d"]; `Atom "e"]);;
eq' (parse_string_list "#; (a b) 1") (Ok [`Atom "1"]);;
let sexp_bijective s = to_string s |> parse_string = Ok s;;
eq ~printer:CCFormat.(to_string (Dump.result pp))
(Ok (`List [`Atom ""])) (parse_string "(\"\")");;
t @@ fun () -> sexp_bijective (`List [`Atom ""]);;
let sexp_gen =
let mkatom a = `Atom a and mklist l = `List l in
let atom = Q.Gen.(map mkatom (string_size ~gen:printable (1 -- 30))) in
let gen = Q.Gen.(
sized (fix
(fun self n st -> match n with
| 0 -> atom st
| _ ->
frequency
[ 1, atom
; 2, map mklist (list_size (0 -- 10) (self (n/10)))
] st
)
)) in
let rec small = function
| `Atom s -> String.length s
| `List l -> List.fold_left (fun n x->n+small x) 0 l
and print = function
| `Atom s -> Printf.sprintf "`Atom \"%s\"" s
| `List l -> "`List " ^ Q.Print.list print l
and shrink = function
| `Atom s -> Q.Iter.map mkatom (Q.Shrink.string s)
| `List l -> Q.Iter.map mklist (Q.Shrink.list ~shrink l)
in
Q.make ~print ~small ~shrink gen;;
q ~count:100 sexp_gen sexp_bijective;;
(* regression for #338 *)
t @@ fun () ->
Printexc.record_backtrace true;
let cases = [
"\"\\256\"";
"\"\\722\02622222\\\\\n\r<\\\\\\\\\"\\222222222\\\\\"\"\2032!2222\\\\\"\"";
"\"\n\r<\\t\023\n\203\\622222222\\\\\"\"\2032!2222\\\\\"\"";
"\"\n\r<@t\023\n\203\\2222D2\n\r22222\01622222222222222222222222\203\\292242\222 2\\\\\">K2";
"\"\n\r<\\t\023\n\203\\272222222\\\\\"\"\2032\0042222\\\\\"\"";
"\"\023\n\203\\5222\n\r<\\t\023\n\203\\52222222\\\\\"2\\\216\216\216\216\216\\\\\"\216\216\216\216\216\216\216\216\216222222222222222\147";
"\"\\722\02622222\\\\\n\r<\\\\\\\\\"\\222222222\\\\\"\"\2032!2222\\\\\"\"";
] in
cases
|> List.iter (fun s ->
try ignore (parse_string s);
with e ->
let st = Printexc.get_backtrace() in
print_endline @@ Printexc.to_string e ^ "\n" ^ st;
assert false);
true;;

264
tests/core/t_string.ml Normal file
View file

@ -0,0 +1,264 @@
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
open CCString;;
open CCShims_.Stdlib;;
q Q.printable_string (fun s -> s = rev (rev s));;
q Q.printable_string (fun s -> length s = length (rev s));;
q Q.printable_string (fun s -> rev s = (to_list s |> List.rev |> of_list));;
eq "abc" (rev "cba");;
eq "" (rev "");;
eq " " (rev " ");;
let eq' = eq ~printer:string_of_int;;
eq' 1 (find ~sub:"bc" "abcd");;
eq' ~-1 (find ~sub:"bc" "abd");;
eq' 1 (find ~sub:"a" "_a_a_a_");;
eq' 6 (find ~start:5 ~sub:"a" "a1a234a");;
q ~count:10_000
Q.(pair printable_string printable_string) (fun (s1,s2) ->
let i = find ~sub:s2 s1 in
i < 0 || String.sub s1 i (length s2) = s2);;
let eq' = eq ~printer:Q.Print.(list int);;
eq' [1; 6] (find_all_l ~sub:"bc" "abc aabc aab");;
eq' [] (find_all_l ~sub:"bc" "abd");;
eq' [76] (find_all_l ~sub:"aaaaaa"
"aabbaabbaaaaabbbbabababababbbbabbbabbaaababbbaaabaabbaabbaaaabbababaaaabbaabaaaaaabbbaaaabababaabaaabbaabaaaabbababbaabbaaabaabbabababbbaabababaaabaaababbbaaaabbbaabaaababbabaababbaabbaaaaabababbabaababbbaaabbabbabababaaaabaaababaaaaabbabbaabbabbbbbbbbbbbbbbaabbabbbbbabbaaabbabbbbabaaaaabbababbbaaaa");;
t @@ fun () -> mem ~sub:"bc" "abcd";;
t @@ fun () -> not (mem ~sub:"a b" "abcd");;
let eq' = eq ~printer:string_of_int ;;
eq' 1 (rfind ~sub:"bc" "abcd");;
eq' ~-1 (rfind ~sub:"bc" "abd");;
eq' 5 (rfind ~sub:"a" "_a_a_a_");;
eq' 4 (rfind ~sub:"bc" "abcdbcd");;
eq' 6 (rfind ~sub:"a" "a1a234a");;
q ~count:10_000
Q.(pair printable_string printable_string) (fun (s1,s2) ->
let i = rfind ~sub:s2 s1 in
i < 0 || String.sub s1 i (length s2) = s2);;
eq ~printer:CCFun.id (replace ~which:`All ~sub:"a" ~by:"b" "abcdabcd") "bbcdbbcd";;
eq ~printer:CCFun.id (replace ~which:`Left ~sub:"a" ~by:"b" "abcdabcd") "bbcdabcd";;
eq ~printer:CCFun.id (replace ~which:`Right ~sub:"a" ~by:"b" "abcdabcd") "abcdbbcd";;
eq ~printer:CCFun.id (replace ~which:`All ~sub:"ab" ~by:"hello" " abab cdabb a")
" hellohello cdhellob a";;
eq ~printer:CCFun.id (replace ~which:`Left ~sub:"ab" ~by:"nope" " a b c d ") " a b c d ";;
eq ~printer:CCFun.id (replace ~sub:"a" ~by:"b" "1aa234a") "1bb234b";;
t @@ fun () -> Split.list_cpy ~by:"," "aa,bb,cc" = ["aa"; "bb"; "cc"];;
t @@ fun () -> Split.list_cpy ~by:"--" "a--b----c--" = ["a"; "b"; ""; "c"; ""];;
t @@ fun () -> Split.list_cpy ~by:" " "hello world aie" = ["hello"; ""; "world"; "aie"];;
t @@ fun () -> Split.left ~by:" " "ab cde f g " = Some ("ab", "cde f g ");;
t @@ fun () -> Split.left ~by:"__" "a__c__e_f" = Some ("a", "c__e_f");;
t @@ fun () -> Split.left ~by:"_" "abcde" = None;;
t @@ fun () -> Split.left ~by:"bb" "abbc" = Some ("a", "c");;
t @@ fun () -> Split.left ~by:"a_" "abcde" = None;;
t @@ fun () -> Split.right ~by:" " "ab cde f g" = Some ("ab cde f", "g");;
t @@ fun () -> Split.right ~by:"__" "a__c__e_f" = Some ("a__c", "e_f");;
t @@ fun () -> Split.right ~by:"_" "abcde" = None;;
t @@ fun () -> Split.right ~by:"a_" "abcde" = None;;
eq ~printer:Q.Print.(list string)
["a"; "few"; "words"; "from"; "our"; "sponsors"]
(split_on_char ' ' "a few words from our sponsors");;
q Q.(printable_string) (fun s ->
let s = split_on_char ' ' s |> String.concat " " in
s = (split_on_char ' ' s |> String.concat " "));;
t @@ fun () -> compare_versions "0.1.3" "0.1" > 0;;
t @@ fun () -> compare_versions "10.1" "2.0" > 0;;
t @@ fun () -> compare_versions "0.1.alpha" "0.1" > 0;;
t @@ fun () -> compare_versions "0.3.dev" "0.4" < 0;;
t @@ fun () -> compare_versions "0.foo" "0.0" < 0;;
t @@ fun () -> compare_versions "1.2.3.4" "01.2.4.3" < 0;;
q Q.(pair printable_string printable_string) (fun (a,b) ->
CCOrd.equiv (compare_versions a b) (CCOrd.opp compare_versions b a));;
t @@ fun () -> compare_natural "foo1" "foo2" < 0;;
t @@ fun () -> compare_natural "foo11" "foo2" > 0;;
t @@ fun () -> compare_natural "foo11" "foo11" = 0;;
t @@ fun () -> compare_natural "foo011" "foo11" = 0;;
t @@ fun () -> compare_natural "foo1a" "foo1b" < 0;;
t @@ fun () -> compare_natural "foo1a1" "foo1a2" < 0;;
t @@ fun () -> compare_natural "foo1a17" "foo1a2" > 0;;
q Q.(pair printable_string printable_string) (fun (a,b) ->
CCOrd.opp compare_natural a b = compare_natural b a);;
q Q.(printable_string) (fun a -> compare_natural a a = 0);;
q Q.(triple printable_string printable_string printable_string) (fun (a,b,c) ->
if compare_natural a b < 0 && compare_natural b c < 0
then compare_natural a c < 0 else Q.assume_fail());;
q Q.(string_of_size Gen.(0 -- 30)) (fun s ->
edit_distance s s = 0);;
q Q.(let p = string_of_size Gen.(0 -- 20) in pair p p) (fun (s1,s2) ->
edit_distance s1 s2 = edit_distance s2 s1);;
q Q.(let p = string_of_size Gen.(0 -- 20) in pair p p) (fun (s1,s2) ->
let e = edit_distance s1 s2 in
let e' = edit_distance ~cutoff:3 s1 s2 in
(if e' < 3 then e=e' else e >= 3) &&
(if e <= 3 then e=e' else true));;
eq ~printer:string_of_int 2 (edit_distance "hello" "helo!");;
eq ~printer:string_of_int 5 (edit_distance "abcde" "tuvwx");;
eq ~printer:string_of_int 2 (edit_distance ~cutoff:2 "abcde" "tuvwx");;
eq ~printer:string_of_int 1
(edit_distance ("a" ^ String.make 100 '_') ("b"^String.make 100 '_'));;
eq ~printer:string_of_int 1
(edit_distance ~cutoff:4 ("a" ^ String.make 1000 '_') ("b"^String.make 1000 '_'));;
eq ~printer:string_of_int 2
(edit_distance ~cutoff:3 ("a" ^ String.make 1000 '_' ^ "c")
("b" ^ String.make 1000 '_' ^ "d"));;
(* test that building a from s, and mutating one char of s, yields
a string s' that is accepted by a.
--> generate triples (s, i, c) where c is a char, s a non empty string
and i a valid index in s.
*)
q (
let gen = Q.Gen.(
3 -- 10 >>= fun len ->
0 -- (len-1) >>= fun i ->
string_size (return len) >>= fun s ->
char >|= fun c -> (s,i,c)
) in
let small (s,_,_) = String.length s in
Q.make ~small gen
)
(fun (s,i,c) ->
let s' = Bytes.of_string s in
Bytes.set s' i c;
edit_distance s (Bytes.to_string s') <= 1)
;;
t @@ fun () -> prefix ~pre:"aab" "aabcd";;
t @@ fun () -> not (prefix ~pre:"ab" "aabcd");;
t @@ fun () -> not (prefix ~pre:"abcd" "abc");;
t @@ fun () -> prefix ~pre:"abc" "abcde";;
t @@ fun () -> prefix ~pre:"" "";;
t @@ fun () -> prefix ~pre:"" "abc";;
t @@ fun () -> prefix ~pre:"abc" "abc";;
t @@ fun () -> suffix ~suf:"cd" "abcd";;
t @@ fun () -> suffix ~suf:"" "";;
t @@ fun () -> suffix ~suf:"" "abc";;
t @@ fun () -> not (suffix ~suf:"cd" "abcde");;
t @@ fun () -> not (suffix ~suf:"abcd" "cd");;
eq ("ab", "cd") (take_drop 2 "abcd");;
eq ("abc", "") (take_drop 3 "abc");;
eq ("abc", "") (take_drop 5 "abc");;
let eq' = eq ~printer:Q.Print.(option string);;
eq' (Some "ab") (chop_suffix ~suf:"cd" "abcd");;
eq' None (chop_suffix ~suf:"cd" "abcde");;
eq' None (chop_suffix ~suf:"abcd" "cd");;
eq' (Some "cd") (chop_prefix ~pre:"aab" "aabcd");;
eq' None (chop_prefix ~pre:"ab" "aabcd");;
eq' None (chop_prefix ~pre:"abcd" "abc");;
let eq' = eq ~printer:Q.Print.string;;
eq' " 42" (pad 4 "42");;
eq' "0042" (pad ~c:'0' 4 "42");;
eq' "4200" (pad ~side:`Right ~c:'0' 4 "42");;
eq' "hello" (pad 4 "hello");;
eq' "aaa" (pad ~c:'a' 3 "");;
eq' "aaa" (pad ~side:`Right ~c:'a' 3 "");;
t @@ fun () -> of_list ['a'; 'b'; 'c'] = "abc";;
t @@ fun () -> of_list [] = "";;
let eq' = eq ~printer:Q.Print.(list @@ Printf.sprintf "%S");;
eq' ["ab"; "c"] (lines "ab\nc");;
eq' ["ab"; "c"] (lines "ab\nc\n");;
eq' [] (lines "");;
eq' [""] (lines "\n");;
eq' [""; "a"] (lines "\na");;
q Q.(printable_string) (fun s ->
lines s = (lines_gen s |> Gen.to_list));;
q Q.(printable_string) (fun s ->
lines s = (lines_iter s |> Iter.to_list));;
q Q.(small_list printable_string) (fun l ->
concat_iter ~sep:"\n" (Iter.of_list l) = concat "\n" l);;
q Q.(small_list printable_string) (fun l ->
concat_gen ~sep:"\n" (Gen.of_list l) = concat "\n" l);;
q Q.(small_list printable_string) (fun l ->
concat_seq ~sep:"\n" (CCSeq.of_list l) = concat "\n" l);;
eq ~printer:CCFun.id "" (unlines []);;
eq ~printer:CCFun.id "ab\nc\n" (unlines ["ab"; "c"]);;
q Q.printable_string (fun s -> trim (unlines (lines s)) = trim s);;
q Q.printable_string (fun s -> trim (unlines_gen (lines_gen s)) = trim s);;
q Q.(small_list small_string) (fun l ->
let l = unlines l |> lines in
l = (unlines l |> lines));;
t @@ fun () -> set "abcd" 1 '_' = "a_cd";;
t @@ fun () -> set "abcd" 0 '-' = "-bcd";;
t @@ fun () -> (try ignore (set "abc" 5 '_'); false with Invalid_argument _ -> true);;
eq ~printer:Q.Print.string
"bcef" (filter_map
(function 'c' -> None | c -> Some (Char.chr (Char.code c + 1))) "abcde");;
eq ~printer:Q.Print.string
"abde" (filter (function 'c' -> false | _ -> true) "abcdec");;
q Q.printable_string (fun s -> filter (fun _ -> true) s = s);;
eq ~printer:Q.Print.string
"abcde" (uniq CCShims_.Stdlib.(=) "abbccdeeeee");;
eq ~printer:CCFun.id "abc " (ltrim " abc ");;
eq ~printer:CCFun.id " abc" (rtrim " abc ");;
q Q.(printable_string) (fun s ->
String.trim s = (s |> ltrim |> rtrim));;
q Q.(printable_string) (fun s -> ltrim s = ltrim (ltrim s));;
q Q.(printable_string) (fun s -> rtrim s = rtrim (rtrim s));;
q Q.(printable_string) (fun s ->
let s' = ltrim s in
if s'="" then Q.assume_fail() else s'.[0] <> ' ');;
q Q.(printable_string) (fun s ->
let s' = rtrim s in
if s'="" then Q.assume_fail() else s'.[String.length s'-1] <> ' ');;
t @@ fun () -> equal_caseless "foo" "FoO";;
t @@ fun () -> equal_caseless "helLo" "HEllO";;
q Q.(pair printable_string printable_string) (fun (s1,s2) ->
equal_caseless s1 s2 = (lowercase_ascii s1=lowercase_ascii s2));;
q Q.(printable_string) (fun s -> equal_caseless s s);;
q Q.(printable_string) (fun s -> equal_caseless (uppercase_ascii s) s);;
let eq' = eq ~printer:(Printf.sprintf "%S");;
eq' "0068656c6c6f20776f726c64" (to_hex "\000hello world");;
eq' "" (to_hex "");;
eq' "\000hello world" (of_hex_exn "0068656c6c6f20776f726c64");;
eq' "hello world" (of_hex_exn "68656C6C6F20776F726C64");;
q Q.(string) (fun s ->
of_hex_exn (to_hex s) = s);;
q Q.(string) (fun s ->
CCString.for_all (function 'A'..'F'|'a'..'f'|'0'..'9' -> true | _ -> false) @@ to_hex s);;
t @@ fun () -> "ab" < "abc";;
t @@ fun () -> "123" < "14";;

48
tests/core/t_unix.ml Normal file
View file

@ -0,0 +1,48 @@
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
open CCUnix;;
t @@ fun () -> escape_str "foo" = "foo";;
t @@ fun () -> escape_str "foo bar" = "'foo bar'";;
t @@ fun () -> escape_str "fo'o b'ar" = "'fo'\\''o b'\\''ar'";;
t @@ fun () -> call_full ~stdin:(`Str "abc") "cat" |> stdout = "abc";;
t @@ fun () -> call_full "echo %s" (escape_str "a'b'c") |> stdout = "a'b'c\n";;
t @@ fun () -> call_full "echo %s" "a'b'c" |> stdout = "abc\n";;
t @@ fun () -> call_stdout ~stdin:(`Str "abc") "cat" = "abc";;
t @@ fun () -> call_stdout "echo %s" (escape_str "a'b'c") = "a'b'c\n";;
t @@ fun () -> call_stdout "echo %s" "a'b'c" = "abc\n";;
t @@ fun () ->
let m = 200 in
let n = 50 in
let write_atom filename s =
with_file_lock ~kind:`Write filename
(fun () ->
CCIO.with_out ~flags:[Open_append; Open_creat]
filename (fun oc -> output_string oc s; flush oc))
in
let f filename =
for _j=1 to m do
write_atom filename "foo\n"
done
in
CCIO.File.with_temp ~prefix:"containers_" ~suffix:".txt"
(fun filename ->
let a = Array.init n (fun _ -> Thread.create f filename) in
Array.iter Thread.join a;
let lines = CCIO.with_in filename CCIO.read_lines_l in
assert_equal ~printer:string_of_int (n * m) (List.length lines);
assert (List.for_all ((=) "foo") lines));
true;;
t @@ fun () ->
let filename = with_temp_dir "test_containers"
(fun dir ->
let name = Filename.concat dir "test" in
CCIO.with_out name (fun oc -> output_string oc "content"; flush oc);
assert (Sys.file_exists name);
name)
in
assert (not (Sys.file_exists filename));
true;;

162
tests/core/t_utf8string.ml Normal file
View file

@ -0,0 +1,162 @@
open CCUtf8_string
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
eq ~cmp:(=) ~printer:Q.Print.(list (fun c -> string_of_int@@ Uchar.to_int c))
(to_list (of_string_exn "aébõ😀")) (to_seq (of_string_exn "aébõ😀") |> CCList.of_seq);;
(* make sure it's persisted correctly *)
t @@ fun () ->
let s = (of_string_exn "aébõ😀") in
let seq = to_seq s in
let l = to_list s in
let testeq seq = assert_equal ~cmp:(=) l (CCList.of_seq seq) in
testeq seq;
testeq seq;
testeq seq;
true;;
let printer s = String.escaped (to_string s)
let pp_uchar (c:Uchar.t) = Printf.sprintf "0x%x" (Uchar.to_int c)
let arb_uchar =
let rec gen = lazy (
let open Q.Gen in
Q.Gen.int_range Uchar.(to_int min) Uchar.(to_int max) >>= fun n ->
try return (Uchar.of_int n)
with _ -> Lazy.force gen
) in
Q.make
~print:(fun c -> Printf.sprintf "<uchar '%d'>" (Uchar.to_int c))
(Lazy.force gen)
let uutf_is_valid s =
try
Uutf.String.fold_utf_8
(fun () _ -> function
| `Malformed _ -> raise Exit
| `Uchar _ -> ())
() s;
true
with Exit ->
false
let uutf_to_iter s f =
Uutf.String.fold_utf_8
(fun () _ -> function
| `Malformed _ -> f (Uchar.of_int 0xfffd)
| `Uchar c -> f c)
() s
let uutf_of_l l =
let buf = Buffer.create 32 in
List.iter (Uutf.Buffer.add_utf_8 buf) l;
Buffer.contents buf;;
t @@ fun () ->
let s = of_string_exn "このため、" in
let s' = to_iter s |> of_iter in
assert_equal ~cmp:equal ~printer s s';
true;;
q Q.small_string (fun s ->
Q.assume (CCString.for_all (fun c -> Char.code c < 128) s);
is_valid s);;
q ~long_factor:10
Q.small_string (fun s ->
Q.assume (CCString.for_all (fun c -> Char.code c < 128) s);
s = (of_string_exn s |> to_iter|> of_iter|> to_string)
);;
q ~long_factor:10
Q.string (fun s ->
Q.assume (CCString.for_all (fun c -> Char.code c < 128) s);
String.length s = List.length (of_string_exn s |> to_list)
);;
q ~long_factor:10 ~count:20_000
Q.(small_list arb_uchar) (fun l ->
let s = of_list l in
l = to_list s);;
q ~long_factor:10
Q.(small_list arb_uchar) (fun l ->
let s = of_list l in
l = (to_list @@ of_gen @@ to_gen s)
);;
q ~long_factor:10
Q.(small_list arb_uchar) (fun l ->
let s = of_list l in
l = (to_list @@ of_iter @@ to_iter s)
);;
t @@ fun () -> not (is_valid "\192\181");;
t @@ fun () -> not (is_valid "\193\143");;
t @@ fun () -> not (is_valid "\224\151\167");;
t @@ fun () -> not (is_valid "\224\137\165");;
t @@ fun () -> is_valid "\240\151\189\163";;
q ~long_factor:40
Q.string (fun s ->
Q.assume (is_valid s);
let s = of_string_exn s in
let s2 = s |> to_iter|> of_iter in
if s=s2 then true
else Q.Test.fail_reportf "s=%S, s2=%S" (to_string s)(to_string s2)
);;
q ~long_factor:40
Q.string (fun s ->
Q.assume (is_valid s);
let s = of_string_exn s in
let s2 = s |> to_gen |> of_gen in
if s=s2 then true
else Q.Test.fail_reportf "s=%S, s2=%S" (to_string s)(to_string s2)
);;
(* compare with uutf *)
q ~long_factor:40 ~count:50_000
Q.small_string (fun s ->
let v1 = is_valid s in
let v2 = uutf_is_valid s in
if v1=v2 then true
else Q.Test.fail_reportf "s:%S, valid: %B, uutf_valid: %B" s v1 v2
);;
q ~long_factor:40 ~count:50_000
Q.(small_list arb_uchar) (fun l ->
let pp s = Q.Print.(list pp_uchar) s in
let uutf = uutf_of_l l in
let s = (of_list l:>string) in
if uutf = s then true
else Q.Test.fail_reportf "l: '%s', uutf: '%s', containers: '%s'"
(pp l) uutf s
);;
q ~long_factor:40 ~count:50_000
Q.small_string (fun s ->
Q.assume (is_valid s && uutf_is_valid s);
let pp s = Q.Print.(list pp_uchar) s in
let l_uutf = uutf_to_iter s |> Iter.to_list in
let l_co = of_string_exn s |> to_iter |> Iter.to_list in
if l_uutf = l_co then true
else Q.Test.fail_reportf "uutf: '%s', containers: '%s', is_valid %B, uutf_is_valid %B"
(pp l_uutf) (pp l_co) (is_valid s) (uutf_is_valid s)
);;
t @@ fun () ->
for i = 0 to 127 do
let c = Uchar.of_int i in
assert_equal 1 (n_bytes (of_list [c]))
done;
true ;;
q Q.(small_list arb_uchar) (fun l ->
of_list l = concat empty (List.map of_uchar l));;
q Q.(pair small_nat arb_uchar) (fun (i,c) ->
make i c = concat empty (CCList.init i (fun _ -> of_uchar c)));;

361
tests/core/t_vector.ml Normal file
View file

@ -0,0 +1,361 @@
module T = (val Containers_testlib.make ~__FILE__ ())
include T;;
open CCVector;;
t @@ fun () -> (create_with ~capacity:200 1 |> capacity) >= 200;;
t @@ fun () -> return 42 |> to_list = [42];;
t @@ fun () -> return 42 |> length = 1;;
t @@ fun () ->
let v = create_with ~capacity:10 1 in
ensure v 200;
capacity v >= 200;;
t @@ fun () -> let v = create() in push v 0.; push v 1.; push v 2.; 3=length v;;
t @@ fun () -> let v = create() in push v 1.; push v 2.; push v 3.;
6. = (get v 0 +. get v 1 +. get v 2);;
t @@ fun () -> let v = create() in push v 0; push v 1; push v 2; 3=length v;;
t @@ fun () -> let v = create() in push v 1; push v 2; push v 3;
6 = (get v 0 + get v 1 + get v 2);;
t @@ fun () -> let v = create() in push v "a"; push v "b"; push v "c"; 3=length v;;
t @@ fun () -> let v = create() in push v "a"; push v "b"; push v "c";
"abc" = String.concat "" (to_list v);;
t @@ fun () ->
let v = create() in
push v 0.; push v 1.;
clear v;
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
truncate v 2;
assert_equal 1. (fold (+.) 0. v);
clear v;
assert_equal 0 (size v);
push v 0.; push v 1.; push v 7.; push v 10.; push v 12.;
assert_equal (1. +. 7. +. 10. +. 12.) (fold (+.) 0. v);
true;;
t @@ fun () ->
let v = of_iter Iter.(1 -- 10) in
assert_equal 10 (size v);
clear v;
assert_equal 0 (size v);
assert (Iter.is_empty (to_iter v));
true;;
t @@ fun () -> let v = create () in push v 1; to_list v = [1];;
t @@ fun () -> let v = of_list [1;2;3] in push v 4; to_list v = [1;2;3;4];;
t @@ fun () -> let v = make 1 0 in resize_with v (fun i -> i) 5; to_list v = [0;1;2;3;4];;
t @@ fun () -> let v = make 1 0 in resize_with v (fun i -> i) 5; CCList.length (to_list v) = 5;;
t @@ fun () -> let v = create_with ~capacity:2 0 in resize_with v (fun i -> i) 5; to_list v = [0;1;2;3;4];;
t @@ fun () -> let v = make 5 0 in resize_with v (fun i -> i) 5; to_list v = [0;0;0;0;0];;
t @@ fun () -> let v = make 5 0 in resize_with v (fun i -> i) 6; to_list v = [0;0;0;0;0;5];;
t @@ fun () -> let v = make 5 0 in
try resize_with v (fun i -> i) (-1); false
with Invalid_argument _ -> true;;
t @@ fun () -> let v = make 5 0 in resize_with v (fun i -> i) 5; List.length (to_list v) = 5;;
t @@ fun () -> let v = make 1 0 in resize_with_init v ~init:1 5; to_list v = [0;1;1;1;1];;
t @@ fun () -> let v = make 1 0 in resize_with_init v ~init:1 5; List.length (to_list v) = 5;;
t @@ fun () ->
let v = create_with ~capacity:2 0 in
resize_with_init v ~init:1 5; to_list v = [1;1;1;1;1];;
t @@ fun () -> let v = make 5 0 in resize_with_init v ~init:1 5; to_list v = [0;0;0;0;0];;
t @@ fun () -> let v = make 3 0 in resize_with_init v ~init:1 5; to_list v = [0;0;0;1;1];;
t @@ fun () -> let v = make 5 0 in
try resize_with_init v ~init:1 (-1); false
with Invalid_argument _ -> true;;
t @@ fun () -> let v = make 5 0 in resize_with_init v ~init:1 5; List.length (to_list v) = 5;;
(* test for asymptotic behavior *)
t @@ fun () -> let v =make 1 0 in
for i=0 to 100_000 do resize_with_init v ~init:10 i; done; true;;
t @@ fun () -> let v1 = init 5 (fun i->i) and v2 = init 5 (fun i->i+5) in
append v1 v2; to_list v1 = CCList.(0--9);;
t @@ fun () -> let empty = create () and v2 = init 5 (fun i->i) in
append empty v2; to_list empty = CCList.(0--4);;
t @@ fun () -> let v1 = init 5 (fun i->i) and empty = create () in
append v1 empty; to_list v1 = CCList.(0--4);;
t @@ fun () -> let v = init 3 (fun i->i) in
append v v; to_list v = [0; 1; 2; 0; 1; 2];;
t @@ fun () -> let empty = create () in
append empty empty; to_list empty = [];;
t @@ fun () ->
let a = of_iter Iter.(1 -- 5) in
let b = of_iter Iter.(6 -- 10) in
append a b;
assert_equal 10 (size a);
assert_equal (Iter.to_array Iter.(1 -- 10)) (to_array a);
assert_equal (Iter.to_array Iter.(6 -- 10)) (to_array b);
true;;
q Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l ->
let v1 = of_list l and v2 = of_list l in
remove_and_shift v1 9;
remove_unordered v2 9;
to_list v1 = (to_list v2));;
q Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l ->
let l = List.sort CCInt.compare l in
let v = of_list l in
remove_and_shift v 3;
to_list v = (List.sort CCInt.compare (to_list v)));;
q Q.(list_of_size (Gen.int_range 10 10) small_int) (fun l ->
let l = List.sort CCInt.compare l in
let v1 = of_list l and v2 = of_list l in
remove_and_shift v1 3;
remove_unordered v2 3;
to_list v1 = (List.sort CCInt.compare (to_list v2)));;
t @@ fun () -> let v = (1 -- 5) in insert v 3 9; to_list v = [1;2;3;9;4;5];;
t @@ fun () -> let v = create () in insert v 0 2; to_list v = [2];;
t @@ fun () -> let v = (1 -- 3) in remove_and_shift v 1; insert v 1 5; to_list v = [1;5;3];;
t @@ fun () -> let v = (1 -- 3) in remove_and_shift v 0; insert v 2 5; to_list v = [2;3;5];;
t @@ fun () -> let v = (1 -- 3) in insert v 3 5; to_list v = [1;2;3;5];;
t @@ fun () ->
let v1 = init 5 (fun i->i) and v2 = Array.init 5 (fun i->i+5) in
append_array v1 v2; to_list v1 = CCList.(0--9);;
t @@ fun () -> let empty = create () in
append_array empty CCArray.(0--5); to_list empty = CCList.(0--5);;
t @@ fun () -> let v1 = init 5 (fun i->i) in
append_array v1 [| |]; to_list v1 = CCList.(0--4);;
t @@ fun () -> let empty = create () in
append_array empty [| |]; to_list empty = [];;
q Q.(pair (list int)(list int)) (fun (l1,l2) ->
let v = of_list l1 in append_list v l2;
to_list v = (l1 @ l2)) ;;
q Q.(pair (list int)(list int)) (fun (l1,l2) ->
let v = of_list l1 in append_list v l2;
length v = List.length l1 + List.length l2);;
q Q.(pair (list int)(list int)) (fun (l1,l2) ->
let v = of_list l1 in append_gen v (Gen.of_list l2);
to_list v = (l1 @ l2));;
q Q.(pair (list int)(list int)) (fun (l1,l2) ->
let v = of_list l1 in append_gen v (Gen.of_list l2);
length v = List.length l1 + List.length l2);;
let gen x =
let small = length in
let print = CCOption.map (fun p x -> Q.Print.list p (CCVector.to_list x)) x.Q.print in
Q.make ?print ~small Q.Gen.(list x.Q.gen >|= of_list);;
q (Q.pair (gen Q.int) (gen Q.int)) (fun (v1,v2) ->
let l1 = to_list v1 in
append v1 v2;
Iter.to_list (to_iter v1) =
Iter.(to_list (append (of_list l1) (to_iter v2)))
);;
t @@ fun () -> equal (=) (create ()) (create ());;
t @@ fun () -> equal (=) (return 42) (return 42);;
t @@ fun () -> not (equal (=) (create ()) (return 42));;
t @@ fun () -> not (equal (=) (return 42) (create ()));;
q Q.(let g = list_of_size Gen.(0--10) small_int in pair g g) (fun (l1,l2) ->
equal (=) (of_list l1) (of_list l2) = (l1=l2));;
q Q.(pair (small_list small_int)(small_list small_int)) (fun (l1,l2) ->
let v1 = of_list l1 in
let v2 = of_list l2 in
equal (=) v1 v2 = (l1=l2));;
q Q.(pair (small_list small_int)(small_list small_int)) (fun (l1,l2) ->
let v1 = of_list l1 in
let v2 = of_list l2 in
compare Stdlib.compare v1 v2 = CCList.compare Stdlib.compare l1 l2) ;;
t @@ fun () -> 1 -- 10 |> top = Some 10;;
t @@ fun () -> create () |> top = None;;
t @@ fun () -> 1 -- 10 |> top_exn = 10;;
t @@ fun () -> (let v = of_list [1;2;3] in let v' = copy v in to_list v' = [1;2;3]);;
t @@ fun () -> create () |> copy |> is_empty;;
t @@ fun () ->
let v = of_iter Iter.(1 -- 100) in
assert_equal 100 (size v);
let v' = copy v in
assert_equal 100 (size v');
clear v';
assert (is_empty v');
assert (not (is_empty v));
true;;
q Q.(small_list small_int) (fun l ->
let v = of_list l in
let v' = copy v in
equal (=) v v');;
t @@ fun () ->
let v = of_iter Iter.(1 -- 10) in
truncate v 5;
assert_equal [1;2;3;4;5] (to_list v);
true ;;
q (gen Q.small_int) (fun v ->
let n = size v / 2 in
let l = to_list v in
let h = Iter.(to_list (take n (of_list l))) in
let v' = copy v in
truncate v' n;
h = to_list v'
) ;;
q (gen Q.small_int) (fun v ->
let v' = copy v in
shrink_to_fit v;
to_list v = to_list v'
) ;;
q (gen Q.small_int) (fun v ->
let v' = copy v in
sort' Stdlib.compare v';
let l = to_list v' in
List.sort Stdlib.compare l = l
);;
t @@ fun () -> let v = of_list [1;4;5;3;2;4;1] in
uniq_sort Stdlib.compare v; to_list v = [1;2;3;4;5];;
q ~long_factor:10
Q.(small_list small_int) (fun l ->
let v = of_list l in
uniq_sort Stdlib.compare v;
to_list v = (CCList.sort_uniq ~cmp:Stdlib.compare l));;
t @@ fun () -> let v = (0--6) in
iteri (fun i _ -> if i = 3 then remove_unordered v i) v; length v = 6;;
t @@ fun () ->
let v = create() in push v 1; push v 2; push v 3;
to_list (map string_of_int v) = ["1"; "2"; "3"];;
q Q.(pair (fun1 Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (map f v) = List.map f l);;
t @@ fun () ->
let v = create() in push v 1; push v 2; push v 3;
to_list (mapi (fun i e -> Printf.sprintf "%i %i" i e) v) = ["0 1"; "1 2"; "2 3"];;
q Q.(pair (fun2 Observable.int Observable.int small_int) (small_list small_int))
(fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (mapi f v) = List.mapi f l);;
q Q.(pair (fun1 Observable.int small_int) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
map_in_place f v;
to_list v = List.map f l);;
t @@ fun () ->
let v = 1 -- 10 in filter_in_place (fun x->x<4) v;
to_list v = [1;2;3];;
q Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
filter_in_place f v;
to_list v = List.filter f l) ;;
t @@ fun () -> filter (fun x-> x mod 2=0) (of_list [1;2;3;4;5]) |> to_list = [2;4];;
t @@ fun () -> filter (fun x-> x mod 2=0) (1 -- 1_000_000) |> length = 500_000;;
q Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (filter f v) = List.filter f l);;
t @@ fun () -> fold (+) 0 (of_list [1;2;3;4;5]) = 15;;
t @@ fun () -> fold (+) 0 (create ()) = 0;;
q Q.(pair (fun2 Observable.int Observable.int small_int) (small_list small_int))
(fun (Q.Fun (_,f),l) ->
let v = of_list l in
fold f 0 v = List.fold_left f 0 l);;
q Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
exists f v = List.exists f l);;
q Q.(pair (fun1 Observable.int bool) (small_list small_int))
(fun (Q.Fun (_,f),l) ->
let v = of_list l in
for_all f v = List.for_all f l);;
q Q.(pair (fun1 Observable.int bool) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
find f v = CCList.find_pred f l);;
q Q.(list small_int) (fun l ->
let v = of_list l in
let f x = x>30 && x < 35 in
find_map (fun x -> if f x then Some x else None) v = find f v);;
q Q.(pair (fun1 Observable.int (option bool)) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
to_list (filter_map f v) = CCList.filter_map f l);;
q Q.(pair (fun1 Observable.int (option small_int)) (small_list small_int)) (fun (Q.Fun (_,f),l) ->
let v = of_list l in
filter_map_in_place f v;
to_list v = CCList.filter_map f l);;
(* check it frees memory properly *)
t @@ fun () ->
let s = "coucou" ^ "lol" in
let w = Weak.create 1 in
Weak.set w 0 (Some s);
let v = of_list ["a"; s] in
filter_in_place (fun s -> String.length s <= 1) v;
assert_equal 1 (length v);
assert_equal "a" (get v 0);
Gc.full_major();
assert_equal None (Weak.get w 0);
true;;
eq ~cmp:(=) ~printer:Q.Print.(list int)
[ 11; 12; 21; 22 ] (List.sort CCInt.compare @@
to_list @@ monoid_product (+) (of_list [10; 20]) (of_list [1; 2]));;
eq ~cmp:(=) ~printer:Q.Print.(list int)
[ 11; 12; 13; 14 ] (List.sort CCInt.compare @@
to_list @@ monoid_product (+) (of_list [10]) (of_list [1; 2; 3; 4]));;
q Q.(small_list small_int) (fun l ->
let v = of_list l in
rev_in_place v;
to_list v = List.rev l);;
t @@ fun () -> rev (of_list [1;2;3;4]) |> to_list = [4;3;2;1];;
t @@ fun () -> rev (of_list [1;2;3;4;5]) |> to_list = [5;4;3;2;1];;
t @@ fun () -> rev (create ()) |> to_list = [];;
q Q.(small_list small_int) (fun l ->
let v = of_list l in
to_list (rev v) = List.rev l);;
t @@ fun () -> let v = of_list [1;2;3] in (fun f->rev_iter f v) |> Iter.to_list = [3;2;1];;
q Q.(list int) (fun l ->
let v = of_list l in
(fun f->rev_iter f v) |> Iter.to_list = List.rev l);;
t @@ fun () -> of_iter Iter.(1 -- 10) |> to_list = CCList.(1 -- 10);;
q Q.(list int) (fun l ->
let v= of_list l in v |> to_iter_rev |> Iter.to_rev_list = l);;
t @@ fun () -> slice_iter (of_list [0;1;2;3;4]) 1 3 |> CCList.of_iter = [1;2;3];;
t @@ fun () -> slice_iter (of_list [0;1;2;3;4]) 1 4 |> CCList.of_iter = [1;2;3;4];;
t @@ fun () -> slice_iter (of_list [0;1;2;3;4]) 0 5 |> CCList.of_iter = [0;1;2;3;4];;
t @@ fun () -> (1 -- 4) |> to_list = [1;2;3;4];;
t @@ fun () -> (4 -- 1) |> to_list = [4;3;2;1];;
t @@ fun () -> (0 -- 0) |> to_list = [0];;
q Q.(pair small_int small_int) (fun (a,b) ->
(a -- b) |> to_list = CCList.(a -- b));;
q Q.(pair small_int small_int) (fun (a,b) ->
(a --^ b) |> to_list = CCList.(a --^ b));;
t @@ fun () -> of_list CCList.(1--300_000) |> to_list = CCList.(1--300_000);;
t @@ fun () -> let v = (1--10) in to_list v = Gen.to_list (to_gen v);;