mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2026-03-07 21:27:55 -05:00
332 lines
8.2 KiB
OCaml
332 lines
8.2 KiB
OCaml
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;;
|
|
|
|
(* Additional comprehensive tests for CCOption *)
|
|
|
|
(* Test map *)
|
|
eq (Some 2) (map (( + ) 1) (Some 1));;
|
|
eq None (map (( + ) 1) None);;
|
|
t @@ fun () -> map (fun x -> x * 2) (Some 5) = Some 10;;
|
|
|
|
(* Test map_or *)
|
|
eq 10 (map_or ~default:0 (fun x -> x * 2) (Some 5));;
|
|
eq 0 (map_or ~default:0 (fun x -> x * 2) None);;
|
|
t @@ fun () -> map_or ~default:"empty" String.uppercase_ascii (Some "hello") = "HELLO";;
|
|
t @@ fun () -> map_or ~default:"empty" String.uppercase_ascii None = "empty";;
|
|
|
|
(* Test map_lazy *)
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let result = map_lazy (fun () -> called := true; 0) (fun x -> x * 2) (Some 5) in
|
|
result = 10 && not !called
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let result = map_lazy (fun () -> called := true; 0) (fun x -> x * 2) None in
|
|
result = 0 && !called
|
|
;;
|
|
|
|
(* Test is_some and is_none *)
|
|
t @@ fun () -> is_some (Some 1);;
|
|
t @@ fun () -> not (is_some None);;
|
|
t @@ fun () -> is_none None;;
|
|
t @@ fun () -> not (is_none (Some 1));;
|
|
|
|
(* Test compare *)
|
|
t @@ fun () -> compare Int.compare (Some 1) (Some 1) = 0;;
|
|
t @@ fun () -> compare Int.compare (Some 1) (Some 2) < 0;;
|
|
t @@ fun () -> compare Int.compare (Some 2) (Some 1) > 0;;
|
|
t @@ fun () -> compare Int.compare None None = 0;;
|
|
t @@ fun () -> compare Int.compare None (Some 1) < 0;;
|
|
t @@ fun () -> compare Int.compare (Some 1) None > 0;;
|
|
|
|
(* Test equal *)
|
|
t @@ fun () -> equal Int.equal (Some 1) (Some 1);;
|
|
t @@ fun () -> not (equal Int.equal (Some 1) (Some 2));;
|
|
t @@ fun () -> equal Int.equal None None;;
|
|
t @@ fun () -> not (equal Int.equal None (Some 1));;
|
|
t @@ fun () -> not (equal Int.equal (Some 1) None);;
|
|
|
|
(* Test return and some *)
|
|
eq (Some 42) (return 42);;
|
|
eq (Some "hello") (some "hello");;
|
|
t @@ fun () -> return 5 = Some 5;;
|
|
|
|
(* Test none *)
|
|
t @@ fun () -> (none : int option) = None;;
|
|
|
|
(* Test flat_map / bind *)
|
|
eq (Some 2) (flat_map (fun x -> Some (x + 1)) (Some 1));;
|
|
eq None (flat_map (fun x -> Some (x + 1)) None);;
|
|
eq None (flat_map (fun _ -> None) (Some 1));;
|
|
|
|
eq (Some 2) (bind (Some 1) (fun x -> Some (x + 1)));;
|
|
eq None (bind None (fun x -> Some (x + 1)));;
|
|
|
|
(* Test flat_map_l *)
|
|
eq [1; 2; 3] (flat_map_l (fun x -> [x; x+1; x+2]) (Some 1));;
|
|
eq [] (flat_map_l (fun x -> [x; x+1]) None);;
|
|
|
|
(* Test map2 *)
|
|
eq (Some 5) (map2 ( + ) (Some 2) (Some 3));;
|
|
eq None (map2 ( + ) None (Some 3));;
|
|
eq None (map2 ( + ) (Some 2) None);;
|
|
eq None (map2 ( + ) None None);;
|
|
|
|
(* Test iter *)
|
|
t @@ fun () ->
|
|
let r = ref 0 in
|
|
iter (fun x -> r := x) (Some 42);
|
|
!r = 42
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
let r = ref 0 in
|
|
iter (fun x -> r := x) None;
|
|
!r = 0
|
|
;;
|
|
|
|
(* Test fold *)
|
|
eq 10 (fold (fun acc x -> acc + x) 5 (Some 5));;
|
|
eq 5 (fold (fun acc x -> acc + x) 5 None);;
|
|
|
|
(* Test if_ *)
|
|
eq (Some 5) (if_ (fun x -> x > 0) 5);;
|
|
eq None (if_ (fun x -> x > 0) (-5));;
|
|
eq (Some "hello") (if_ (fun s -> String.length s > 0) "hello");;
|
|
eq None (if_ (fun s -> String.length s > 0) "");;
|
|
|
|
(* Test exists *)
|
|
t @@ fun () -> exists (fun x -> x > 0) (Some 5);;
|
|
t @@ fun () -> not (exists (fun x -> x > 0) (Some (-5)));;
|
|
t @@ fun () -> not (exists (fun x -> x > 0) None);;
|
|
|
|
(* Test for_all *)
|
|
t @@ fun () -> for_all (fun x -> x > 0) (Some 5);;
|
|
t @@ fun () -> not (for_all (fun x -> x > 0) (Some (-5)));;
|
|
t @@ fun () -> for_all (fun x -> x > 0) None;;
|
|
|
|
(* Test get_or *)
|
|
eq 5 (get_or ~default:0 (Some 5));;
|
|
eq 0 (get_or ~default:0 None);;
|
|
|
|
(* Test value *)
|
|
eq 5 (value (Some 5) ~default:0);;
|
|
eq 0 (value None ~default:0);;
|
|
|
|
(* Test apply_or *)
|
|
eq 10 (apply_or (fun x -> Some (x * 2)) 5);;
|
|
t @@ fun () -> apply_or (fun x -> if x > 0 then Some (x * 2) else None) 5 = 10;;
|
|
t @@ fun () -> apply_or (fun x -> if x > 0 then Some (x * 2) else None) (-5) = -5;;
|
|
|
|
(* Test get_exn *)
|
|
eq 42 (get_exn (Some 42));;
|
|
|
|
t @@ fun () ->
|
|
try
|
|
ignore (get_exn None);
|
|
false
|
|
with Invalid_argument _ -> true
|
|
;;
|
|
|
|
(* Test get_lazy *)
|
|
eq 5 (get_lazy (fun () -> 0) (Some 5));;
|
|
eq 0 (get_lazy (fun () -> 0) None);;
|
|
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let _ = get_lazy (fun () -> called := true; 0) (Some 5) in
|
|
not !called
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let _ = get_lazy (fun () -> called := true; 0) None in
|
|
!called
|
|
;;
|
|
|
|
(* Test wrap *)
|
|
t @@ fun () ->
|
|
wrap (fun x -> x + 1) 5 = Some 6
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
wrap (fun _ -> failwith "error") () = None
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
wrap ~handler:(fun _ -> true) (fun x -> if x = 0 then failwith "div by zero" else 10 / x) 0 = None
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
wrap ~handler:(function Division_by_zero -> true | _ -> false)
|
|
(fun x -> 10 / x) 2 = Some 5
|
|
;;
|
|
|
|
(* Test wrap2 *)
|
|
t @@ fun () ->
|
|
wrap2 ( + ) 2 3 = Some 5
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
wrap2 (fun _ _ -> failwith "error") 1 2 = None
|
|
;;
|
|
|
|
(* Test pure *)
|
|
eq (Some 42) (pure 42);;
|
|
|
|
(* Test or_ *)
|
|
eq (Some 1) (or_ ~else_:(Some 2) (Some 1));;
|
|
eq (Some 2) (or_ ~else_:(Some 2) None);;
|
|
eq None (or_ ~else_:None None);;
|
|
|
|
(* Test or_lazy *)
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let result = or_lazy ~else_:(fun () -> called := true; Some 2) (Some 1) in
|
|
result = Some 1 && not !called
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let result = or_lazy ~else_:(fun () -> called := true; Some 2) None in
|
|
result = Some 2 && !called
|
|
;;
|
|
|
|
(* Test choice *)
|
|
eq (Some 1) (choice [Some 1; Some 2; Some 3]);;
|
|
eq (Some 2) (choice [None; Some 2; Some 3]);;
|
|
eq (Some 3) (choice [None; None; Some 3]);;
|
|
eq None (choice [None; None; None]);;
|
|
eq None (choice []);;
|
|
|
|
(* Test to_list *)
|
|
eq [42] (to_list (Some 42));;
|
|
eq [] (to_list None);;
|
|
|
|
(* Test of_list *)
|
|
eq (Some 1) (of_list [1]);;
|
|
eq (Some 1) (of_list [1; 2; 3]);;
|
|
eq None (of_list []);;
|
|
|
|
(* Test to_result *)
|
|
eq (Ok 5) (to_result "error" (Some 5));;
|
|
eq (Error "error") (to_result "error" None);;
|
|
|
|
(* Test to_result_lazy *)
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let result = to_result_lazy (fun () -> called := true; "error") (Some 5) in
|
|
result = Ok 5 && not !called
|
|
;;
|
|
|
|
t @@ fun () ->
|
|
let called = ref false in
|
|
let result = to_result_lazy (fun () -> called := true; "error") None in
|
|
result = Error "error" && !called
|
|
;;
|
|
|
|
(* Test of_result *)
|
|
eq (Some 5) (of_result (Ok 5));;
|
|
eq None (of_result (Error "error"));;
|
|
|
|
(* Property-based tests *)
|
|
q Q.int (fun x ->
|
|
return x = Some x
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
is_some o = not (is_none o)
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
map CCFun.id o = o
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
flat_map return o = o
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
bind o return = o
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
equal Int.equal o o
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
compare Int.compare o o = 0
|
|
);;
|
|
|
|
q Q.(pair (option int) int) (fun (o, default) ->
|
|
let v = get_or ~default o in
|
|
match o with
|
|
| Some x -> v = x
|
|
| None -> v = default
|
|
);;
|
|
|
|
q Q.int (fun x ->
|
|
to_list (Some x) = [x]
|
|
);;
|
|
|
|
q Q.(list int) (fun l ->
|
|
match of_list l with
|
|
| Some x -> List.mem x l
|
|
| None -> l = []
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
match o with
|
|
| Some x -> of_list (to_list o) = Some x
|
|
| None -> of_list (to_list o) = None
|
|
);;
|
|
|
|
q Q.(option int) (fun o ->
|
|
of_result (to_result "err" o) = o
|
|
);;
|
|
|
|
q Q.int (fun x ->
|
|
let o1 = Some x in
|
|
let o2 = Some x in
|
|
or_ ~else_:o2 o1 = o1
|
|
);;
|
|
|
|
q Q.int (fun x ->
|
|
or_ ~else_:(Some x) None = Some x
|
|
);;
|
|
|
|
q Q.(pair (option int) (option int)) (fun (o1, o2) ->
|
|
match choice [o1; o2] with
|
|
| Some _ -> is_some o1 || is_some o2
|
|
| None -> is_none o1 && is_none o2
|
|
);;
|